[Flang] Enable support for conversion of recursive record types
Uses the recursive type conversion implemented in D113579, D113580. Tests check for recursive and mutually recursive types. Note: The downstream implementation for recursive types is a bit old and is based on a static map. This was removed while upstreaming (https://reviews.llvm.org/D112961) based on review comments. Since the recursive type conversion is now available in MLIR we are using that. If this patch is accepted we can use the same in the downstream implementation. Part of upstreaming flang from fir-dev branch of https://github.com/flang-compiler/f18-llvm-project. Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D115937 Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This commit is contained in:
parent
4c2aba999e
commit
21d299172e
|
|
@ -80,8 +80,10 @@ public:
|
||||||
});
|
});
|
||||||
addConversion(
|
addConversion(
|
||||||
[&](fir::PointerType pointer) { return convertPointerLike(pointer); });
|
[&](fir::PointerType pointer) { return convertPointerLike(pointer); });
|
||||||
addConversion(
|
addConversion([&](fir::RecordType derived, SmallVectorImpl<Type> &results,
|
||||||
[&](fir::RecordType derived) { return convertRecordType(derived); });
|
ArrayRef<Type> callStack) {
|
||||||
|
return convertRecordType(derived, results, callStack);
|
||||||
|
});
|
||||||
addConversion([&](fir::FieldType field) {
|
addConversion([&](fir::FieldType field) {
|
||||||
// Convert to i32 because of LLVM GEP indexing restriction.
|
// Convert to i32 because of LLVM GEP indexing restriction.
|
||||||
return mlir::IntegerType::get(field.getContext(), 32);
|
return mlir::IntegerType::get(field.getContext(), 32);
|
||||||
|
|
@ -127,16 +129,23 @@ public:
|
||||||
mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); }
|
mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); }
|
||||||
|
|
||||||
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
|
// fir.type<name(p : TY'...){f : TY...}> --> llvm<"%name = { ty... }">
|
||||||
mlir::Type convertRecordType(fir::RecordType derived) {
|
llvm::Optional<LogicalResult>
|
||||||
|
convertRecordType(fir::RecordType derived, SmallVectorImpl<Type> &results,
|
||||||
|
ArrayRef<Type> callStack) {
|
||||||
auto name = derived.getName();
|
auto name = derived.getName();
|
||||||
auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
|
auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
|
||||||
|
if (llvm::count(callStack, derived) > 1) {
|
||||||
|
results.push_back(st);
|
||||||
|
return success();
|
||||||
|
}
|
||||||
llvm::SmallVector<mlir::Type> members;
|
llvm::SmallVector<mlir::Type> members;
|
||||||
for (auto mem : derived.getTypeList()) {
|
for (auto mem : derived.getTypeList()) {
|
||||||
members.push_back(convertType(mem.second).cast<mlir::Type>());
|
members.push_back(convertType(mem.second).cast<mlir::Type>());
|
||||||
}
|
}
|
||||||
if (mlir::succeeded(st.setBody(members, /*isPacked=*/false)))
|
if (mlir::failed(st.setBody(members, /*isPacked=*/false)))
|
||||||
return st;
|
return failure();
|
||||||
return mlir::Type();
|
results.push_back(st);
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is an extended descriptor needed given the element type of a fir.box type ?
|
// Is an extended descriptor needed given the element type of a fir.box type ?
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Test lowering FIR to LLVM IR for recursive types
|
||||||
|
|
||||||
|
// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
|
||||||
|
// RUN: fir-opt --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
|
||||||
|
// RUN: fir-opt --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s
|
||||||
|
// RUN: fir-opt --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s
|
||||||
|
|
||||||
|
!t1 = type !fir.type<t1 {a1:!fir.ptr<!fir.type<t1>>}>
|
||||||
|
!t2 = type !fir.type<t2 {b1:f32,b2:!fir.ptr<!fir.type<t2>>,b3:i32,b4:!fir.ptr<!fir.type<t2>>}>
|
||||||
|
!t3 = type !fir.type<t3 {c1:!fir.ptr<!fir.type<t4>>}>
|
||||||
|
!t4 = type !fir.type<t4 {d1:!fir.ptr<!fir.type<t3>>}>
|
||||||
|
|
||||||
|
// CHECK-LABEL: llvm.func @recursiveTypes
|
||||||
|
// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T1:.*]]", (ptr<struct<"[[T1]]">>)>
|
||||||
|
// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T2:.*]]", (f32, ptr<struct<"[[T2]]">>, i32, ptr<struct<"[[T2]]">>)>
|
||||||
|
// CHECK-SAME: %{{.*}}: !llvm.struct<"[[T3:.*]]", (ptr<struct<"[[T4:.*]]", (ptr<struct<"[[T3]]">>)>>)>, %{{.*}}: !llvm.struct<"[[T4]]", (ptr<struct<"[[T3]]", (ptr<struct<"[[T4]]">>)>>)>)
|
||||||
|
func @recursiveTypes(%a : !t1, %b : !t2, %c : !t3, %d : !t4) {
|
||||||
|
return
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue