mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 16:11:29 +00:00
[flang] Adapt descriptor codegen to support unlimited polymorphic entities
Code generation to create and populate the descriptor (element size and type code) is based on the boxed result type. This does not work well with unlimited polymorphic entities since the fir type does not represent what is actually emboxed or reboxed. In the case of emboxing, the input type will be used to populate the descriptor element size and type code. When reboxing an unlimited polymorphic to a unlimited polymorphic entities, the element size and type code is retrieve from the input box. Reviewed By: jeanPerier Differential Revision: https://reviews.llvm.org/D138587
This commit is contained in:
parent
cb888971d2
commit
c1b7e9c962
@ -288,6 +288,9 @@ bool isPolymorphicType(mlir::Type ty);
|
||||
/// value.
|
||||
bool isUnlimitedPolymorphicType(mlir::Type ty);
|
||||
|
||||
/// Return the inner type of the given type.
|
||||
mlir::Type unwrapInnerType(mlir::Type ty);
|
||||
|
||||
/// Return true iff `ty` is a RecordType with members that are allocatable.
|
||||
bool isRecordWithAllocatableMember(mlir::Type ty);
|
||||
|
||||
|
@ -951,6 +951,7 @@ void CompilerInvocation::setLoweringOptions() {
|
||||
|
||||
// Lower TRANSPOSE as a runtime call under -O0.
|
||||
loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
|
||||
loweringOpts.setPolymorphicTypeImpl(true);
|
||||
|
||||
const LangOptions &langOptions = getLangOpts();
|
||||
Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();
|
||||
|
@ -142,7 +142,9 @@ struct TypeBuilder {
|
||||
Fortran::common::TypeCategory category = dynamicType->category();
|
||||
|
||||
mlir::Type baseType;
|
||||
if (category == Fortran::common::TypeCategory::Derived) {
|
||||
if (dynamicType->IsUnlimitedPolymorphic()) {
|
||||
baseType = mlir::NoneType::get(context);
|
||||
} else if (category == Fortran::common::TypeCategory::Derived) {
|
||||
baseType = genDerivedType(dynamicType->GetDerivedTypeSpec());
|
||||
} else {
|
||||
// LOGICAL, INTEGER, REAL, COMPLEX, CHARACTER
|
||||
|
@ -1468,21 +1468,19 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
|
||||
|
||||
/// Get the address of the type descriptor global variable that was created by
|
||||
/// lowering for derived type \p recType.
|
||||
template <typename BOX>
|
||||
mlir::Value
|
||||
getTypeDescriptor(BOX box, mlir::ConversionPatternRewriter &rewriter,
|
||||
mlir::Location loc, fir::RecordType recType) const {
|
||||
mlir::Value getTypeDescriptor(mlir::ModuleOp mod,
|
||||
mlir::ConversionPatternRewriter &rewriter,
|
||||
mlir::Location loc,
|
||||
fir::RecordType recType) const {
|
||||
std::string name =
|
||||
fir::NameUniquer::getTypeDescriptorName(recType.getName());
|
||||
auto module = box->template getParentOfType<mlir::ModuleOp>();
|
||||
if (auto global = module.template lookupSymbol<fir::GlobalOp>(name)) {
|
||||
if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name)) {
|
||||
auto ty = mlir::LLVM::LLVMPointerType::get(
|
||||
this->lowerTy().convertType(global.getType()));
|
||||
return rewriter.create<mlir::LLVM::AddressOfOp>(loc, ty,
|
||||
global.getSymName());
|
||||
}
|
||||
if (auto global =
|
||||
module.template lookupSymbol<mlir::LLVM::GlobalOp>(name)) {
|
||||
if (auto global = mod.template lookupSymbol<mlir::LLVM::GlobalOp>(name)) {
|
||||
// The global may have already been translated to LLVM.
|
||||
auto ty = mlir::LLVM::LLVMPointerType::get(global.getType());
|
||||
return rewriter.create<mlir::LLVM::AddressOfOp>(loc, ty,
|
||||
@ -1496,31 +1494,21 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
|
||||
fir::emitFatalError(
|
||||
loc, "runtime derived type info descriptor was not generated");
|
||||
return rewriter.create<mlir::LLVM::NullOp>(
|
||||
loc, ::getVoidPtrType(box.getContext()));
|
||||
loc, ::getVoidPtrType(mod.getContext()));
|
||||
}
|
||||
|
||||
template <typename BOX>
|
||||
std::tuple<fir::BaseBoxType, mlir::Value, mlir::Value>
|
||||
consDescriptorPrefix(BOX box, mlir::ConversionPatternRewriter &rewriter,
|
||||
unsigned rank, mlir::ValueRange lenParams,
|
||||
mlir::Value typeDesc = {}) const {
|
||||
auto loc = box.getLoc();
|
||||
auto boxTy = box.getType().template dyn_cast<fir::BaseBoxType>();
|
||||
mlir::Value populateDescriptor(mlir::Location loc, mlir::ModuleOp mod,
|
||||
fir::BaseBoxType boxTy, mlir::Type inputType,
|
||||
mlir::ConversionPatternRewriter &rewriter,
|
||||
unsigned rank, mlir::Value eleSize,
|
||||
mlir::Value cfiTy,
|
||||
mlir::Value typeDesc) const {
|
||||
auto convTy = this->lowerTy().convertBoxType(boxTy, rank);
|
||||
auto llvmBoxPtrTy = convTy.template cast<mlir::LLVM::LLVMPointerType>();
|
||||
auto llvmBoxTy = llvmBoxPtrTy.getElementType();
|
||||
bool isUnlimitedPolymorphic = fir::isUnlimitedPolymorphicType(boxTy);
|
||||
mlir::Value descriptor =
|
||||
rewriter.create<mlir::LLVM::UndefOp>(loc, llvmBoxTy);
|
||||
|
||||
llvm::SmallVector<mlir::Value> typeparams = lenParams;
|
||||
if constexpr (!std::is_same_v<BOX, fir::EmboxOp>) {
|
||||
if (!box.getSubstr().empty() && fir::hasDynamicSize(boxTy.getEleTy()))
|
||||
typeparams.push_back(box.getSubstr()[1]);
|
||||
}
|
||||
|
||||
// Write each of the fields with the appropriate values
|
||||
auto [eleSize, cfiTy] =
|
||||
getSizeAndTypeCode(loc, rewriter, boxTy.getEleTy(), typeparams);
|
||||
descriptor =
|
||||
insertField(rewriter, loc, descriptor, {kElemLenPosInBox}, eleSize);
|
||||
descriptor = insertField(rewriter, loc, descriptor, {kVersionPosInBox},
|
||||
@ -1531,20 +1519,98 @@ struct EmboxCommonConversion : public FIROpConversion<OP> {
|
||||
descriptor =
|
||||
insertField(rewriter, loc, descriptor, {kAttributePosInBox},
|
||||
this->genI32Constant(loc, rewriter, getCFIAttr(boxTy)));
|
||||
const bool hasAddendum = isDerivedType(boxTy);
|
||||
const bool hasAddendum = isDerivedType(boxTy) || isUnlimitedPolymorphic;
|
||||
descriptor =
|
||||
insertField(rewriter, loc, descriptor, {kF18AddendumPosInBox},
|
||||
this->genI32Constant(loc, rewriter, hasAddendum ? 1 : 0));
|
||||
|
||||
if (hasAddendum) {
|
||||
unsigned typeDescFieldId = getTypeDescFieldId(boxTy);
|
||||
if (!typeDesc)
|
||||
typeDesc =
|
||||
getTypeDescriptor(box, rewriter, loc, unwrapIfDerived(boxTy));
|
||||
descriptor =
|
||||
insertField(rewriter, loc, descriptor, {typeDescFieldId}, typeDesc,
|
||||
/*bitCast=*/true);
|
||||
if (!typeDesc) {
|
||||
if (isUnlimitedPolymorphic) {
|
||||
mlir::Type innerType = fir::unwrapInnerType(inputType);
|
||||
if (innerType && innerType.template isa<fir::RecordType>()) {
|
||||
auto recTy = innerType.template dyn_cast<fir::RecordType>();
|
||||
typeDesc = getTypeDescriptor(mod, rewriter, loc, recTy);
|
||||
} else {
|
||||
// Unlimited polymorphic type descriptor with no record type. Set
|
||||
// type descriptor address to a clean state.
|
||||
typeDesc = rewriter.create<mlir::LLVM::NullOp>(
|
||||
loc, ::getVoidPtrType(mod.getContext()));
|
||||
}
|
||||
} else {
|
||||
typeDesc =
|
||||
getTypeDescriptor(mod, rewriter, loc, unwrapIfDerived(boxTy));
|
||||
}
|
||||
}
|
||||
if (typeDesc)
|
||||
descriptor =
|
||||
insertField(rewriter, loc, descriptor, {typeDescFieldId}, typeDesc,
|
||||
/*bitCast=*/true);
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// Template used for fir::EmboxOp and fir::cg::XEmboxOp
|
||||
template <typename BOX>
|
||||
std::tuple<fir::BaseBoxType, mlir::Value, mlir::Value>
|
||||
consDescriptorPrefix(BOX box, mlir::Type inputType,
|
||||
mlir::ConversionPatternRewriter &rewriter, unsigned rank,
|
||||
mlir::ValueRange lenParams,
|
||||
mlir::Value typeDesc = {}) const {
|
||||
auto loc = box.getLoc();
|
||||
auto boxTy = box.getType().template dyn_cast<fir::BaseBoxType>();
|
||||
bool isUnlimitedPolymorphic = fir::isUnlimitedPolymorphicType(boxTy);
|
||||
bool useInputType =
|
||||
isUnlimitedPolymorphic && !fir::isUnlimitedPolymorphicType(inputType);
|
||||
llvm::SmallVector<mlir::Value> typeparams = lenParams;
|
||||
if constexpr (!std::is_same_v<BOX, fir::EmboxOp>) {
|
||||
if (!box.getSubstr().empty() && fir::hasDynamicSize(boxTy.getEleTy()))
|
||||
typeparams.push_back(box.getSubstr()[1]);
|
||||
}
|
||||
|
||||
// Write each of the fields with the appropriate values.
|
||||
// When emboxing an element to a unlimited polymorphic descriptor, use the
|
||||
// input type since the destination descriptor type as no type information.
|
||||
auto [eleSize, cfiTy] = getSizeAndTypeCode(
|
||||
loc, rewriter, useInputType ? inputType : boxTy.getEleTy(), typeparams);
|
||||
auto mod = box->template getParentOfType<mlir::ModuleOp>();
|
||||
mlir::Value descriptor = populateDescriptor(
|
||||
loc, mod, boxTy, inputType, rewriter, rank, eleSize, cfiTy, typeDesc);
|
||||
|
||||
return {boxTy, descriptor, eleSize};
|
||||
}
|
||||
|
||||
std::tuple<fir::BaseBoxType, mlir::Value, mlir::Value>
|
||||
consDescriptorPrefix(fir::cg::XReboxOp box, mlir::Value loweredBox,
|
||||
mlir::ConversionPatternRewriter &rewriter, unsigned rank,
|
||||
mlir::ValueRange lenParams,
|
||||
mlir::Value typeDesc = {}) const {
|
||||
auto loc = box.getLoc();
|
||||
auto boxTy = box.getType().dyn_cast<fir::BaseBoxType>();
|
||||
llvm::SmallVector<mlir::Value> typeparams = lenParams;
|
||||
if (!box.getSubstr().empty() && fir::hasDynamicSize(boxTy.getEleTy()))
|
||||
typeparams.push_back(box.getSubstr()[1]);
|
||||
|
||||
auto [eleSize, cfiTy] =
|
||||
getSizeAndTypeCode(loc, rewriter, boxTy.getEleTy(), typeparams);
|
||||
|
||||
// Reboxing an unlimited polymorphic entities. eleSize and type code need to
|
||||
// be retrived from the initial box.
|
||||
if (fir::isUnlimitedPolymorphicType(boxTy) &&
|
||||
fir::isUnlimitedPolymorphicType(box.getBox().getType())) {
|
||||
mlir::Type idxTy = this->lowerTy().indexType();
|
||||
eleSize = this->loadElementSizeFromBox(loc, idxTy, loweredBox, rewriter);
|
||||
cfiTy = this->getValueFromBox(loc, loweredBox, cfiTy.getType(), rewriter,
|
||||
kTypePosInBox);
|
||||
typeDesc = this->loadTypeDescAddress(loc, box.getBox().getType(),
|
||||
loweredBox, rewriter);
|
||||
}
|
||||
|
||||
auto mod = box->template getParentOfType<mlir::ModuleOp>();
|
||||
mlir::Value descriptor =
|
||||
populateDescriptor(loc, mod, boxTy, box.getBox().getType(), rewriter,
|
||||
rank, eleSize, cfiTy, typeDesc);
|
||||
|
||||
return {boxTy, descriptor, eleSize};
|
||||
}
|
||||
@ -1674,7 +1740,7 @@ struct EmboxOpConversion : public EmboxCommonConversion<fir::EmboxOp> {
|
||||
tdesc = operands[embox.getTdescOffset()];
|
||||
assert(!embox.getShape() && "There should be no dims on this embox op");
|
||||
auto [boxTy, dest, eleSize] = consDescriptorPrefix(
|
||||
embox, rewriter,
|
||||
embox, fir::unwrapRefType(embox.getMemref().getType()), rewriter,
|
||||
/*rank=*/0, /*lenParams=*/operands.drop_front(1), tdesc);
|
||||
dest = insertBaseAddress(rewriter, embox.getLoc(), dest, operands[0]);
|
||||
if (isDerivedTypeWithLenParams(boxTy)) {
|
||||
@ -1699,9 +1765,9 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
|
||||
mlir::Value tdesc;
|
||||
if (xbox.getTdesc())
|
||||
tdesc = operands[xbox.getTdescOffset()];
|
||||
auto [boxTy, dest, eleSize] =
|
||||
consDescriptorPrefix(xbox, rewriter, xbox.getOutRank(),
|
||||
operands.drop_front(xbox.lenParamOffset()), tdesc);
|
||||
auto [boxTy, dest, eleSize] = consDescriptorPrefix(
|
||||
xbox, fir::unwrapRefType(xbox.getMemref().getType()), rewriter,
|
||||
xbox.getOutRank(), operands.drop_front(xbox.lenParamOffset()), tdesc);
|
||||
// Generate the triples in the dims field of the descriptor
|
||||
auto i64Ty = mlir::IntegerType::get(xbox.getContext(), 64);
|
||||
mlir::Value base = operands[0];
|
||||
@ -1908,8 +1974,9 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
|
||||
typeDescAddr = loadTypeDescAddress(loc, rebox.getBox().getType(),
|
||||
loweredBox, rewriter);
|
||||
|
||||
auto [boxTy, dest, eleSize] = consDescriptorPrefix(
|
||||
rebox, rewriter, rebox.getOutRank(), lenParams, typeDescAddr);
|
||||
auto [boxTy, dest, eleSize] =
|
||||
consDescriptorPrefix(rebox, loweredBox, rewriter, rebox.getOutRank(),
|
||||
lenParams, typeDescAddr);
|
||||
|
||||
// Read input extents, strides, and base address
|
||||
llvm::SmallVector<mlir::Value> inputExtents;
|
||||
|
@ -244,7 +244,7 @@ public:
|
||||
dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, rank));
|
||||
}
|
||||
// opt-type-ptr: i8* (see fir.tdesc)
|
||||
if (requiresExtendedDesc(ele)) {
|
||||
if (requiresExtendedDesc(ele) || fir::isUnlimitedPolymorphicType(box)) {
|
||||
dataDescFields.push_back(
|
||||
getExtendedDescFieldTypeModel<kOptTypePtrPosInBox>()(&getContext()));
|
||||
auto rowTy =
|
||||
|
@ -308,6 +308,17 @@ bool isUnlimitedPolymorphicType(mlir::Type ty) {
|
||||
return isAssumedType(ty);
|
||||
}
|
||||
|
||||
mlir::Type unwrapInnerType(mlir::Type ty) {
|
||||
return llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)
|
||||
.Case<fir::PointerType, fir::HeapType, fir::SequenceType>([](auto t) {
|
||||
mlir::Type eleTy = t.getEleTy();
|
||||
if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
|
||||
return seqTy.getEleTy();
|
||||
return eleTy;
|
||||
})
|
||||
.Default([](mlir::Type) { return mlir::Type{}; });
|
||||
}
|
||||
|
||||
bool isRecordWithAllocatableMember(mlir::Type ty) {
|
||||
if (auto recTy = ty.dyn_cast<fir::RecordType>())
|
||||
for (auto [field, memTy] : recTy.getTypeList()) {
|
||||
@ -987,14 +998,7 @@ mlir::Type BaseBoxType::getEleTy() const {
|
||||
}
|
||||
|
||||
mlir::Type BaseBoxType::unwrapInnerType() const {
|
||||
return llvm::TypeSwitch<mlir::Type, mlir::Type>(getEleTy())
|
||||
.Case<fir::PointerType, fir::HeapType, fir::SequenceType>([](auto ty) {
|
||||
mlir::Type eleTy = ty.getEleTy();
|
||||
if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
|
||||
return seqTy.getEleTy();
|
||||
return eleTy;
|
||||
})
|
||||
.Default([](mlir::Type) { return mlir::Type{}; });
|
||||
return fir::unwrapInnerType(getEleTy());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1514,11 +1514,11 @@ func.func @embox0(%arg0: !fir.ref<!fir.array<100xi32>>) {
|
||||
// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr<array<100 x i32>>
|
||||
// CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32
|
||||
// CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>>
|
||||
// CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
|
||||
// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
|
||||
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
|
||||
// CHECK: %[[I64_ELEM_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
|
||||
// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32
|
||||
// CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
|
||||
// CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[I64_ELEM_SIZE]], %[[DESC]][1] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
|
||||
// CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
|
||||
// CHECK: %[[DESC1:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[DESC0]][2] : !llvm.struct<(ptr<array<100 x i32>>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
|
||||
@ -1737,11 +1737,11 @@ func.func @xembox0(%arg0: !fir.ref<!fir.array<?xi32>>) {
|
||||
// CHECK: %[[ALLOCA_SIZE:.*]] = llvm.mlir.constant(1 : i32) : i32
|
||||
// CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr<struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>>
|
||||
// CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
|
||||
// CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
|
||||
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
|
||||
// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
|
||||
// CHECK: %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32
|
||||
// CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
// CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
// CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
|
||||
// CHECK: %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
@ -1836,11 +1836,11 @@ func.func private @_QPxb(!fir.box<!fir.array<?x?xf64>>)
|
||||
// CHECK: %[[ARR_SIZE_TMP1:.*]] = llvm.mul %[[C1_0]], %[[N1]] : i64
|
||||
// CHECK: %[[ARR_SIZE:.*]] = llvm.mul %[[ARR_SIZE_TMP1]], %[[N2]] : i64
|
||||
// CHECK: %[[ARR:.*]] = llvm.alloca %[[ARR_SIZE]] x f64 {bindc_name = "arr", in_type = !fir.array<?x?xf64>, operand_segment_sizes = array<i32: 0, 2>, uniq_name = "_QFsbEarr"} : (i64) -> !llvm.ptr<f64>
|
||||
// CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
|
||||
// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<f64>
|
||||
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
|
||||
// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<f64> to i64
|
||||
// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(28 : i32) : i32
|
||||
// CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
|
||||
// CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
|
||||
// CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
|
||||
// CHECK: %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr<f64>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)>
|
||||
@ -1915,11 +1915,11 @@ func.func private @_QPtest_dt_callee(%arg0: !fir.box<!fir.array<?xi32>>)
|
||||
// CHECK: %[[V:.*]] = llvm.alloca %[[ALLOCA_SIZE_V]] x i32 {bindc_name = "v", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFtest_dt_sliceEv"} : (i64) -> !llvm.ptr<i32>
|
||||
// CHECK: %[[ALLOCA_SIZE_X:.*]] = llvm.mlir.constant(1 : i64) : i64
|
||||
// CHECK: %[[X:.*]] = llvm.alloca %[[ALLOCA_SIZE_X]] x !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>> {bindc_name = "x", in_type = !fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFtest_dt_sliceEx"} : (i64) -> !llvm.ptr<array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>>>
|
||||
// CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<i32>
|
||||
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
|
||||
// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<i32> to i64
|
||||
// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32
|
||||
// CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
// CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
// CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
|
||||
// CHECK: %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr<i32>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
|
||||
@ -2192,11 +2192,11 @@ func.func @test_rebox_1(%arg0: !fir.box<!fir.array<?x?xf32>>) {
|
||||
//CHECK: %[[FIVE:.*]] = llvm.mlir.constant(5 : index) : i64
|
||||
//CHECK: %[[SIX:.*]] = llvm.mlir.constant(6 : index) : i64
|
||||
//CHECK: %[[EIGHTY:.*]] = llvm.mlir.constant(80 : index) : i64
|
||||
//CHECK: %[[RBOX:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
|
||||
//CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr<f32>
|
||||
//CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1]
|
||||
//CHECK: %[[ELEM_SIZE_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr<f32> to i64
|
||||
//CHECK: %[[FLOAT_TYPE:.*]] = llvm.mlir.constant(27 : i32) : i32
|
||||
//CHECK: %[[RBOX:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
|
||||
//CHECK: %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE_I64]], %[[RBOX]][1] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
|
||||
//CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32
|
||||
//CHECK: %[[RBOX_TMP2:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[RBOX_TMP1]][2] : !llvm.struct<(ptr<f32>, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
|
||||
|
@ -11,10 +11,81 @@ func.func @_QMpolymorphic_testPtest_allocate_unlimited_polymorphic_non_derived()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @_QMpolymorphic_testPtest_allocate_unlimited_polymorphic_non_derived() {
|
||||
// CHECK: %[[MEM:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }
|
||||
// CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1
|
||||
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8 } { ptr null, i64 0, i32 20180515, i8 0, i8 -1, i8 1, i8 0 }, ptr %[[MEM]]
|
||||
// CHECK: %[[LOADED:.*]] = load { ptr, i64, i32, i8, i8, i8, i8 }, ptr %[[MEM]], align 8
|
||||
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8 } %[[LOADED]], ptr %[[DESC]]
|
||||
// CHECK: %[[MEM:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }
|
||||
// CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1
|
||||
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr null, i64 0, i32 20180515, i8 0, i8 -1, i8 1, i8 1, ptr null, [1 x i64] undef }, ptr %[[MEM]]
|
||||
// CHECK: %[[LOADED:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[MEM]], align 8
|
||||
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED]], ptr %[[DESC]]
|
||||
// CHECK: ret void
|
||||
// CHECK: }
|
||||
|
||||
|
||||
// Test rebox of unlimited polymoprhic descriptor
|
||||
|
||||
func.func @_QMpolymorphic_testPtest_rebox() {
|
||||
%0 = fir.address_of(@_QFEx) : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>
|
||||
%c-1_i32 = arith.constant -1 : i32
|
||||
%9 = fir.address_of(@_QQcl.2E2F64756D6D792E66393000) : !fir.ref<!fir.char<1,12>>
|
||||
%10 = fir.convert %9 : (!fir.ref<!fir.char<1,12>>) -> !fir.ref<i8>
|
||||
%c8_i32 = arith.constant 8 : i32
|
||||
%11 = fir.call @_FortranAioBeginExternalListOutput(%c-1_i32, %10, %c8_i32) fastmath<contract> : (i32, !fir.ref<i8>, i32) -> !fir.ref<i8>
|
||||
%12 = fir.load %0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>
|
||||
%c0_1 = arith.constant 0 : index
|
||||
%13:3 = fir.box_dims %12, %c0_1 : (!fir.class<!fir.ptr<!fir.array<?xnone>>>, index) -> (index, index, index)
|
||||
%14 = fir.shift %13#0 : (index) -> !fir.shift<1>
|
||||
%15 = fir.rebox %12(%14) : (!fir.class<!fir.ptr<!fir.array<?xnone>>>, !fir.shift<1>) -> !fir.class<!fir.array<?xnone>>
|
||||
%16 = fir.convert %15 : (!fir.class<!fir.array<?xnone>>) -> !fir.box<none>
|
||||
%17 = fir.call @_FortranAioOutputDescriptor(%11, %16) fastmath<contract> : (!fir.ref<i8>, !fir.box<none>) -> i1
|
||||
%18 = fir.call @_FortranAioEndIoStatement(%11) fastmath<contract> : (!fir.ref<i8>) -> i32
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @_QMpolymorphic_testPtest_rebox
|
||||
// CHECK: %[[ELE_SIZE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 1
|
||||
// CHECK: %[[ELE_SIZE:.*]] = load i64, ptr %[[ELE_SIZE_GEP]]
|
||||
// CHECK: %[[TYPE_CODE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 4
|
||||
// CHECK: %[[TYPE_CODE:.*]] = load i32, ptr %[[TYPE_CODE_GEP]]
|
||||
// CHECK: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } undef, i64 %[[ELE_SIZE]], 1
|
||||
// CHECK: %[[TYPE_CODE_I8:.*]] = trunc i32 %[[TYPE_CODE]] to i8
|
||||
// CHECK: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %{{.*}}, i8 %[[TYPE_CODE_I8]], 4
|
||||
|
||||
// Test emboxing to a unlimited polymorphic descriptor
|
||||
|
||||
func.func @_QMpolymorphic_testPtest_embox() {
|
||||
%0 = fir.address_of(@_QFEx) : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>
|
||||
%1 = fir.address_of(@_QFEy) : !fir.ref<!fir.array<1xi32>>
|
||||
%c1 = arith.constant 1 : index
|
||||
%2 = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"}
|
||||
%3 = fir.shape %c1 : (index) -> !fir.shape<1>
|
||||
%4 = fir.embox %1(%3) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.class<!fir.ptr<!fir.array<?xnone>>>
|
||||
fir.store %4 to %0 : !fir.ref<!fir.class<!fir.ptr<!fir.array<?xnone>>>>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @_QMpolymorphic_testPtest_embox()
|
||||
// CHECK: %[[ALLOCA_DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }
|
||||
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } { ptr @_QFEy, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20180515, i8 1, i8 9, {{.*}}, ptr %[[ALLOCA_DESC]]
|
||||
// CHECK: %[[LOADED_DESC:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_DESC]], align 8
|
||||
// CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[LOADED_DESC]], ptr @_QFEx, align 8
|
||||
|
||||
|
||||
fir.global internal @_QFEx : !fir.class<!fir.ptr<!fir.array<?xnone>>> {
|
||||
%0 = fir.zero_bits !fir.ptr<!fir.array<?xnone>>
|
||||
%c0 = arith.constant 0 : index
|
||||
%1 = fir.shape %c0 : (index) -> !fir.shape<1>
|
||||
%2 = fir.embox %0(%1) : (!fir.ptr<!fir.array<?xnone>>, !fir.shape<1>) -> !fir.class<!fir.ptr<!fir.array<?xnone>>>
|
||||
fir.has_value %2 : !fir.class<!fir.ptr<!fir.array<?xnone>>>
|
||||
}
|
||||
|
||||
fir.global internal @_QFEy target : !fir.array<1xi32> {
|
||||
%0 = fir.undefined !fir.array<1xi32>
|
||||
fir.has_value %0 : !fir.array<1xi32>
|
||||
}
|
||||
|
||||
func.func private @_FortranAioBeginExternalListOutput(i32, !fir.ref<i8>, i32) -> !fir.ref<i8> attributes {fir.io, fir.runtime}
|
||||
func.func private @_FortranAioOutputDescriptor(!fir.ref<i8>, !fir.box<none>) -> i1 attributes {fir.io, fir.runtime}
|
||||
func.func private @_FortranAioEndIoStatement(!fir.ref<i8>) -> i32 attributes {fir.io, fir.runtime}
|
||||
fir.global linkonce @_QQcl.2E2F64756D6D792E66393000 constant : !fir.char<1,12> {
|
||||
%0 = fir.string_lit "./dummy.f90\00"(12) : !fir.char<1,12>
|
||||
fir.has_value %0 : !fir.char<1,12>
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user