diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 23:44:57 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 23:44:57 +0800 |
| commit | e6cd1347cc2c76babe56842e1b7bd05d68fe9584 (patch) | |
| tree | d00769b50841cbcea907b76ac006b366147325dc /backend/lib/Target/RISCV/RISCVCallLowering.cpp | |
| parent | 234d7d3bec020103e46daaff39d207d978479730 (diff) | |
| download | rcc-project-e6cd1347cc2c76babe56842e1b7bd05d68fe9584.tar.gz rcc-project-e6cd1347cc2c76babe56842e1b7bd05d68fe9584.tar.xz | |
[RISCV] Model typed floating-point register views
Diffstat (limited to 'backend/lib/Target/RISCV/RISCVCallLowering.cpp')
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVCallLowering.cpp | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/backend/lib/Target/RISCV/RISCVCallLowering.cpp b/backend/lib/Target/RISCV/RISCVCallLowering.cpp index 60bf6f2..5da3fc8 100644 --- a/backend/lib/Target/RISCV/RISCVCallLowering.cpp +++ b/backend/lib/Target/RISCV/RISCVCallLowering.cpp @@ -70,6 +70,26 @@ constexpr std::uint32_t AllowedDirectCallFlags = (*Semantics == FloatSemantics::IEEESingle || *Semantics == FloatSemantics::IEEEDouble); } +[[nodiscard]] Expected<PhysicalRegister> floatingRegisterView(PhysicalRegister DoubleView, + LLT Type) { + if (!isSupportedFloat(Type)) { + return makeUnexpected(ErrorCode::InvalidArgument, + "RISC-V floating-register view requires f32 or f64"); + } + if (Type.scalarBitWidth() == 64) + return DoubleView; + + constexpr std::uint32_t FirstDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F0_D); + constexpr std::uint32_t LastDouble = static_cast<std::uint32_t>(PhysicalRegisterID::F31_D); + constexpr std::uint32_t FirstSingle = static_cast<std::uint32_t>(PhysicalRegisterID::F0_F); + const std::uint32_t Number = DoubleView.number(); + if (Number < FirstDouble || Number > LastDouble) { + return makeUnexpected(ErrorCode::InternalError, + "RISC-V ABI floating register is not an FPR64 view"); + } + return PhysicalRegister::create(FirstSingle + Number - FirstDouble); +} + [[nodiscard]] bool requiresIntegerTransport(const ABIValue &Value) noexcept { return !isSupportedFloat(Value.Type) || Value.Flags.has(ABIValueFlag::ByVal) || Value.Flags.has(ABIValueFlag::StructReturn) || Value.Flags.has(ABIValueFlag::Indirect); @@ -301,14 +321,19 @@ assignArguments(std::span<const ABIValue> Values, std::size_t FixedArgumentCount if (CanUsePreferredAggregate) { for (std::size_t Fragment = 0; Fragment < GroupSize; ++Fragment) { const ABIValue &Value = Values[Index + Fragment]; - Expected<CCAssignment> Assignment = - requiresIntegerTransport(Value) - ? registerAssignment(Value, Index + Fragment, - Convention.IntegerArgumentRegisters[State.GPR++], *I64, false, - false) - : registerAssignment(Value, Index + Fragment, - Convention.FloatingArgumentRegisters[State.FPR++], Value.Type, - false, false); + Expected<CCAssignment> Assignment = makeUnexpected( + ErrorCode::InternalError, "RISC-V ABI argument assignment was not initialized"); + if (requiresIntegerTransport(Value)) { + Assignment = registerAssignment(Value, Index + Fragment, + Convention.IntegerArgumentRegisters[State.GPR++], *I64, + false, false); + } else { + auto View = + floatingRegisterView(Convention.FloatingArgumentRegisters[State.FPR++], Value.Type); + if (!View) + return std::unexpected(View.error()); + Assignment = registerAssignment(Value, Index + Fragment, *View, Value.Type, false, false); + } if (!Assignment) return std::unexpected(Assignment.error()); Result.Assignments.push_back(*Assignment); @@ -413,8 +438,10 @@ assignReturns(std::span<const ABIValue> Values, bool RequireRegisters, Expected<CCAssignment> Assignment = makeUnexpected( ErrorCode::Unsupported, "RISC-V calling convention has no return register available"); if (UseFloatingRegister) { - Assignment = registerAssignment(Value, Index, Convention.FloatingReturnRegisters[FPR++], - Value.Type, false, false); + auto View = floatingRegisterView(Convention.FloatingReturnRegisters[FPR++], Value.Type); + if (!View) + return std::unexpected(View.error()); + Assignment = registerAssignment(Value, Index, *View, Value.Type, false, false); } else if (GPR < Convention.IntegerReturnRegisters.size()) { Assignment = registerAssignment(Value, Index, Convention.IntegerReturnRegisters[GPR++], *I64, false, isSupportedFloat(Value.Type)); |
