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

via flang-commits flang-commits at lists.llvm.org
Mon Sep 28 06:12:05 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{}}};
----------------
jeanPerier wrote:

Maybe the end results is the same, but I think clang is generating split i64 arguments when passing complex<f64>, not a tuple type.

Also, note that I am not sure that we handle `tuple` type in getTypeSizeAndAlignment, so if you have two complex<f64> argument as in:

```
subroutine spill_two(a0, a1, a2, a3, a4, a5, a6, z1, z2) bind(c)
  integer(8), value :: a0, a1, a2, a3, a4, a5, a6
  complex(8), value :: z1, z2
end subroutine
```

You would likely hit a TODO.

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


More information about the flang-commits mailing list