diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-15 18:47:53 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-15 18:47:53 +0800 |
| commit | 2c7a437b066ad243a21af6d2c1ce1550e467f5f5 (patch) | |
| tree | 5db730f98bad8058bdaf798e0dbcd8292e19978e /backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp | |
| parent | 32a365a2dc0096b4421fb3947b32d971b7f34c40 (diff) | |
| download | rcc-project-2c7a437b066ad243a21af6d2c1ce1550e467f5f5.tar.gz rcc-project-2c7a437b066ad243a21af6d2c1ce1550e467f5f5.tar.xz | |
[GlobalISel] Lower floating-point conversion libcalls
Diffstat (limited to 'backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp')
| -rw-r--r-- | backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp | 133 |
1 files changed, 91 insertions, 42 deletions
diff --git a/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp index b0c22fc..050de5b 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVCallLowering.cpp @@ -801,28 +801,92 @@ createMemoryOperand(MachineFunction &Function, MemoryAccessFlags Accesses, std:: return Function.createMemOperand(std::move(Description)); } -[[nodiscard]] Expected<void> emitCCCopy(MachineIRBuilder &Builder, Register Destination, - Register Source, CallValueTransform Transform) { - const Opcode CopyOpcode = Transform == CallValueTransform::Full - ? opcode(GenericOpcode::COPY) - : instructionOpcode(InstructionOpcode::PseudoCC_COPY); - auto Instruction = Builder.buildInstr(CopyOpcode); - if (!Instruction) - return std::unexpected(Instruction.error()); - auto Def = Instruction->addDef(Destination); - if (!Def) - return std::unexpected(Def.error()); - auto Use = Instruction->addUse(Source); - if (!Use) - return std::unexpected(Use.error()); - if (Transform != CallValueTransform::Full) { - auto Action = Instruction->addImmediate(static_cast<std::int64_t>(Transform)); - if (!Action) - return std::unexpected(Action.error()); +[[nodiscard]] Expected<Register> extendOutgoingRegister(MachineIRBuilder &Builder, Register Source, + const CCAssignment &Assignment) { + const std::uint32_t ValueWidth = Assignment.ValueType.scalarBitWidth(); + const std::uint32_t LocationWidth = Assignment.LocationType.scalarBitWidth(); + if (ValueWidth == LocationWidth) + return Source; + if (ValueWidth > LocationWidth) { + return makeUnexpected(ErrorCode::VerificationError, + "RISC-V ABI register assignment narrows an outgoing value"); + } + + auto Extended = Builder.function().registerInfo().createVirtualRegister(Assignment.LocationType); + if (!Extended) + return std::unexpected(Extended.error()); + + Expected<MachineInstr *> Built = makeUnexpected( + ErrorCode::InternalError, "RISC-V ABI outgoing register extension was not initialized"); + switch (outgoingTransform(Assignment)) { + case CallValueTransform::AnyExtend: + case CallValueTransform::Bitcast: + Built = Builder.buildAnyExt(*Extended, Source); + break; + case CallValueTransform::SignExtend: + Built = Builder.buildSExt(*Extended, Source); + break; + case CallValueTransform::ZeroExtend: + Built = Builder.buildZExt(*Extended, Source); + break; + case CallValueTransform::Full: + case CallValueTransform::Truncate: + return makeUnexpected(ErrorCode::VerificationError, + "RISC-V ABI outgoing register assignment lacks an extension transform"); } - auto Built = Instruction->build(); if (!Built) return std::unexpected(Built.error()); + return *Extended; +} + +[[nodiscard]] Expected<void> emitOutgoingRegisterAssignment(MachineIRBuilder &Builder, + const CCAssignment &Assignment, + Register Source) { + if (!Assignment.LocationRegister) { + return makeUnexpected(ErrorCode::InternalError, + "RISC-V register assignment has no location register"); + } + auto Extended = extendOutgoingRegister(Builder, Source, Assignment); + if (!Extended) + return std::unexpected(Extended.error()); + auto Copy = Builder.buildCopy(Register::fromPhysical(*Assignment.LocationRegister), *Extended); + if (!Copy) + return std::unexpected(Copy.error()); + return {}; +} + +[[nodiscard]] Expected<void> emitIncomingRegisterAssignment(MachineIRBuilder &Builder, + const CCAssignment &Assignment) { + if (!Assignment.LocationRegister) { + return makeUnexpected(ErrorCode::InternalError, + "RISC-V register assignment has no location register"); + } + + const std::uint32_t ValueWidth = Assignment.ValueType.scalarBitWidth(); + const std::uint32_t LocationWidth = Assignment.LocationType.scalarBitWidth(); + if (ValueWidth == LocationWidth) { + auto Copy = Builder.buildCopy(Assignment.OriginalValue, + Register::fromPhysical(*Assignment.LocationRegister)); + if (!Copy) + return std::unexpected(Copy.error()); + return {}; + } + if (ValueWidth > LocationWidth) { + return makeUnexpected(ErrorCode::VerificationError, + "RISC-V ABI register assignment widens an incoming value"); + } + + auto LocationValue = + Builder.function().registerInfo().createVirtualRegister(Assignment.LocationType); + if (!LocationValue) + return std::unexpected(LocationValue.error()); + auto Copy = + Builder.buildCopy(*LocationValue, Register::fromPhysical(*Assignment.LocationRegister)); + if (!Copy) + return std::unexpected(Copy.error()); + auto Truncation = Builder.buildTrunc(Assignment.OriginalValue, *LocationValue); + if (!Truncation) + return std::unexpected(Truncation.error()); return {}; } @@ -970,15 +1034,10 @@ createMemoryOperand(MachineFunction &Function, MemoryAccessFlags Accesses, std:: [[nodiscard]] Expected<void> verifyRequiredOpcodes(const MachineIRBuilder &Builder) { static constexpr std::array Required{ - InstructionOpcode::PseudoCC_COPY, - InstructionOpcode::PseudoLOAD_STACK_ARG, - InstructionOpcode::PseudoSTORE_STACK_ARG, - InstructionOpcode::PseudoBYVAL_COPY, - InstructionOpcode::ADJCALLSTACKDOWN, - InstructionOpcode::ADJCALLSTACKUP, - InstructionOpcode::PseudoCALL, - InstructionOpcode::PseudoTAIL, - InstructionOpcode::PseudoRET, + InstructionOpcode::PseudoLOAD_STACK_ARG, InstructionOpcode::PseudoSTORE_STACK_ARG, + InstructionOpcode::PseudoBYVAL_COPY, InstructionOpcode::ADJCALLSTACKDOWN, + InstructionOpcode::ADJCALLSTACKUP, InstructionOpcode::PseudoCALL, + InstructionOpcode::PseudoTAIL, InstructionOpcode::PseudoRET, }; for (const InstructionOpcode OpcodeValue : Required) { if (Builder.target().instructionDescriptor(instructionOpcode(OpcodeValue)) == nullptr) { @@ -1085,8 +1144,7 @@ createMemoryOperand(MachineFunction &Function, MemoryAccessFlags Accesses, std:: auto BlockLiveIn = ensureBlockLiveIn(Entry, Location); if (!BlockLiveIn) return std::unexpected(BlockLiveIn.error()); - auto Copy = emitCCCopy(Builder, Assignment.OriginalValue, Register::fromPhysical(Location), - incomingTransform(Assignment)); + auto Copy = emitIncomingRegisterAssignment(Builder, Assignment); if (!Copy) return std::unexpected(Copy.error()); continue; @@ -1296,8 +1354,7 @@ emitOutgoingArguments(MachineIRBuilder &Builder, const CallLoweringPlan &Plan, const Register Source = Replacement == Replacements.end() ? Assignment.OriginalValue : Replacement->second; if (Assignment.LocationRegister) { - auto Copy = emitCCCopy(Builder, Register::fromPhysical(*Assignment.LocationRegister), Source, - outgoingTransform(Assignment)); + auto Copy = emitOutgoingRegisterAssignment(Builder, Assignment, Source); if (!Copy) return std::unexpected(Copy.error()); continue; @@ -1422,11 +1479,7 @@ emitOutgoingArguments(MachineIRBuilder &Builder, const CallLoweringPlan &Plan, } if (Plan.tailDecision() == TailCallKind::NotTail) { for (const CCAssignment &Assignment : Plan.returnAssignments()) { - auto Location = requiredLocationRegister(Assignment); - if (!Location) - return std::unexpected(Location.error()); - auto Copy = emitCCCopy(Builder, Assignment.OriginalValue, Register::fromPhysical(*Location), - incomingTransform(Assignment)); + auto Copy = emitIncomingRegisterAssignment(Builder, Assignment); if (!Copy) return std::unexpected(Copy.error()); } @@ -1453,11 +1506,7 @@ emitOutgoingArguments(MachineIRBuilder &Builder, const CallLoweringPlan &Plan, [[nodiscard]] Expected<void> emitReturn(MachineIRBuilder &Builder, const CallLoweringPlan &Plan) { for (const CCAssignment &Assignment : Plan.returnAssignments()) { - auto Location = requiredLocationRegister(Assignment); - if (!Location) - return std::unexpected(Location.error()); - auto Copy = emitCCCopy(Builder, Register::fromPhysical(*Location), Assignment.OriginalValue, - outgoingTransform(Assignment)); + auto Copy = emitOutgoingRegisterAssignment(Builder, Assignment, Assignment.OriginalValue); if (!Copy) return std::unexpected(Copy.error()); } |
