https://github.com/LunaTheFoxgirl updated https://github.com/llvm/llvm-project/pull/223990
>From 51404516227ebe3faceaef9f01afce05dff58b2f Mon Sep 17 00:00:00 2001 From: LunaTheFoxgirl <[email protected]> Date: Fri, 5 Jun 2026 07:07:15 +0200 Subject: [PATCH 1/4] Add o64 ABI to MIPS --- clang/lib/Basic/Targets/Mips.cpp | 11 +++++++--- clang/lib/Basic/Targets/Mips.h | 22 +++++++++++++++++-- .../Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 15 +++++++++++-- .../Target/Mips/MCTargetDesc/MipsABIInfo.h | 7 ++++-- .../Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 4 ++-- llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 22 +++++++++++++++---- llvm/lib/Target/Mips/MipsSubtarget.cpp | 5 +++-- llvm/lib/Target/Mips/MipsSubtarget.h | 1 + llvm/lib/TargetParser/TargetDataLayout.cpp | 8 ++++--- 9 files changed, 75 insertions(+), 20 deletions(-) diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index 76c90815670531..2531aa0074d065 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -112,6 +112,10 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__mips_o32"); Builder.defineMacro("_ABIO32", "1"); Builder.defineMacro("_MIPS_SIM", "_ABIO32"); + } else if (ABI == "o64") { + Builder.defineMacro("__mips_o64"); + Builder.defineMacro("_ABIO64", "4"); + Builder.defineMacro("_MIPS_SIM", "_ABIO64"); } else if (ABI == "n32") { Builder.defineMacro("__mips_n32"); Builder.defineMacro("_ABIN32", "2"); @@ -219,7 +223,7 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts, // found in 64-bit processors. In the case of O32 on a 64-bit processor, // the instructions exist but using them violates the ABI since they // require 64-bit GPRs and O32 only supports 32-bit GPRs. - if (ABI == "n32" || ABI == "n64") + if (ABI == "o64" || ABI == "n32" || ABI == "n64") Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } @@ -241,6 +245,7 @@ MipsTargetInfo::getTargetBuiltins() const { unsigned MipsTargetInfo::getUnwindWordWidth() const { return llvm::StringSwitch<unsigned>(ABI) .Case("o32", 32) + .Case("o64", 64) .Case("n32", 64) .Case("n64", 64) .Default(getPointerWidth(LangAS::Default)); @@ -254,7 +259,7 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { } // 64-bit ABI's require 64-bit CPU's. - if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) { + if (!processorSupportsGPR64() && (ABI == "o64" || ABI == "n32" || ABI == "n64")) { Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU; return false; } @@ -297,7 +302,7 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { } // Option -mmsa permitted on Mips32 iff revision 2 or higher is present if (HasMSA && (CPU == "mips1" || CPU == "mips2" || getISARev() < 2) && - ABI == "o32") { + (ABI == "o32" || ABI == "o64")) { Diags.Report(diag::err_mips_fp64_req) << "-mmsa"; return false; } diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 4c09390c3c6d5f..43907b34621169 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -90,6 +90,11 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { ABI = Name; return true; } + if (Name == "o64") { + setO64ABITypes(); + ABI = Name; + return true; + } if (Name == "n32") { setN32ABITypes(); @@ -117,6 +122,19 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { SuitableAlign = 64; } + void setO64ABITypes() { + Int64Type = SignedLongLong; + IntMaxType = Int64Type; + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + LongDoubleWidth = LongDoubleAlign = 128; + LongWidth = LongAlign = 64; + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + PointerWidth = PointerAlign = 64; + PtrDiffType = IntPtrType = SignedLong; + SizeType = UnsignedLong; + SuitableAlign = 128; + } + void setN32N64ABITypes() { LongDoubleWidth = LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); @@ -416,13 +434,13 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, {{"ra"}, "$31"} }; - if (ABI == "o32") + if (ABI == "o64" || ABI == "o32") return llvm::ArrayRef(O32RegAliases); return llvm::ArrayRef(NewABIRegAliases); } bool hasInt128Type() const override { - return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; + return (ABI == "o64" || ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; } unsigned getUnwindWordWidth() const override; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 59c8e7c72224ef..281522d66ff3fb 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -27,6 +27,7 @@ cl::opt<bool> namespace { static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; +static const MCPhysReg O64IntRegs[4] = {Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64}; static const MCPhysReg Mips64IntRegs[8] = { Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64, @@ -36,6 +37,8 @@ static const MCPhysReg Mips64IntRegs[8] = { ArrayRef<MCPhysReg> MipsABIInfo::GetByValArgRegs() const { if (IsO32()) return ArrayRef(O32IntRegs); + if (IsO64()) + return ArrayRef(O64IntRegs); if (IsN32() || IsN64()) return ArrayRef(Mips64IntRegs); llvm_unreachable("Unhandled ABI"); @@ -48,13 +51,19 @@ ArrayRef<MCPhysReg> MipsABIInfo::getVarArgRegs(bool isGP64bit) const { else return ArrayRef(O32IntRegs); } + if (IsO64()) { + if (isGP64bit) + return ArrayRef(Mips64IntRegs); + else + return ArrayRef(O64IntRegs); + } if (IsN32() || IsN64()) return ArrayRef(Mips64IntRegs); llvm_unreachable("Unhandled ABI"); } unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { - if (IsO32()) + if (IsO32() || IsO64()) return CC != CallingConv::Fast ? 16 : 0; if (IsN32() || IsN64()) return 0; @@ -63,6 +72,8 @@ unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef ABIName) { if (ABIName.starts_with("o32")) + return MipsABIInfo::O64(); + if (ABIName.starts_with("o64")) return MipsABIInfo::O32(); if (ABIName.starts_with("n32")) return MipsABIInfo::N32(); @@ -129,5 +140,5 @@ unsigned MipsABIInfo::GetEhDataReg(unsigned I) const { Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64 }; - return IsN64() ? EhDataReg64[I] : EhDataReg[I]; + return (IsABI64()) ? EhDataReg64[I] : EhDataReg[I]; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index d8003d2fcc1648..e1ce417c228a4e 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -21,7 +21,7 @@ class StringRef; class MipsABIInfo { public: - enum class ABI { Unknown, O32, N32, N64 }; + enum class ABI { Unknown, O32, O64, N32, N64 }; protected: ABI ThisABI; @@ -31,14 +31,17 @@ class MipsABIInfo { static MipsABIInfo Unknown() { return MipsABIInfo(ABI::Unknown); } static MipsABIInfo O32() { return MipsABIInfo(ABI::O32); } + static MipsABIInfo O64() { return MipsABIInfo(ABI::O64); } static MipsABIInfo N32() { return MipsABIInfo(ABI::N32); } static MipsABIInfo N64() { return MipsABIInfo(ABI::N64); } static MipsABIInfo computeTargetABI(const Triple &TT, StringRef ABIName); bool IsKnown() const { return ThisABI != ABI::Unknown; } bool IsO32() const { return ThisABI == ABI::O32; } + bool IsO64() const { return ThisABI == ABI::O64; } bool IsN32() const { return ThisABI == ABI::N32; } bool IsN64() const { return ThisABI == ABI::N64; } + bool IsABI64() const { return ThisABI == ABI::N64 || ThisABI == ABI::O64; } ABI GetEnumValue() const { return ThisABI; } /// The registers to use for byval arguments. @@ -69,7 +72,7 @@ class MipsABIInfo { unsigned GetPtrSubuOp() const; unsigned GetPtrAndOp() const; unsigned GetGPRMoveOp() const; - inline bool ArePtrs64bit() const { return IsN64(); } + inline bool ArePtrs64bit() const { return IsO64() || IsN64(); } inline bool AreGprs64bit() const { return IsN32() || IsN64(); } unsigned GetEhDataReg(unsigned I) const; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index dbb0af75f3651d..762595ab323cd6 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -28,10 +28,10 @@ MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple, MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TheTriple, Options.getABIName()); - if (TheTriple.isMIPS64() && !ABI.IsN32()) + if (TheTriple.isMIPS64() && !(ABI.IsN32() || ABI.IsO64())) CodePointerSize = CalleeSaveStackSlotSize = 8; - if (ABI.IsO32()) + if (ABI.IsO32() || ABI.IsO64()) InternalSymbolPrefix = "$"; else if (ABI.IsN32() || ABI.IsN64()) InternalSymbolPrefix = ".L"; diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp index 948d4db8585db7..540e2f67b80551 100644 --- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -106,16 +106,30 @@ MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { } // O32 ABI + if (Subtarget.isABI_O32()) { + if (Subtarget.isSingleFloat()) + return CSR_O32_SingleFloat_SaveList; + + if (Subtarget.isFP64bit()) + return CSR_O32_FP64_SaveList; + + if (Subtarget.isFPXX()) + return CSR_O32_FPXX_SaveList; + + return CSR_O32_SaveList; + } + + // O64 ABI if (Subtarget.isSingleFloat()) - return CSR_O32_SingleFloat_SaveList; + return CSR_O64_SingleFloat_SaveList; if (Subtarget.isFP64bit()) - return CSR_O32_FP64_SaveList; + return CSR_O64_FP64_SaveList; if (Subtarget.isFPXX()) - return CSR_O32_FPXX_SaveList; + return CSR_O64_FPXX_SaveList; - return CSR_O32_SaveList; + return CSR_O64_SaveList; } const uint32_t * diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 287a4cbbf5af4b..356601c33f6506 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -265,14 +265,14 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, if (StackAlignOverride) stackAlignment = *StackAlignOverride; - else if (isABI_N32() || isABI_N64()) + else if (isABI_O64() || isABI_N32() || isABI_N64()) stackAlignment = Align(16); else { assert(isABI_O32() && "Unknown ABI for stack alignment!"); stackAlignment = Align(8); } - if ((isABI_N32() || isABI_N64()) && !isGP64bit()) + if ((isABI_O64() || isABI_N32() || isABI_N64()) && !isGP64bit()) reportFatalUsageError("64-bit code requested on a subtarget that doesn't " "support it!"); @@ -292,6 +292,7 @@ Reloc::Model MipsSubtarget::getRelocationModel() const { bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); } bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); } bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); } +bool MipsSubtarget::isABI_O64() const { return getABI().IsO64(); } const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); } const SelectionDAGTargetInfo *MipsSubtarget::getSelectionDAGInfo() const { diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 3acfaa82965ab7..dcd9420d69940d 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -249,6 +249,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo { bool isABI_N64() const; bool isABI_N32() const; bool isABI_O32() const; + bool isABI_O64() const; const MipsABIInfo &getABI() const; bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index a2125eeb829324..49668a47a71cb2 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -151,7 +151,7 @@ static std::string computeM68kDataLayout(const Triple &TT) { } namespace { -enum class MipsABI { Unknown, O32, N32, N64 }; +enum class MipsABI { Unknown, O32, O64, N32, N64 }; } // FIXME: This duplicates MipsABIInfo::computeTargetABI, but duplicating this is @@ -161,6 +161,8 @@ enum class MipsABI { Unknown, O32, N32, N64 }; static MipsABI getMipsABI(const Triple &TT, StringRef ABIName) { if (ABIName.starts_with("o32")) return MipsABI::O32; + if (ABIName.starts_with("o64")) + return MipsABI::O64; if (ABIName.starts_with("n32")) return MipsABI::N32; if (ABIName.starts_with("n64")) @@ -184,7 +186,7 @@ static std::string computeMipsDataLayout(const Triple &TT, StringRef ABIName) { else Ret += "E"; - if (ABI == MipsABI::O32) + if (ABI == MipsABI::O32 || ABI == MipsABI::O64) Ret += "-m:m"; else Ret += "-m:e"; @@ -200,7 +202,7 @@ static std::string computeMipsDataLayout(const Triple &TT, StringRef ABIName) { // 32 bit registers are always available and the stack is at least 64 bit // aligned. On N64 64 bit registers are also available and the stack is // 128 bit aligned. - if (ABI == MipsABI::N64 || ABI == MipsABI::N32) + if (ABI == MipsABI::O64 || ABI == MipsABI::N64 || ABI == MipsABI::N32) Ret += "-i128:128-n32:64-S128"; else Ret += "-n32-S64"; >From 78edbe46ff9f2a21a4bb472bc849297ed833aa9a Mon Sep 17 00:00:00 2001 From: LunaTheFoxgirl <[email protected]> Date: Wed, 16 Sep 2026 13:59:14 +0200 Subject: [PATCH 2/4] Implement more of O64 ABI --- .../Target/Mips/AsmParser/MipsAsmParser.cpp | 2 + .../Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 4 +- llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 1 + llvm/lib/Target/Mips/MipsCallingConv.td | 53 ++++++ llvm/lib/Target/Mips/MipsFastISel.cpp | 17 ++ llvm/lib/Target/Mips/MipsISelLowering.cpp | 153 ++++++++++++++++++ llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 27 ++-- llvm/lib/Target/Mips/MipsSubtarget.cpp | 4 +- llvm/lib/TargetParser/TargetDataLayout.cpp | 2 +- 9 files changed, 245 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 928bd03b57c60b..17234925199f22 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -12,6 +12,7 @@ #include "MCTargetDesc/MipsMCAsmInfo.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MCTargetDesc/MipsTargetStreamer.h" +#include "MipsRegisterInfo.h" #include "TargetInfo/MipsTargetInfo.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" @@ -598,6 +599,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool isABI_N32() const { return ABI.IsN32(); } bool isABI_N64() const { return ABI.IsN64(); } bool isABI_O32() const { return ABI.IsO32(); } + bool isABI_O64() const { return ABI.IsO64(); } bool isABI_FPXX() const { return getSTI().hasFeature(Mips::FeatureFPXX); } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 281522d66ff3fb..c9b24fb9593870 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -72,9 +72,9 @@ unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef ABIName) { if (ABIName.starts_with("o32")) - return MipsABIInfo::O64(); - if (ABIName.starts_with("o64")) return MipsABIInfo::O32(); + if (ABIName.starts_with("o64")) + return MipsABIInfo::O64(); if (ABIName.starts_with("n32")) return MipsABIInfo::N32(); if (ABIName.starts_with("n64")) diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 715b96e52e6c82..5411d226a99cfd 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -386,6 +386,7 @@ void MipsAsmPrinter::emitFrameDirective() { const char *MipsAsmPrinter::getCurrentABIString() const { switch (static_cast<MipsTargetMachine &>(TM).getABI().GetEnumValue()) { case MipsABIInfo::ABI::O32: return "abi32"; + case MipsABIInfo::ABI::O64: return "abiO64"; case MipsABIInfo::ABI::N32: return "abiN32"; case MipsABIInfo::ABI::N64: return "abi64"; default: llvm_unreachable("Unknown Mips ABI"); diff --git a/llvm/lib/Target/Mips/MipsCallingConv.td b/llvm/lib/Target/Mips/MipsCallingConv.td index 748162525b0915..dc39cf08ac9b36 100644 --- a/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/llvm/lib/Target/Mips/MipsCallingConv.td @@ -107,6 +107,49 @@ def CC_MipsO32_FP : CallingConv<[ CCIfSubtarget<"isFP64bit()", CCDelegateTo<CC_MipsO32_FP64>> ]>; +//===----------------------------------------------------------------------===// +// Mips O64 Calling Convention +//===----------------------------------------------------------------------===// + +def CC_MipsO64 : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i1, i8, i16], CCPromoteToType<i32>>, + + // Integer values get stored in stack slots that are 4 bytes in + // size and 8-byte aligned. + CCIfType<[i32, f32], CCAssignToStack<4, 8>>, + + // Integer values get stored in stack slots that are 8 bytes in + // size and 8-byte aligned. + CCIfType<[i64, f64], CCAssignToStack<8, 8>> +]>; + +// Only the return rules are defined here for O64. The rules for argument +// passing are defined in MipsISelLowering.cpp. +def RetCC_MipsO64 : CallingConv<[ + // Promote i1/i8/i16 return values to i32. + CCIfType<[i1, i8, i16], CCPromoteToType<i32>>, + + // i64 are returned in registers V0, V1, A0, A1, unless the original return + // type was a vector of floats. + CCIfOrigArgWasNotVectorFloat<CCIfType<[i64], + CCAssignToReg<[V0_64, V1_64, A0_64, A1_64]>>>, + + // f32 are returned in registers F12, F13 + CCIfType<[f32], CCAssignToReg<[F12, F13]>>, + + // f64 are returned in registers D12, D13 + CCIfType<[f64], CCAssignToReg<[D12_64, D13_64]>>, +]>; + +def CC_MipsO64_FP32 : CustomCallingConv; +def CC_MipsO64_FP64 : CustomCallingConv; + +def CC_MipsO64_FP : CallingConv<[ + CCIfSubtargetNot<"isFP64bit()", CCDelegateTo<CC_MipsO64_FP32>>, + CCIfSubtarget<"isFP64bit()", CCDelegateTo<CC_MipsO64_FP64>> +]>; + //===----------------------------------------------------------------------===// // Mips N32/64 Calling Convention //===----------------------------------------------------------------------===// @@ -284,11 +327,13 @@ def CC_Mips_FastCC : CallingConv<[ def RetCC_Mips : CallingConv<[ CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>, CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>, + CCIfSubtarget<"isABI_O64()", CCDelegateTo<RetCC_MipsO64>>, CCDelegateTo<RetCC_MipsO32> ]>; def CC_Mips_ByVal : CallingConv<[ CCIfSubtarget<"isABI_O32()", CCIfByVal<CCPassByVal<4, 4>>>, + CCIfSubtarget<"isABI_O64()", CCIfByVal<CCPassByVal<4, 8>>>, CCIfByVal<CCPassByVal<8, 8>> ]>; @@ -325,6 +370,7 @@ def CC_Mips_FixedArg : CallingConv<[ CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_Mips_FastCC>>, CCIfSubtarget<"isABI_O32()", CCIfSubtargetNot<"isGP64bit()", CCDelegateTo<CC_MipsO32_FP>>>, + CCIfSubtarget<"isABI_O64()", CCDelegateTo<CC_MipsO64_FP>>, CCDelegateTo<CC_MipsN> ]>; @@ -332,6 +378,7 @@ def CC_Mips_VarArg : CallingConv<[ CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>, CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>, + CCIfSubtarget<"isABI_O64()", CCDelegateTo<CC_MipsO64_FP>>, CCDelegateTo<CC_MipsN_VarArg> ]>; @@ -359,6 +406,12 @@ def CSR_O32_FP64 : CalleeSavedRegs<(add (decimate (sequence "D%u_64", 30, 20), 2), RA, FP, (sequence "S%u", 7, 0))>; +def CSR_O64 : CalleeSavedRegs<(add (sequence "D%u_64", 15, 10), RA_64, FP_64, + (sequence "S%u_64", 7, 0))>; + +def CSR_O64_SingleFloat : CalleeSavedRegs<(add(sequence "F%u", 31, 20), RA_64, FP_64, + (sequence "S%u_64", 7, 0))>; + def CSR_N32 : CalleeSavedRegs<(add(decimate(sequence "D%u_64", 30, 20), 2), RA_64, FP_64, GP_64, (sequence "S%u_64", 7, 0))>; diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp index 9645fb5293609c..0d2b0756c3ceca 100644 --- a/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -285,9 +285,26 @@ static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, llvm_unreachable("should not be called"); } + +static bool CC_MipsO64_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, Type *OrigTy, + CCState &State) { + llvm_unreachable("should not be called"); +} + +static bool CC_MipsO64_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, Type *OrigTy, + CCState &State) { + llvm_unreachable("should not be called"); +} + #include "MipsGenCallingConv.inc" CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { + if (getABI().IsO64()) + return CC_MipsO64; return CC_MipsO32; } diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 298b525e48cffb..ac4aa085440e95 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -3138,6 +3138,158 @@ static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State); +//===----------------------------------------------------------------------===// +// TODO: Implement a generic logic using tblgen that can support this. +// Mips O64 ABI rules: +// --- +// i64 - Passed in A0, A1, A2, A3 and stack +// f32 - Only passed in f32 registers if no int reg has been used yet to hold +// an argument. Otherwise, passed in A1, A2, A3 and stack. +// f64 - Only passed in two aliased f32 registers if no int reg has been used +// yet to hold an argument. Otherwise, use A2, A3 and stack. If A1 is +// not used, it must be shadowed. If only A3 is available, shadow it and +// go to stack. +// vXiX - Received as scalarized i32s, passed in A0 - A3 and the stack. +// vXf32 - Passed in either a pair of registers {A0, A1}, {A2, A3} or {A0 - A3} +// with the remainder spilled to the stack. +// vXf64 - Passed in either {A0, A1, A2, A3} or {A2, A3} and in both cases +// spilling the remainder to the stack. +// +// For vararg functions, all arguments are passed in A0, A1, A2, A3 and stack. +//===----------------------------------------------------------------------===// + +static bool CC_MipsO64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + Type *OrigTy, CCState &State, + ArrayRef<MCPhysReg> F64Regs) { + const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>( + State.getMachineFunction().getSubtarget()); + + static const MCPhysReg IntRegs[] = { Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64 }; + static const MCPhysReg Int32Regs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; + static const MCPhysReg FloatVectorIntRegs[] = { Mips::A0_64, Mips::A2_64 }; + + // Do not process byval args here. + if (ArgFlags.isByVal()) + return true; + + // Promote i8 and i16 + if (ArgFlags.isInReg() && !Subtarget.isLittle()) { + if (LocVT == MVT::i8 || LocVT == MVT::i16 || LocVT == MVT::i32) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExtUpper; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExtUpper; + else + LocInfo = CCValAssign::AExtUpper; + } + } + + // Promote i8, i16 + if (LocVT == MVT::i8 || LocVT == MVT::i16) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } + + unsigned Reg; + + // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following + // is true: function is vararg, argument is 3rd or higher, there is previous + // argument which is not f32 or f64. + bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || + State.getFirstUnallocated(F64Regs) != ValNo; + Align OrigAlign = ArgFlags.getNonZeroOrigAlign(); + bool isVectorFloat = OrigTy->isVectorTy() && OrigTy->isFPOrFPVectorTy(); + + // The MIPS vector ABI for floats passes them in a pair of registers + if (ValVT == MVT::i32 && isVectorFloat) { + // This is the start of an vector that was scalarized into an unknown number + // of components. It doesn't matter how many there are. Allocate one of the + // notional 8 byte aligned registers which map onto the argument stack, and + // shadow the register lost to alignment requirements. + if (ArgFlags.isSplit()) { + Reg = State.AllocateReg(FloatVectorIntRegs); + if (Reg == Mips::A2_64) + State.AllocateReg(Mips::A1_64); + else if (Reg == 0) + State.AllocateReg(Mips::A3_64); + } else { + // If we're an intermediate component of the split, we can just attempt to + // allocate a register directly. + Reg = State.AllocateReg(IntRegs); + } + } else if (ValVT == MVT::i32 || + (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { + Reg = State.AllocateReg(Int32Regs); + LocVT = MVT::i32; + } else if (ValVT == MVT::i64 || + (ValVT == MVT::f64 && AllocateFloatsInIntReg)) { + Reg = State.AllocateReg(IntRegs); + LocVT = MVT::i64; + } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { + // Allocate int register and shadow next int register. If first + // available register is Mips::A1 or Mips::A3, shadow it too. + Reg = State.AllocateReg(IntRegs); + if (Reg) { + LocVT = MVT::i64; + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return false; + } + } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { + // we are guaranteed to find an available float register + if (ValVT == MVT::f32) { + Reg = State.AllocateReg(F64Regs); + // Shadow int register + State.AllocateReg(IntRegs); + } else { + Reg = State.AllocateReg(F64Regs); + // Shadow int registers + State.AllocateReg(IntRegs); + } + } else + llvm_unreachable("Cannot handle this ValVT."); + + if (!Reg) { + unsigned Offset = State.AllocateStack(ValVT.getStoreSize(), OrigAlign); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + } else + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + + return false; +} + +static bool CC_MipsO64_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, Type *OrigTy, + CCState &State) { + static const MCPhysReg F64Regs[] = { Mips::D12_64, Mips::D13_64 }; + + return CC_MipsO64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, OrigTy, State, + F64Regs); +} + +static bool CC_MipsO64_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, Type *OrigTy, + CCState &State) { + static const MCPhysReg F64Regs[] = { Mips::D12_64, Mips::D13_64 }; + + return CC_MipsO64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, OrigTy, State, + F64Regs); +} + +[[maybe_unused]] static bool CC_MipsO64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, Type *OrigTy, + CCState &State); + + #include "MipsGenCallingConv.inc" CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{ @@ -3147,6 +3299,7 @@ static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{ return RetCC_Mips; } + //===----------------------------------------------------------------------===// // Call Calling Convention Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp index 540e2f67b80551..d75b050fa6a3b2 100644 --- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -123,12 +123,6 @@ MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { if (Subtarget.isSingleFloat()) return CSR_O64_SingleFloat_SaveList; - if (Subtarget.isFP64bit()) - return CSR_O64_FP64_SaveList; - - if (Subtarget.isFPXX()) - return CSR_O64_FPXX_SaveList; - return CSR_O64_SaveList; } @@ -153,16 +147,23 @@ MipsRegisterInfo::getCallPreservedMask(const MachineFunction &MF, } // O32 ABI - if (Subtarget.isSingleFloat()) - return CSR_O32_SingleFloat_RegMask; + if (Subtarget.isABI_O32()) { + if (Subtarget.isSingleFloat()) + return CSR_O32_SingleFloat_RegMask; - if (Subtarget.isFP64bit()) - return CSR_O32_FP64_RegMask; + if (Subtarget.isFP64bit()) + return CSR_O32_FP64_RegMask; - if (Subtarget.isFPXX()) - return CSR_O32_FPXX_RegMask; + if (Subtarget.isFPXX()) + return CSR_O32_FPXX_RegMask; + + return CSR_O32_RegMask; + } - return CSR_O32_RegMask; + // O64 ABI + if (Subtarget.isSingleFloat()) + return CSR_O64_SingleFloat_RegMask; + return CSR_O64_RegMask; } const uint32_t *MipsRegisterInfo::getMips16RetHelperMask() { diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 356601c33f6506..26cad4a7d52280 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -265,10 +265,10 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, if (StackAlignOverride) stackAlignment = *StackAlignOverride; - else if (isABI_O64() || isABI_N32() || isABI_N64()) + else if (isABI_N32() || isABI_N64()) stackAlignment = Align(16); else { - assert(isABI_O32() && "Unknown ABI for stack alignment!"); + assert((isABI_O32() || isABI_O64()) && "Unknown ABI for stack alignment!"); stackAlignment = Align(8); } diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index 49668a47a71cb2..89a37e753acd09 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -192,7 +192,7 @@ static std::string computeMipsDataLayout(const Triple &TT, StringRef ABIName) { Ret += "-m:e"; // Pointers are 32 bit on some ABIs. - if (ABI != MipsABI::N64) + if (ABI != MipsABI::N64 && ABI != MipsABI::O64) Ret += "-p:32:32"; // 8 and 16 bit integers only need to have natural alignment, but try to >From 5910c16fb634bed49f1277f3e13320dcf346b9b4 Mon Sep 17 00:00:00 2001 From: LunaTheFoxgirl <[email protected]> Date: Thu, 17 Sep 2026 20:57:15 +0200 Subject: [PATCH 3/4] Add R4300 proc and infra --- clang/lib/Basic/Targets/Mips.cpp | 7 +++--- clang/lib/Basic/Targets/Mips.h | 25 +++++++++++++++------- clang/lib/Driver/ToolChains/Arch/Mips.cpp | 4 ++++ llvm/lib/Target/Mips/Mips.td | 12 +++++++++-- llvm/lib/Target/Mips/MipsSubtarget.cpp | 1 + llvm/lib/Target/Mips/MipsSubtarget.h | 9 ++++++++ llvm/lib/Target/Mips/MipsTargetMachine.cpp | 2 +- llvm/lib/TargetParser/TargetDataLayout.cpp | 4 ++-- 8 files changed, 48 insertions(+), 16 deletions(-) diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index 2531aa0074d065..587ee4a5c2771b 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -46,6 +46,7 @@ bool MipsTargetInfo::processorSupportsGPR64() const { .Case("mips64r6", true) .Case("octeon", true) .Case("octeon+", true) + .Case("vr4300", true) .Case("r5900", true) .Case("i6400", true) .Case("i6500", true) @@ -56,8 +57,8 @@ static constexpr llvm::StringLiteral ValidCPUNames[] = { {"mips1"}, {"mips2"}, {"mips3"}, {"mips4"}, {"mips5"}, {"mips32"}, {"mips32r2"}, {"mips32r3"}, {"mips32r5"}, {"mips32r6"}, {"mips64"}, {"mips64r2"}, {"mips64r3"}, {"mips64r5"}, {"mips64r6"}, - {"octeon"}, {"octeon+"}, {"p5600"}, {"r5900"}, {"i6400"}, - {"i6500"}}; + {"octeon"}, {"octeon+"}, {"p5600"}, {"vr4300"}, {"r5900"}, + {"i6400"}, {"i6500"}}; bool MipsTargetInfo::isValidCPUName(StringRef Name) const { return llvm::is_contained(ValidCPUNames, Name); @@ -245,7 +246,7 @@ MipsTargetInfo::getTargetBuiltins() const { unsigned MipsTargetInfo::getUnwindWordWidth() const { return llvm::StringSwitch<unsigned>(ABI) .Case("o32", 32) - .Case("o64", 64) + .Case("o64", 32) .Case("n32", 64) .Case("n64", 64) .Default(getPointerWidth(LangAS::Default)); diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 7ba46fdf1adf68..b3ac848356cd4e 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -109,30 +109,39 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { return false; } + void setOABITypes() { + // TODO: OABI's long length can differ, find a way to do this and + // propagate to datalayout string. + + unsigned LongLength = 32; + LongWidth = LongAlign = LongLength; + PointerWidth = PointerAlign = LongLength; + } + void setO32ABITypes() { + setOABITypes(); + Int64Type = SignedLongLong; IntMaxType = Int64Type; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); LongDoubleWidth = LongDoubleAlign = 64; - LongWidth = LongAlign = 32; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; - PointerWidth = PointerAlign = 32; PtrDiffType = IntPtrType = SignedInt; SizeType = UnsignedInt; SuitableAlign = 64; } void setO64ABITypes() { + setOABITypes(); + Int64Type = SignedLongLong; IntMaxType = Int64Type; - LongDoubleFormat = &llvm::APFloat::IEEEquad(); - LongDoubleWidth = LongDoubleAlign = 128; - LongWidth = LongAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + LongDoubleWidth = LongDoubleAlign = 64; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; - PointerWidth = PointerAlign = 64; PtrDiffType = IntPtrType = SignedLong; SizeType = UnsignedLong; - SuitableAlign = 128; + SuitableAlign = 64; } void setN32N64ABITypes() { @@ -440,7 +449,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { } bool hasInt128Type() const override { - return (ABI == "o64" || ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; + return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; } unsigned getUnwindWordWidth() const override; diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index e3187351a0b555..68b38853f60d39 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -12,6 +12,7 @@ #include "clang/Options/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Option/OptSpecifier.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -104,6 +105,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, .Case("p5600", "o32") .Case("i6400", "n64") .Case("i6500", "n64") + .Case("vr4300", "o64") .Default(""); } @@ -116,6 +118,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, // Deduce CPU name from ABI name. CPUName = llvm::StringSwitch<const char *>(ABIName) .Case("o32", DefMips32CPU) + .Case("o64", DefMips64CPU) .Cases({"n32", "n64"}, DefMips64CPU) .Default(""); } @@ -129,6 +132,7 @@ std::string mips::getMipsABILibSuffix(const ArgList &Args, tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); return llvm::StringSwitch<std::string>(ABIName) .Case("o32", "") + .Case("o64", "o64") .Case("n32", "32") .Case("n64", "64"); } diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index 3b78de8ec43ad1..89fb79d3fec081 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -186,9 +186,16 @@ def FeatureCnMipsP : SubtargetFeature<"cnmipsp", "HasCnMipsP", "true", "Octeon+ cnMIPS Support", [FeatureCnMips]>; +def FeatureFixR4300 : SubtargetFeature<"fix-r4300", "FixR4300", "true", + "Enable R4300 mulmul erratum fix">; + def FeatureFixR5900 : SubtargetFeature<"fix-r5900", "FixR5900", "true", "Enable R5900 short loop erratum fix">; +def FeatureR4300 : SubtargetFeature<"vr4300", "IsR4300", "true", + "R4300 (Nintendo 64 CPU-NUS) Support", + [FeatureMips64, FeatureFixR4300]>; + def FeatureR5900 : SubtargetFeature<"r5900", "IsR5900", "true", "R5900 (PS2 Emotion Engine) Support", [FeatureMips3, FeatureSingleFloat, @@ -228,9 +235,9 @@ def FeatureUseCompactBranches // Mips Instruction Predicate Definitions. //===----------------------------------------------------------------------===// -def IsPTR64bit : Predicate<"Subtarget->isABI_N64()">, +def IsPTR64bit : Predicate<"Subtarget->isABI_64Bit()">, AssemblerPredicate<(all_of FeaturePTR64Bit)>; -def IsPTR32bit : Predicate<"!Subtarget->isABI_N64()">, +def IsPTR32bit : Predicate<"!Subtarget->isABI_64Bit()">, AssemblerPredicate<(all_of (not FeaturePTR64Bit))>; def UseCompactBranches : Predicate<"Subtarget->useCompactBranches()">, AssemblerPredicate<(all_of FeatureUseCompactBranches)>; @@ -307,6 +314,7 @@ def : Proc<"mips64r5", [FeatureMips64r5]>; def : Proc<"mips64r6", [FeatureMips64r6]>; def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>; def : Proc<"octeon+", [FeatureMips64r2, FeatureCnMips, FeatureCnMipsP]>; +def : Proc<"vr4300", [FeatureR4300]>; def : ProcessorModel<"p5600", MipsP5600Model, [ImplP5600]>; def : Proc<"r5900", [FeatureR5900]>; def : ProcessorModel<"i6400", MipsI6400Model, [ImplI6400]>; diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 26cad4a7d52280..980ccab1b464d1 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -293,6 +293,7 @@ bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); } bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); } bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); } bool MipsSubtarget::isABI_O64() const { return getABI().IsO64(); } +bool MipsSubtarget::isABI_64Bit() const { return isABI_O64() || isABI_N64(); } const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); } const SelectionDAGTargetInfo *MipsSubtarget::getSelectionDAGInfo() const { diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 83127bfaf00d7a..ac2e1411e4f884 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -127,6 +127,12 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // CPU supports cnMIPSP (Cavium Networks Octeon+ CPU). bool HasCnMipsP; + // IsR4300 - CPU is R4300 (Nintendo 64 CPU-NUS). + bool IsR4300; + + // FixR4300 - Enable R4300 mulmul erratum fix. + bool FixR4300; + // IsR5900 - CPU is R5900 (PlayStation 2 Emotion Engine). bool IsR5900; @@ -254,6 +260,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo { bool isABI_N32() const; bool isABI_O32() const; bool isABI_O64() const; + bool isABI_64Bit() const; const MipsABIInfo &getABI() const; bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } @@ -310,6 +317,8 @@ class MipsSubtarget : public MipsGenSubtargetInfo { bool hasCnMips() const { return HasCnMips; } bool hasCnMipsP() const { return HasCnMipsP; } + bool isR4300() const { return IsR4300; } + bool fixR4300() const { return FixR4300; } bool isR5900() const { return IsR5900; } bool fixR5900() const { return FixR5900; } diff --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp index 3b4a6aa0b7a543..6db0ea557eb598 100644 --- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -283,7 +283,7 @@ void MipsPassConfig::addPreEmitPass() { // This pass inserts a nop instruction between two back-to-back multiplication // instructions when the "mfix4300" flag is passed. - if (EnableMulMulFix) + if (EnableMulMulFix || getMipsSubtarget().fixR4300()) addPass(createMipsMulMulBugPass()); // The delay slot filler pass can potientially create forbidden slot hazards diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index d7c4b123881d7a..e20a8c32030ec8 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -190,7 +190,7 @@ static std::string computeMipsDataLayout(const Triple &TT, StringRef ABIName) { Ret += "-m:e"; // Pointers are 32 bit on some ABIs. - if (ABI != MipsABI::N64 && ABI != MipsABI::O64) + if (ABI != MipsABI::N64) Ret += "-p:32:32"; // 8 and 16 bit integers only need to have natural alignment, but try to @@ -200,7 +200,7 @@ static std::string computeMipsDataLayout(const Triple &TT, StringRef ABIName) { // 32 bit registers are always available and the stack is at least 64 bit // aligned. On N64 64 bit registers are also available and the stack is // 128 bit aligned. - if (ABI == MipsABI::O64 || ABI == MipsABI::N64 || ABI == MipsABI::N32) + if (ABI == MipsABI::N64 || ABI == MipsABI::N32) Ret += "-i128:128-n32:64-S128"; else Ret += "-n32-S64"; >From b95058ca567b66fcbf6941ff4e9e712fccd88869 Mon Sep 17 00:00:00 2001 From: LunaTheFoxgirl <[email protected]> Date: Thu, 17 Sep 2026 22:01:20 +0200 Subject: [PATCH 4/4] Solve issues from review --- llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 6 +++--- llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h | 5 +++-- llvm/lib/Target/Mips/MipsSubtarget.cpp | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index c9b24fb9593870..9aecc1b3f5f98e 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -63,9 +63,9 @@ ArrayRef<MCPhysReg> MipsABIInfo::getVarArgRegs(bool isGP64bit) const { } unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { - if (IsO32() || IsO64()) + if (IsOABI()) return CC != CallingConv::Fast ? 16 : 0; - if (IsN32() || IsN64()) + if (IsNABI()) return 0; llvm_unreachable("Unhandled ABI"); } @@ -140,5 +140,5 @@ unsigned MipsABIInfo::GetEhDataReg(unsigned I) const { Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64 }; - return (IsABI64()) ? EhDataReg64[I] : EhDataReg[I]; + return (ArePtrs64bit()) ? EhDataReg64[I] : EhDataReg[I]; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index e1ce417c228a4e..b6fd6e5445f3f8 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -41,7 +41,8 @@ class MipsABIInfo { bool IsO64() const { return ThisABI == ABI::O64; } bool IsN32() const { return ThisABI == ABI::N32; } bool IsN64() const { return ThisABI == ABI::N64; } - bool IsABI64() const { return ThisABI == ABI::N64 || ThisABI == ABI::O64; } + bool IsOABI() const { return ThisABI == ABI::O32 || ThisABI == ABI::O64; } + bool IsNABI() const { return ThisABI == ABI::N32 || ThisABI == ABI::N64; } ABI GetEnumValue() const { return ThisABI; } /// The registers to use for byval arguments. @@ -73,7 +74,7 @@ class MipsABIInfo { unsigned GetPtrAndOp() const; unsigned GetGPRMoveOp() const; inline bool ArePtrs64bit() const { return IsO64() || IsN64(); } - inline bool AreGprs64bit() const { return IsN32() || IsN64(); } + inline bool AreGprs64bit() const { return IsO64() || IsN32() || IsN64(); } unsigned GetEhDataReg(unsigned I) const; }; diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 980ccab1b464d1..5af1dcba6615b4 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -272,7 +272,7 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, stackAlignment = Align(8); } - if ((isABI_O64() || isABI_N32() || isABI_N64()) && !isGP64bit()) + if (getABI().AreGprs64bit() && !isGP64bit()) reportFatalUsageError("64-bit code requested on a subtarget that doesn't " "support it!"); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
