[flang-commits] [flang] [flang][MIPS] Add N32 and N64 target ABI support (PR #224920)

Jiaxun Yang via flang-commits flang-commits at lists.llvm.org
Thu Sep 24 02:38:10 PDT 2026


================
@@ -1409,6 +1411,87 @@ struct TargetSparcV9 : public GenericTarget<TargetSparcV9> {
 };
 } // namespace
 
+//===----------------------------------------------------------------------===//
+// MIPS N32 and N64 target specifics.
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct TargetMips64 : public GenericTarget<TargetMips64> {
+  using GenericTarget::GenericTarget;
+
+  const int defaultWidth = targetABI == "n32" ? 32 : 64;
+
+  CodeGenSpecifics::Marshalling
+  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
+    return complexArgumentType(loc, eleTy, {});
+  }
+
+  CodeGenSpecifics::Marshalling
+  complexArgumentType(mlir::Location loc, mlir::Type eleTy,
+                      const Marshalling &previousArguments) const override {
+    const auto *sem = &floatToSemantics(kindMap, eleTy);
+    if (sem != &llvm::APFloat::IEEEsingle() &&
+        sem != &llvm::APFloat::IEEEdouble())
+      typeTodo(sem, loc, "argument");
+
+    // N32/N64 share eight argument slots between integer and floating-point
+    // registers. A complex argument uses two FPRs when both parts fit.
+    // Otherwise, pass its memory representation in GPRs or on the stack,
+    // packing COMPLEX(4) into one slot.
+    uint64_t slots = 0;
+    for (auto [ty, attr] : previousArguments) {
+      if (attr.isAppend())
+        continue;
+      if (fir::conformsWithPassByRef(ty)) {
+        if (++slots >= 7)
+          break;
+        continue;
+      }
+      auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash(
+          loc, ty, getDataLayout(), kindMap);
+      slots = llvm::alignTo(slots, align > 8 ? 2 : 1);
+      slots += llvm::divideCeil(size, uint64_t{8});
+      if (slots >= 7)
+        break;
+    }
+
+    if (slots < 7)
+      return {{eleTy, AT{}}, {eleTy, AT{}}};
+
+    auto i64Ty = mlir::IntegerType::get(eleTy.getContext(), 64);
+    if (sem == &llvm::APFloat::IEEEsingle())
+      return {{i64Ty, AT{}}};
+    return {{mlir::TupleType::get(eleTy.getContext(), {i64Ty, i64Ty}), AT{}}};
+  }
+
+  CodeGenSpecifics::Marshalling
+  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
+    const auto *sem = &floatToSemantics(kindMap, eleTy);
+    auto structTy =
+        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
+    if (sem == &llvm::APFloat::IEEEsingle() ||
+        sem == &llvm::APFloat::IEEEdouble())
+      return {{structTy, AT{}}};
+    if (sem == &llvm::APFloat::IEEEquad())
+      return {{fir::ReferenceType::get(structTy),
+               AT{/*alignment=*/16, /*byval=*/false, /*sret=*/true}}};
----------------
FlyGoat wrote:

Yes, N32 have 64bit GPR, thus same stack alignment.

https://github.com/llvm/llvm-project/pull/224920


More information about the flang-commits mailing list