[flang-commits] [flang] 4c5dee7 - [flang] Lowering fir.dispatch in the polymorphic op pass
via flang-commits
flang-commits at lists.llvm.org
Thu Mar 23 09:41:21 PDT 2023
Author: Renaud-K
Date: 2023-03-23T09:40:47-07:00
New Revision: 4c5dee7773dcc5ec1b7485dfba5ce5baa2355b2f
URL: https://github.com/llvm/llvm-project/commit/4c5dee7773dcc5ec1b7485dfba5ce5baa2355b2f
DIFF: https://github.com/llvm/llvm-project/commit/4c5dee7773dcc5ec1b7485dfba5ce5baa2355b2f.diff
LOG: [flang] Lowering fir.dispatch in the polymorphic op pass
Differential revision: https://reviews.llvm.org/D146594
Added:
Modified:
flang/include/flang/Semantics/runtime-type-info.h
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
flang/lib/Semantics/runtime-type-info.cpp
flang/test/Fir/dispatch.f90
flang/test/Lower/allocatable-polymorphic.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Semantics/runtime-type-info.h b/flang/include/flang/Semantics/runtime-type-info.h
index 76560b98b1c20..e27091cf32de0 100644
--- a/flang/include/flang/Semantics/runtime-type-info.h
+++ b/flang/include/flang/Semantics/runtime-type-info.h
@@ -42,6 +42,14 @@ RuntimeDerivedTypeTables BuildRuntimeDerivedTypeTables(SemanticsContext &);
/// to describe other derived types at runtime in flang descriptor.
constexpr char typeInfoBuiltinModule[]{"__fortran_type_info"};
+/// Name of the bindings descriptor component in the DerivedType type of the
+/// __Fortran_type_info module
+constexpr char bindingDescCompName[]{"binding"};
+
+/// Name of the __builtin_c_funptr component in the Binding type of the
+/// __Fortran_type_info module
+constexpr char procCompName[]{"proc"};
+
SymbolVector CollectBindings(const Scope &dtScope);
} // namespace Fortran::semantics
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 6b4591789c545..8ea8fa7290372 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -104,10 +104,8 @@ template <typename FromOp>
class FIROpConversion : public mlir::ConvertOpToLLVMPattern<FromOp> {
public:
explicit FIROpConversion(fir::LLVMTypeConverter &lowering,
- const fir::FIRToLLVMPassOptions &options,
- const fir::BindingTables &bindingTables)
- : mlir::ConvertOpToLLVMPattern<FromOp>(lowering), options(options),
- bindingTables(bindingTables) {}
+ const fir::FIRToLLVMPassOptions &options)
+ : mlir::ConvertOpToLLVMPattern<FromOp>(lowering), options(options) {}
protected:
mlir::Type convertType(mlir::Type ty) const {
@@ -358,7 +356,6 @@ class FIROpConversion : public mlir::ConvertOpToLLVMPattern<FromOp> {
}
const fir::FIRToLLVMPassOptions &options;
- const fir::BindingTables &bindingTables;
};
/// FIR conversion pattern template
@@ -970,131 +967,6 @@ struct ConvertOpConversion : public FIROpConversion<fir::ConvertOp> {
}
};
-/// Lower `fir.dispatch` operation. A virtual call to a method in a dispatch
-/// table.
-struct DispatchOpConversion : public FIROpConversion<fir::DispatchOp> {
- using FIROpConversion::FIROpConversion;
-
- mlir::LogicalResult
- matchAndRewrite(fir::DispatchOp dispatch, OpAdaptor adaptor,
- mlir::ConversionPatternRewriter &rewriter) const override {
- mlir::Location loc = dispatch.getLoc();
-
- if (bindingTables.empty())
- return emitError(loc) << "no binding tables found";
-
- // Get derived type information.
- mlir::Type declaredType =
- fir::getDerivedType(dispatch.getObject().getType().getEleTy());
- assert(declaredType.isa<fir::RecordType>() && "expecting fir.type");
- auto recordType = declaredType.dyn_cast<fir::RecordType>();
-
- // Lookup for the binding table.
- auto bindingsIter = bindingTables.find(recordType.getName());
- if (bindingsIter == bindingTables.end())
- return emitError(loc)
- << "cannot find binding table for " << recordType.getName();
-
- // Lookup for the binding.
- const fir::BindingTable &bindingTable = bindingsIter->second;
- auto bindingIter = bindingTable.find(dispatch.getMethod());
- if (bindingIter == bindingTable.end())
- return emitError(loc)
- << "cannot find binding for " << dispatch.getMethod();
- unsigned bindingIdx = bindingIter->second;
-
- mlir::Value passedObject = dispatch.getObject();
-
- auto module = dispatch.getOperation()->getParentOfType<mlir::ModuleOp>();
- mlir::Type typeDescTy;
- std::string typeDescName =
- fir::NameUniquer::getTypeDescriptorName(recordType.getName());
- if (auto global = module.lookupSymbol<fir::GlobalOp>(typeDescName)) {
- typeDescTy = convertType(global.getType());
- } else if (auto global =
- module.lookupSymbol<mlir::LLVM::GlobalOp>(typeDescName)) {
- // The global may have already been translated to LLVM.
- typeDescTy = global.getType();
- }
-
- unsigned typeDescFieldId = getTypeDescFieldId(passedObject.getType());
-
- auto descPtr = adaptor.getOperands()[0]
- .getType()
- .dyn_cast<mlir::LLVM::LLVMPointerType>();
-
- // TODO: the following loads from the type descriptor related
- // data structures must have proper TBAA access tags.
- // These loads cannot alias with any real data accesses nor
- // with any box accesses. Moreover, they can probably be marked
- // as reading from constant memory (fourth operand of a TBAA
- // tag may be set to true). These accesses probably deserve
- // separate sub-root in the TBAA graph.
-
- // Load the descriptor.
- auto desc = rewriter.create<mlir::LLVM::LoadOp>(
- loc, descPtr.getElementType(), adaptor.getOperands()[0]);
-
- // Load the type descriptor.
- auto typeDescPtr =
- rewriter.create<mlir::LLVM::ExtractValueOp>(loc, desc, typeDescFieldId);
- auto typeDesc =
- rewriter.create<mlir::LLVM::LoadOp>(loc, typeDescTy, typeDescPtr);
-
- // Load the bindings descriptor.
- auto typeDescStructTy = typeDescTy.dyn_cast<mlir::LLVM::LLVMStructType>();
- auto bindingDescType =
- typeDescStructTy.getBody()[0].dyn_cast<mlir::LLVM::LLVMStructType>();
- auto bindingDesc =
- rewriter.create<mlir::LLVM::ExtractValueOp>(loc, typeDesc, 0);
-
- // Load the correct binding.
- auto bindingType =
- bindingDescType.getBody()[0].dyn_cast<mlir::LLVM::LLVMPointerType>();
- auto baseBindingPtr = rewriter.create<mlir::LLVM::ExtractValueOp>(
- loc, bindingDesc, kAddrPosInBox);
- auto bindingPtr = rewriter.create<mlir::LLVM::GEPOp>(
- loc, bindingType, baseBindingPtr,
- llvm::ArrayRef<mlir::LLVM::GEPArg>{static_cast<int32_t>(bindingIdx)});
- auto binding = rewriter.create<mlir::LLVM::LoadOp>(
- loc, bindingType.getElementType(), bindingPtr);
-
- // Get the function type.
- llvm::SmallVector<mlir::Type> argTypes;
- for (mlir::Value operand : adaptor.getOperands().drop_front())
- argTypes.push_back(operand.getType());
- mlir::Type resultType;
- if (dispatch.getResults().empty())
- resultType = mlir::LLVM::LLVMVoidType::get(dispatch.getContext());
- else
- resultType = convertType(dispatch.getResults()[0].getType());
- auto fctType = mlir::LLVM::LLVMFunctionType::get(resultType, argTypes,
- /*isVarArg=*/false);
-
- // Get the function pointer.
- auto builtinFuncPtr =
- rewriter.create<mlir::LLVM::ExtractValueOp>(loc, binding, 0);
- auto funcAddr =
- rewriter.create<mlir::LLVM::ExtractValueOp>(loc, builtinFuncPtr, 0);
- auto funcPtr = rewriter.create<mlir::LLVM::IntToPtrOp>(
- loc, mlir::LLVM::LLVMPointerType::get(fctType), funcAddr);
-
- // Indirect calls are done with the function pointer as the first operand.
- llvm::SmallVector<mlir::Value> args;
- args.push_back(funcPtr);
- for (mlir::Value operand : adaptor.getOperands().drop_front())
- args.push_back(operand);
- auto callOp = rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(
- dispatch,
- dispatch.getResults().empty() ? mlir::TypeRange{}
- : fctType.getReturnType(),
- "", args);
- callOp.removeCalleeAttr(); // Indirect calls do not have callee attr.
-
- return mlir::success();
- }
-};
-
/// `fir.disptach_table` operation has no specific CodeGen. The operation is
/// only used to carry information during FIR to FIR passes.
struct DispatchTableOpConversion
@@ -3656,9 +3528,8 @@ struct NegcOpConversion : public FIROpConversion<fir::NegcOp> {
template <typename FromOp>
struct MustBeDeadConversion : public FIROpConversion<FromOp> {
explicit MustBeDeadConversion(fir::LLVMTypeConverter &lowering,
- const fir::FIRToLLVMPassOptions &options,
- const fir::BindingTables &bindingTables)
- : FIROpConversion<FromOp>(lowering, options, bindingTables) {}
+ const fir::FIRToLLVMPassOptions &options)
+ : FIROpConversion<FromOp>(lowering, options) {}
using OpAdaptor = typename FromOp::Adaptor;
mlir::LogicalResult
@@ -3768,9 +3639,6 @@ class FIRToLLVMLowering
if (mlir::failed(runPipeline(mathConvertionPM, mod)))
return signalPassFailure();
- fir::BindingTables bindingTables;
- fir::buildBindingTables(bindingTables, mod);
-
auto *context = getModule().getContext();
fir::LLVMTypeConverter typeConverter{getModule(),
options.applyTBAA || applyTBAA};
@@ -3783,11 +3651,11 @@ class FIRToLLVMLowering
BoxProcHostOpConversion, BoxRankOpConversion, BoxTypeCodeOpConversion,
BoxTypeDescOpConversion, CallOpConversion, CmpcOpConversion,
ConstcOpConversion, ConvertOpConversion, CoordinateOpConversion,
- DispatchOpConversion, DispatchTableOpConversion, DTEntryOpConversion,
- DivcOpConversion, EmboxOpConversion, EmboxCharOpConversion,
- EmboxProcOpConversion, ExtractValueOpConversion, FieldIndexOpConversion,
- FirEndOpConversion, FreeMemOpConversion, GlobalLenOpConversion,
- GlobalOpConversion, HasValueOpConversion, InsertOnRangeOpConversion,
+ DispatchTableOpConversion, DTEntryOpConversion, DivcOpConversion,
+ EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion,
+ ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion,
+ FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion,
+ HasValueOpConversion, InsertOnRangeOpConversion,
InsertValueOpConversion, IsPresentOpConversion,
LenParamIndexOpConversion, LoadOpConversion, MulcOpConversion,
NegcOpConversion, NoReassocOpConversion, SelectCaseOpConversion,
@@ -3797,7 +3665,7 @@ class FIRToLLVMLowering
SubcOpConversion, TypeDescOpConversion, UnboxCharOpConversion,
UnboxProcOpConversion, UndefOpConversion, UnreachableOpConversion,
XArrayCoorOpConversion, XEmboxOpConversion, XReboxOpConversion,
- ZeroOpConversion>(typeConverter, options, bindingTables);
+ ZeroOpConversion>(typeConverter, options);
mlir::populateFuncToLLVMConversionPatterns(typeConverter, pattern);
mlir::populateOpenMPToLLVMConversionPatterns(typeConverter, pattern);
mlir::arith::populateArithToLLVMConversionPatterns(typeConverter, pattern);
diff --git a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
index f7ee2c19d45ac..2f8cdf7934436 100644
--- a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
+++ b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
@@ -6,18 +6,25 @@
//
//===----------------------------------------------------------------------===//
+#include "flang/Lower/BuiltinModules.h"
+#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Support/TypeCode.h"
+#include "flang/Optimizer/Support/Utils.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "flang/Runtime/derived-api.h"
+#include "flang/Semantics/runtime-type-info.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/BuiltinOps.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/SmallSet.h"
@@ -72,6 +79,147 @@ class SelectTypeConv : public OpConversionPattern<fir::SelectTypeOp> {
std::mutex *moduleMutex;
};
+/// Lower `fir.dispatch` operation. A virtual call to a method in a dispatch
+/// table.
+struct DispatchOpConv : public OpConversionPattern<fir::DispatchOp> {
+ using OpConversionPattern<fir::DispatchOp>::OpConversionPattern;
+
+ DispatchOpConv(mlir::MLIRContext *ctx, const BindingTables &bindingTables)
+ : mlir::OpConversionPattern<fir::DispatchOp>(ctx),
+ bindingTables(bindingTables) {}
+
+ mlir::LogicalResult
+ matchAndRewrite(fir::DispatchOp dispatch, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ mlir::Location loc = dispatch.getLoc();
+
+ if (bindingTables.empty())
+ return emitError(loc) << "no binding tables found";
+
+ // Get derived type information.
+ mlir::Type declaredType =
+ fir::getDerivedType(dispatch.getObject().getType().getEleTy());
+ assert(declaredType.isa<fir::RecordType>() && "expecting fir.type");
+ auto recordType = declaredType.dyn_cast<fir::RecordType>();
+
+ // Lookup for the binding table.
+ auto bindingsIter = bindingTables.find(recordType.getName());
+ if (bindingsIter == bindingTables.end())
+ return emitError(loc)
+ << "cannot find binding table for " << recordType.getName();
+
+ // Lookup for the binding.
+ const BindingTable &bindingTable = bindingsIter->second;
+ auto bindingIter = bindingTable.find(dispatch.getMethod());
+ if (bindingIter == bindingTable.end())
+ return emitError(loc)
+ << "cannot find binding for " << dispatch.getMethod();
+ unsigned bindingIdx = bindingIter->second;
+
+ mlir::Value passedObject = dispatch.getObject();
+
+ auto module = dispatch.getOperation()->getParentOfType<mlir::ModuleOp>();
+ Type typeDescTy;
+ std::string typeDescName =
+ NameUniquer::getTypeDescriptorName(recordType.getName());
+ if (auto global = module.lookupSymbol<fir::GlobalOp>(typeDescName)) {
+ typeDescTy = global.getType();
+ }
+
+ // clang-format off
+ // Before:
+ // fir.dispatch "proc1"(%11 :
+ // !fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>)
+
+ // After:
+ // %12 = fir.box_tdesc %11 : (!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>) -> !fir.tdesc<none>
+ // %13 = fir.convert %12 : (!fir.tdesc<none>) -> !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype>>
+ // %14 = fir.field_index binding, !fir.type<_QM__fortran_type_infoTderivedtype>
+ // %15 = fir.coordinate_of %13, %14 : (!fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype>>, !fir.field) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QM__fortran_type_infoTbinding>>>>>
+ // %bindings = fir.load %15 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QM__fortran_type_infoTbinding>>>>>
+ // %16 = fir.box_addr %bindings : (!fir.box<!fir.ptr<!fir.array<?x!fir.type<_QM__fortran_type_infoTbinding>>>>) -> !fir.ptr<!fir.array<?x!fir.type<_QM__fortran_type_infoTbinding>>>
+ // %17 = fir.coordinate_of %16, %c0 : (!fir.ptr<!fir.array<?x!fir.type<_QM__fortran_type_infoTbinding>>>, index) -> !fir.ref<!fir.type<_QM__fortran_type_infoTbinding>>
+ // %18 = fir.field_index proc, !fir.type<_QM__fortran_type_infoTbinding>
+ // %19 = fir.coordinate_of %17, %18 : (!fir.ref<!fir.type<_QM__fortran_type_infoTbinding>>, !fir.field) -> !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr>>
+ // %20 = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_funptr>
+ // %21 = fir.coordinate_of %19, %20 : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_funptr>>, !fir.field) -> !fir.ref<i64>
+ // %22 = fir.load %21 : !fir.ref<i64>
+ // %23 = fir.convert %22 : (i64) -> (() -> ())
+ // fir.call %23() : () -> ()
+ // clang-format on
+
+ // Load the descriptor.
+ mlir::Type fieldTy = fir::FieldType::get(rewriter.getContext());
+ mlir::Type tdescType =
+ fir::TypeDescType::get(mlir::NoneType::get(rewriter.getContext()));
+ mlir::Value boxDesc =
+ rewriter.create<fir::BoxTypeDescOp>(loc, tdescType, passedObject);
+ boxDesc = rewriter.create<fir::ConvertOp>(
+ loc, fir::ReferenceType::get(typeDescTy), boxDesc);
+
+ // Load the bindings descriptor.
+ auto bindingsCompName = Fortran::semantics::bindingDescCompName;
+ fir::RecordType typeDescRecTy = typeDescTy.cast<fir::RecordType>();
+ mlir::Value field = rewriter.create<fir::FieldIndexOp>(
+ loc, fieldTy, bindingsCompName, typeDescRecTy, mlir::ValueRange{});
+ mlir::Type coorTy =
+ fir::ReferenceType::get(typeDescRecTy.getType(bindingsCompName));
+ mlir::Value bindingBoxAddr =
+ rewriter.create<fir::CoordinateOp>(loc, coorTy, boxDesc, field);
+ mlir::Value bindingBox = rewriter.create<fir::LoadOp>(loc, bindingBoxAddr);
+
+ // Load the correct binding.
+ mlir::Value bindings = rewriter.create<fir::BoxAddrOp>(loc, bindingBox);
+ fir::RecordType bindingTy =
+ fir::unwrapIfDerived(bindingBox.getType().cast<fir::BaseBoxType>());
+ mlir::Type bindingAddrTy = fir::ReferenceType::get(bindingTy);
+ mlir::Value bindingIdxVal = rewriter.create<mlir::arith::ConstantOp>(
+ loc, rewriter.getIndexType(), rewriter.getIndexAttr(bindingIdx));
+ mlir::Value bindingAddr = rewriter.create<fir::CoordinateOp>(
+ loc, bindingAddrTy, bindings, bindingIdxVal);
+
+ // Get the function pointer.
+ auto procCompName = Fortran::semantics::procCompName;
+ mlir::Value procField = rewriter.create<fir::FieldIndexOp>(
+ loc, fieldTy, procCompName, bindingTy, mlir::ValueRange{});
+ fir::RecordType procTy =
+ bindingTy.getType(procCompName).cast<fir::RecordType>();
+ mlir::Type procRefTy = fir::ReferenceType::get(procTy);
+ mlir::Value procRef = rewriter.create<fir::CoordinateOp>(
+ loc, procRefTy, bindingAddr, procField);
+
+ auto addressFieldName = Fortran::lower::builtin::cptrFieldName;
+ mlir::Value addressField = rewriter.create<fir::FieldIndexOp>(
+ loc, fieldTy, addressFieldName, procTy, mlir::ValueRange{});
+ mlir::Type addressTy = procTy.getType(addressFieldName);
+ mlir::Type addressRefTy = fir::ReferenceType::get(addressTy);
+ mlir::Value addressRef = rewriter.create<fir::CoordinateOp>(
+ loc, addressRefTy, procRef, addressField);
+ mlir::Value address = rewriter.create<fir::LoadOp>(loc, addressRef);
+
+ // Get the function type.
+ llvm::SmallVector<mlir::Type> argTypes;
+ for (mlir::Value operand : dispatch.getArgs())
+ argTypes.push_back(operand.getType());
+ llvm::SmallVector<mlir::Type> resTypes;
+ if (!dispatch.getResults().empty())
+ resTypes.push_back(dispatch.getResults()[0].getType());
+
+ mlir::Type funTy =
+ mlir::FunctionType::get(rewriter.getContext(), argTypes, resTypes);
+ mlir::Value funcPtr = rewriter.create<fir::ConvertOp>(loc, funTy, address);
+
+ // Make the call.
+ llvm::SmallVector<mlir::Value> args{funcPtr};
+ args.append(dispatch.getArgs().begin(), dispatch.getArgs().end());
+ rewriter.replaceOpWithNewOp<fir::CallOp>(dispatch, resTypes, nullptr, args);
+ return mlir::success();
+ }
+
+private:
+ BindingTables bindingTables;
+};
+
/// Convert FIR structured control flow ops to CFG ops.
class PolymorphicOpConversion
: public fir::impl::PolymorphicOpConversionBase<PolymorphicOpConversion> {
@@ -83,14 +231,21 @@ class PolymorphicOpConversion
void runOnOperation() override {
auto *context = &getContext();
+ auto mod = getOperation()->getParentOfType<ModuleOp>();
mlir::RewritePatternSet patterns(context);
+
+ BindingTables bindingTables;
+ buildBindingTables(bindingTables, mod);
+
patterns.insert<SelectTypeConv>(context, moduleMutex);
+ patterns.insert<DispatchOpConv>(context, bindingTables);
mlir::ConversionTarget target(*context);
target.addLegalDialect<mlir::AffineDialect, mlir::cf::ControlFlowDialect,
FIROpsDialect, mlir::func::FuncDialect>();
// apply the patterns
target.addIllegalOp<SelectTypeOp>();
+ target.addIllegalOp<DispatchOp>();
target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
if (mlir::failed(mlir::applyPartialConversion(getOperation(), target,
std::move(patterns)))) {
diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp
index 29f63524b5c07..5e57c70c42fbb 100644
--- a/flang/lib/Semantics/runtime-type-info.cpp
+++ b/flang/lib/Semantics/runtime-type-info.cpp
@@ -151,7 +151,8 @@ RuntimeTableBuilder::RuntimeTableBuilder(
: context_{c}, tables_{t}, derivedTypeSchema_{GetSchema("derivedtype")},
componentSchema_{GetSchema("component")}, procPtrSchema_{GetSchema(
"procptrcomponent")},
- valueSchema_{GetSchema("value")}, bindingSchema_{GetSchema("binding")},
+ valueSchema_{GetSchema("value")}, bindingSchema_{GetSchema(
+ bindingDescCompName)},
specialSchema_{GetSchema("specialbinding")}, deferredEnum_{GetEnumValue(
"deferred")},
explicitEnum_{GetEnumValue("explicit")}, lenParameterEnum_{GetEnumValue(
@@ -562,7 +563,7 @@ const Symbol *RuntimeTableBuilder::DescribeType(Scope &dtScope) {
if (!isAbstractType) {
std::vector<evaluate::StructureConstructor> bindings{
DescribeBindings(dtScope, scope)};
- AddValue(dtValues, derivedTypeSchema_, "binding"s,
+ AddValue(dtValues, derivedTypeSchema_, bindingDescCompName,
SaveDerivedPointerTarget(scope, SaveObjectName(".v."s + distinctName),
std::move(bindings),
evaluate::ConstantSubscripts{
@@ -982,7 +983,7 @@ RuntimeTableBuilder::DescribeBindings(const Scope &dtScope, Scope &scope) {
std::vector<evaluate::StructureConstructor> result;
for (const SymbolRef &ref : CollectBindings(dtScope)) {
evaluate::StructureConstructorValues values;
- AddValue(values, bindingSchema_, "proc"s,
+ AddValue(values, bindingSchema_, procCompName,
SomeExpr{evaluate::ProcedureDesignator{
ref.get().get<ProcBindingDetails>().symbol()}});
AddValue(values, bindingSchema_, "name"s,
@@ -1152,7 +1153,7 @@ void RuntimeTableBuilder::DescribeSpecialProc(
values, specialSchema_, "which"s, SomeExpr{std::move(which.value())});
AddValue(values, specialSchema_, "isargdescriptorset"s,
IntExpr<1>(isArgDescriptorSet));
- AddValue(values, specialSchema_, "proc"s,
+ AddValue(values, specialSchema_, procCompName,
SomeExpr{evaluate::ProcedureDesignator{specific}});
// index might already be present in the case of an override
specials.emplace(*index,
diff --git a/flang/test/Fir/dispatch.f90 b/flang/test/Fir/dispatch.f90
index dcb52bed7d967..933c769d3e169 100644
--- a/flang/test/Fir/dispatch.f90
+++ b/flang/test/Fir/dispatch.f90
@@ -1,4 +1,4 @@
-! RUN: bbc -polymorphic-type -emit-fir %s -o - | tco | FileCheck %s
+! RUN: bbc -polymorphic-type -emit-fir %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s
! RUN: bbc -polymorphic-type -emit-fir %s -o - | FileCheck %s --check-prefix=BT
! Tests codegen of fir.dispatch operation. This test is intentionally run from
@@ -182,105 +182,123 @@ program test_type_to_class
end
-! CHECK-LABEL: define void @_QMdispatch1Pdisplay_class(
-! CHECK-SAME: ptr %[[CLASS:.*]])
+! CHECK-LABEL: func.func @_QMdispatch1Pdisplay_class(
+! CHECK-SAME: %[[ARG:.*]]: [[CLASS:!fir.class<.*>>]]
-! CHECK-DAG: %[[INT32:.*]] = alloca i32, i64 1
-! CHECK-DAG: %[[REAL:.*]] = alloca float, i64 1
-! CHECK-DAG: %[[I:.*]] = alloca i32, i64 1
+! CHECK-DAG: %[[INT32:.*]] = fir.alloca i32
+! CHECK-DAG: %[[REAL:.*]] = fir.alloca f32
+! CHECK-DAG: %[[I:.*]] = fir.alloca i32
! Check dynamic dispatch equal to `call p%display2()` with binding index = 2.
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 2
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: call void %[[FUNC_PTR]](ptr %[[CLASS]])
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c2 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> (([[CLASS]]) -> ())
+! CHECK: fir.call %[[FUNC_PTR]](%[[ARG]]) : ([[CLASS]]) -> ()
! Check dynamic dispatch equal to `call p%display1()` with binding index = 1.
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 1
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: call void %[[FUNC_PTR]](ptr %[[CLASS]])
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c1 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> (([[CLASS]]) -> ())
+! CHECK: fir.call %[[FUNC_PTR]](%[[ARG]]) : ([[CLASS]]) -> ()
! Check dynamic dispatch equal to `call p%aproc()` with binding index = 0.
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 0
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: call void %[[FUNC_PTR]](ptr %[[CLASS]])
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c0 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> (([[CLASS]]) -> ())
+! CHECK: fir.call %[[FUNC_PTR]](%[[ARG]]) : ([[CLASS]]) -> ()
! Check dynamic dispatch of a function with result.
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 3
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: %[[RET:.*]] = call i32 %[[FUNC_PTR]](ptr %[[CLASS]])
-! CHECK: store i32 %[[RET]], ptr %[[I]]
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c3 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> (([[CLASS]]) -> i32)
+! CHECK: %[[RES:.*]] = fir.call %[[FUNC_PTR]](%[[ARG]]) : ([[CLASS]]) -> i32
! Check dynamic dispatch of call with passed-object and additional argument
-! CHECK: store float 2.500000e+00, ptr %[[REAL]]
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 6
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: call void %[[FUNC_PTR]](ptr %[[CLASS]], ptr %[[REAL]])
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c6 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> (([[CLASS]], !fir.ref<f32>) -> ())
+! CHECK: fir.call %[[FUNC_PTR]](%[[ARG]], %[[REAL]]) : ([[CLASS]], !fir.ref<f32>) -> ()
! Check dynamic dispatch of a call with NOPASS
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 4
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: call void %[[FUNC_PTR]]()
-
-! CHECK: store i32 1, ptr %[[INT32]]
-! CHECK: %[[LOADED_CLASS:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[CLASS]]
-! CHECK: %[[TYPEDESCPTR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOADED_CLASS]], 7
-! CHECK: %[[LOADED_TYPEDESC:.*]] = load %_QM__fortran_type_infoTderivedtype, ptr %[[TYPEDESCPTR]]
-! CHECK: %[[DT:.*]] = extractvalue %_QM__fortran_type_infoTderivedtype %[[LOADED_TYPEDESC]], 0
-! CHECK: %[[BINDING_BASE_ADDR:.*]] = extractvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[DT]], 0
-! CHECK: %[[BINDING_PTR:.*]] = getelementptr %_QM__fortran_type_infoTbinding, ptr %[[BINDING_BASE_ADDR]], i32 5
-! CHECK: %[[LOADED_BINDING:.*]] = load %_QM__fortran_type_infoTbinding, ptr %[[BINDING_PTR]]
-! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = extractvalue %_QM__fortran_type_infoTbinding %[[LOADED_BINDING]], 0
-! CHECK: %[[FUNC_ADDR:.*]] = extractvalue %_QM__fortran_builtinsT__builtin_c_funptr %[[BUILTIN_FUNC_PTR]], 0
-! CHECK: %[[FUNC_PTR:.*]] = inttoptr i64 %[[FUNC_ADDR]] to ptr
-! CHECK: call void %[[FUNC_PTR]](ptr %[[INT32]], ptr %[[CLASS]])
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c4 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> (() -> ())
+! CHECK: fir.call %[[FUNC_PTR]]() : () -> ()
+
+! CHECK: %[[BOXDESC:.*]] = fir.box_tdesc %[[ARG]] : ([[CLASS]]) -> !fir.tdesc<none>
+! CHECK: %[[TYPEDESCPTR:.*]] = fir.convert %[[BOXDESC]] : (!fir.tdesc<none>) -> !fir.ref<[[TYPEINFO:!fir.type<_QM__fortran_type_infoTderivedtype{.*}>]]>
+! CHECK: %[[BINDING_FIELD:.*]] = fir.field_index binding, [[TYPEINFO]]
+! CHECK: %[[BINDING_BOX_ADDR:.*]] = fir.coordinate_of %[[TYPEDESCPTR]], %[[BINDING_FIELD]] : (!fir.ref<[[TYPEINFO]]>, !fir.field) -> !fir.ref<[[BINDING_BOX_TYPE:.*]]>
+! CHECK: %[[BINDING_BOX:.*]] = fir.load %[[BINDING_BOX_ADDR]] : !fir.ref<[[BINDING_BOX_TYPE]]>
+! CHECK: %[[BINDING_BASE_ADDR:.*]] = fir.box_addr %[[BINDING_BOX]] : ([[BINDING_BOX_TYPE]]) -> !fir.ptr<[[BINDINGSINFO:.*]]>
+! CHECK: %[[BINDING_PTR:.*]] = fir.coordinate_of %[[BINDING_BASE_ADDR]], %c5 : (!fir.ptr<[[BINDINGSINFO]]>, index) -> !fir.ref<[[BINDINGINFO:.*]]>
+! CHECK: %[[PROC_FIELD:.*]] = fir.field_index proc, [[BINDINGINFO]]
+! CHECK: %[[BUILTIN_FUNC_PTR:.*]] = fir.coordinate_of %[[BINDING_PTR]], %[[PROC_FIELD]] : ({{.*}}) -> !fir.ref<[[BUILTIN_FUNC_TYPE:.*]]>
+! CHECK: %[[ADDRESS_FIELD:.*]] = fir.field_index __address, [[BUILTIN_FUNC_TYPE]]
+! CHECK: %[[FUNC_ADDR_PTR:.*]] = fir.coordinate_of %[[BUILTIN_FUNC_PTR]], %[[ADDRESS_FIELD]]
+! CHECK: %[[FUNC_ADDR:.*]] = fir.load %[[FUNC_ADDR_PTR]] : !fir.ref<i64>
+! CHECK: %[[FUNC_PTR:.*]] = fir.convert %[[FUNC_ADDR]] : (i64) -> ((!fir.ref<i32>, [[CLASS]]) -> ())
+! CHECK: fir.call %[[FUNC_PTR]](%[[INT32]], %[[ARG]]) : (!fir.ref<i32>, [[CLASS]]) -> ()
! CHECK-LABEL: _QMdispatch1Pno_pass_array
! CHECK-LABEL: _QMdispatch1Pno_pass_array_allocatable
diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90
index b129c7c8cdbe1..c3c01a39b8606 100644
--- a/flang/test/Lower/allocatable-polymorphic.f90
+++ b/flang/test/Lower/allocatable-polymorphic.f90
@@ -586,9 +586,9 @@ program test_alloc
! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[C1_LOAD]], ptr %{{.*}}
! LLVM: %[[GEP_TDESC_C1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 7
! LLVM: %[[TDESC_C1:.*]] = load ptr, ptr %[[GEP_TDESC_C1]]
-! LLVM: %[[ELEM_SIZE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.}}, i32 0, i32 1
+! LLVM: %[[ELEM_SIZE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 1
! LLVM: %[[ELEM_SIZE:.*]] = load i64, ptr %[[ELEM_SIZE_GEP]]
-! LLVM: %[[TYPE_CODE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.}}, i32 0, i32 4
+! LLVM: %[[TYPE_CODE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 4
! LLVM: %[[TYPE_CODE:.*]] = load i32, ptr %[[TYPE_CODE_GEP]]
! LLVM: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } undef, i64 %[[ELEM_SIZE]], 1
! LLVM: %[[TRUNC_TYPE_CODE:.*]] = trunc i32 %[[TYPE_CODE]] to i8
@@ -600,9 +600,9 @@ program test_alloc
! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOAD_C2]], ptr %{{.*}}
! LLVM: %[[GEP_TDESC_C2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 7
! LLVM: %[[TDESC_C2:.*]] = load ptr, ptr %[[GEP_TDESC_C2]]
-! LLVM: %[[ELEM_SIZE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.}}, i32 0, i32 1
+! LLVM: %[[ELEM_SIZE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 1
! LLVM: %[[ELEM_SIZE:.*]] = load i64, ptr %[[ELEM_SIZE_GEP]]
-! LLVM: %[[TYPE_CODE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.}}, i32 0, i32 4
+! LLVM: %[[TYPE_CODE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}}, i32 0, i32 4
! LLVM: %[[TYPE_CODE:.*]] = load i32, ptr %[[TYPE_CODE_GEP]]
! LLVM: %{{.*}} = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } undef, i64 %[[ELEM_SIZE]], 1
! LLVM: %[[TRUNC_TYPE_CODE:.*]] = trunc i32 %[[TYPE_CODE]] to i8
More information about the flang-commits
mailing list