[clang] [flang] [Flang] LoongArch64 support for BIND(C) derived types in mabi=lp64d. (PR #117108)

Zhaoxin Yang via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 28 07:06:21 PST 2024


================
@@ -1151,6 +1154,317 @@ struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
 
     return GenericTarget::integerArgumentType(loc, argTy);
   }
+
+  /// Flatten non-basic types, resulting in an array of types containing only
+  /// `IntegerType` and `FloatType`.
+  std::vector<mlir::Type> flattenTypeList(mlir::Location loc,
+                                          const mlir::Type type) const {
+    std::vector<mlir::Type> flatTypes;
+
+    llvm::TypeSwitch<mlir::Type>(type)
+        .template Case<mlir::IntegerType>([&](mlir::IntegerType intTy) {
+          if (intTy.getWidth() != 0)
+            flatTypes.push_back(intTy);
+        })
+        .template Case<mlir::FloatType>([&](mlir::FloatType floatTy) {
+          if (floatTy.getWidth() != 0)
+            flatTypes.push_back(floatTy);
+        })
+        .template Case<mlir::ComplexType>([&](mlir::ComplexType cmplx) {
+          const auto *sem = &floatToSemantics(kindMap, cmplx.getElementType());
+          if (sem == &llvm::APFloat::IEEEsingle() ||
+              sem == &llvm::APFloat::IEEEdouble() ||
+              sem == &llvm::APFloat::IEEEquad())
+            std::fill_n(std::back_inserter(flatTypes), 2,
+                        cmplx.getElementType());
+          else
+            TODO(loc, "unsupported complx type(not IEEEsingle, IEEEdouble, "
+                      "IEEEquad) as a structure component for BIND(C), "
+                      "VALUE derived type argument and type return");
+        })
+        .template Case<fir::LogicalType>([&](fir::LogicalType logicalTy) {
+          const unsigned width =
+              kindMap.getLogicalBitsize(logicalTy.getFKind());
+          if (width != 0)
+            flatTypes.push_back(
+                mlir::IntegerType::get(type.getContext(), width));
+        })
+        .template Case<fir::CharacterType>([&](fir::CharacterType charTy) {
+          assert(kindMap.getCharacterBitsize(charTy.getFKind()) <= 8 &&
+                 "the bit size of characterType as an interoperable type must "
+                 "not exceed 8");
+          for (unsigned i = 0; i < charTy.getLen(); ++i)
+            flatTypes.push_back(mlir::IntegerType::get(type.getContext(), 8));
+        })
+        .template Case<fir::SequenceType>([&](fir::SequenceType seqTy) {
+          if (!seqTy.hasDynamicExtents()) {
+            std::size_t numOfEle = seqTy.getConstantArraySize();
+            mlir::Type eleTy = seqTy.getEleTy();
+            if (!mlir::isa<mlir::IntegerType, mlir::FloatType>(eleTy)) {
+              std::vector<mlir::Type> subTypeList = flattenTypeList(loc, eleTy);
+              if (subTypeList.size() != 0)
+                for (std::size_t i = 0; i < numOfEle; ++i)
+                  llvm::copy(subTypeList, std::back_inserter(flatTypes));
+            } else {
+              std::fill_n(std::back_inserter(flatTypes), numOfEle, eleTy);
+            }
+          } else
+            TODO(loc, "unsupported dynamic extent sequence type as a structure "
+                      "component for BIND(C), "
+                      "VALUE derived type argument and type return");
+        })
+        .template Case<fir::RecordType>([&](fir::RecordType recTy) {
+          for (auto &component : recTy.getTypeList()) {
+            mlir::Type eleTy = component.second;
+            std::vector<mlir::Type> subTypeList = flattenTypeList(loc, eleTy);
+            if (subTypeList.size() != 0)
+              llvm::copy(subTypeList, std::back_inserter(flatTypes));
+          }
+        })
+        .template Case<fir::VectorType>([&](fir::VectorType vecTy) {
----------------
ylzsx wrote:

Thanks for your review. This is my oversight. According to the [LoongArch ABI](https://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc#vectors-1), 128-bit vector are passed with two GARs with adjacent numbers (if available), and 256-bit vector are passed on the stack. In other cases, the manual has not explicitly specified. 

I will modify my code to comply with this ABI requirement and report a TODO for other cases. Specifically,
* For a vector smaller than 128 bits, report a TODO.
* For a vector equal to 128 bits, return `i128`
* For a vector larger than 128 bits, pass it on the stack.

I will try to make sure it behaves as similar to clang as possible. Looking forward to your suggestions.

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


More information about the cfe-commits mailing list