Skip to content

Commit 6393d2e

Browse files
committed
[flang] Create fir.dispatch_table and fir.dt_entry operations
Create the fir.dispatch_table operation based on semantics information. The fir.dispatch_table will be used for static devirtualization as well as for fir.select_type conversion. Depends on D138129 Reviewed By: jeanPerier, PeteSteinfeld Differential Revision: https://reviews.llvm.org/D138131
1 parent ded52a4 commit 6393d2e

File tree

11 files changed

+227
-37
lines changed

11 files changed

+227
-37
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ class AbstractConverter {
204204
virtual void registerRuntimeTypeInfo(mlir::Location loc,
205205
SymbolRef typeInfoSym) = 0;
206206

207+
virtual void registerDispatchTableInfo(
208+
mlir::Location loc,
209+
const Fortran::semantics::DerivedTypeSpec *typeSpec) = 0;
210+
207211
//===--------------------------------------------------------------------===//
208212
// Locations
209213
//===--------------------------------------------------------------------===//

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
212212
bodyBuilder, linkage);
213213
}
214214

215+
/// Create a fir::DispatchTable operation.
216+
fir::DispatchTableOp createDispatchTableOp(mlir::Location loc,
217+
llvm::StringRef name,
218+
llvm::StringRef parentName);
219+
215220
/// Convert a StringRef string into a fir::StringLitOp.
216221
fir::StringLitOp createStringLitOp(mlir::Location loc,
217222
llvm::StringRef string);

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,26 +2804,30 @@ def fir_DispatchTableOp : fir_Op<"dispatch_table",
28042804
```
28052805
}];
28062806

2807+
let arguments = (ins
2808+
SymbolNameAttr:$sym_name,
2809+
OptionalAttr<StrAttr>:$parent
2810+
);
2811+
28072812
let hasCustomAssemblyFormat = 1;
28082813
let hasVerifier = 1;
28092814

2810-
let regions = (region SizedRegion<1>:$region);
2815+
let regions = (region AnyRegion:$region);
28112816

28122817
let skipDefaultBuilders = 1;
28132818
let builders = [
28142819
OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
2815-
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs),
2816-
[{
2817-
$_state.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
2818-
$_builder.getStringAttr(name));
2819-
$_state.addAttributes(attrs);
2820-
}]>
2820+
"llvm::StringRef":$parent,
2821+
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>
28212822
];
28222823

28232824
let extraClassDeclaration = [{
28242825
/// Append a dispatch table entry to the table.
28252826
void appendTableEntry(mlir::Operation *op);
28262827

2828+
static constexpr llvm::StringRef getParentAttrNameStr() { return "parent"; }
2829+
static constexpr llvm::StringRef getExtendsKeyword() { return "extends"; }
2830+
28272831
mlir::Block &getBlock() {
28282832
return getRegion().front();
28292833
}

flang/lib/Lower/Bridge.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@
4646
#include "flang/Optimizer/Transforms/Passes.h"
4747
#include "flang/Parser/parse-tree.h"
4848
#include "flang/Runtime/iostat.h"
49+
#include "flang/Semantics/runtime-type-info.h"
4950
#include "flang/Semantics/tools.h"
5051
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
5152
#include "mlir/IR/PatternMatch.h"
5253
#include "mlir/Parser/Parser.h"
5354
#include "mlir/Transforms/RegionUtils.h"
55+
#include "llvm/ADT/StringSet.h"
5456
#include "llvm/Support/CommandLine.h"
5557
#include "llvm/Support/Debug.h"
5658
#include "llvm/Support/ErrorHandling.h"
@@ -193,6 +195,67 @@ class RuntimeTypeInfoConverter {
193195
llvm::SmallSetVector<Fortran::semantics::SymbolRef, 64> seen;
194196
};
195197

198+
class DispatchTableConverter {
199+
struct DispatchTableInfo {
200+
const Fortran::semantics::DerivedTypeSpec *typeSpec;
201+
mlir::Location loc;
202+
};
203+
204+
public:
205+
void registerTypeSpec(mlir::Location loc,
206+
const Fortran::semantics::DerivedTypeSpec *typeSpec) {
207+
assert(typeSpec && "type spec is null");
208+
std::string dtName = Fortran::lower::mangle::mangleName(*typeSpec);
209+
if (seen.contains(dtName) || dtName.find("__fortran") != std::string::npos)
210+
return;
211+
seen.insert(dtName);
212+
registeredDispatchTableInfo.emplace_back(DispatchTableInfo{typeSpec, loc});
213+
}
214+
215+
void createDispatchTableOps(Fortran::lower::AbstractConverter &converter) {
216+
for (const DispatchTableInfo &info : registeredDispatchTableInfo) {
217+
std::string dtName = Fortran::lower::mangle::mangleName(*info.typeSpec);
218+
const Fortran::semantics::DerivedTypeSpec *parent =
219+
Fortran::evaluate::GetParentTypeSpec(*info.typeSpec);
220+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
221+
fir::DispatchTableOp dt = builder.createDispatchTableOp(
222+
info.loc, dtName,
223+
parent ? Fortran::lower::mangle::mangleName(*parent) : "");
224+
auto insertPt = builder.saveInsertionPoint();
225+
226+
std::vector<const Fortran::semantics::Symbol *> bindings =
227+
Fortran::semantics::CollectBindings(*info.typeSpec->scope());
228+
229+
if (!bindings.empty())
230+
builder.createBlock(&dt.getRegion());
231+
232+
for (const Fortran::semantics::Symbol *binding : bindings) {
233+
const auto *details =
234+
binding->detailsIf<Fortran::semantics::ProcBindingDetails>();
235+
std::string bindingName =
236+
Fortran::lower::mangle::mangleName(details->symbol());
237+
builder.create<fir::DTEntryOp>(
238+
info.loc,
239+
mlir::StringAttr::get(builder.getContext(),
240+
binding->name().ToString()),
241+
mlir::SymbolRefAttr::get(builder.getContext(), bindingName));
242+
}
243+
if (!bindings.empty())
244+
builder.create<fir::FirEndOp>(info.loc);
245+
builder.restoreInsertionPoint(insertPt);
246+
}
247+
registeredDispatchTableInfo.clear();
248+
}
249+
250+
private:
251+
/// Store the semantic DerivedTypeSpec that will be required to generate the
252+
/// dispatch table.
253+
llvm::SmallVector<DispatchTableInfo> registeredDispatchTableInfo;
254+
255+
/// Track processed type specs to avoid multiple creation.
256+
llvm::StringSet<> seen;
257+
};
258+
196259
using IncrementLoopNestInfo = llvm::SmallVector<IncrementLoopInfo, 8>;
197260
} // namespace
198261

@@ -270,6 +333,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
270333
createGlobalOutsideOfFunctionLowering(
271334
[&]() { runtimeTypeInfoConverter.createTypeInfoGlobals(*this); });
272335

336+
/// Create the dispatch tables for derived types.
337+
createGlobalOutsideOfFunctionLowering(
338+
[&]() { dispatchTableConverter.createDispatchTableOps(*this); });
339+
273340
// Create the list of any environment defaults for the runtime to set. The
274341
// runtime default list is only created if there is a main program to ensure
275342
// it only happens once and to provide consistent results if multiple files
@@ -745,6 +812,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
745812
runtimeTypeInfoConverter.registerTypeInfoSymbol(*this, loc, typeInfoSym);
746813
}
747814

815+
void registerDispatchTableInfo(
816+
mlir::Location loc,
817+
const Fortran::semantics::DerivedTypeSpec *typeSpec) override final {
818+
dispatchTableConverter.registerTypeSpec(loc, typeSpec);
819+
}
820+
748821
private:
749822
FirConverter() = delete;
750823
FirConverter(const FirConverter &) = delete;
@@ -3591,6 +3664,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
35913664
Fortran::lower::SymMap localSymbols;
35923665
Fortran::parser::CharBlock currentPosition;
35933666
RuntimeTypeInfoConverter runtimeTypeInfoConverter;
3667+
DispatchTableConverter dispatchTableConverter;
35943668

35953669
/// WHERE statement/construct mask expression stack.
35963670
Fortran::lower::ImplicitIterSpace implicitIterSpace;

flang/lib/Lower/ConvertType.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ struct TypeBuilder {
340340
}
341341
LLVM_DEBUG(llvm::dbgs() << "derived type: " << rec << '\n');
342342

343+
converter.registerDispatchTableInfo(loc, &tySpec);
344+
343345
// Generate the type descriptor object if any
344346
if (const Fortran::semantics::Scope *derivedScope =
345347
tySpec.scope() ? tySpec.scope() : tySpec.typeSymbol().scope())

flang/lib/Optimizer/Builder/FIRBuilder.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal(
271271
return glob;
272272
}
273273

274+
fir::DispatchTableOp fir::FirOpBuilder::createDispatchTableOp(
275+
mlir::Location loc, llvm::StringRef name, llvm::StringRef parentName) {
276+
auto module = getModule();
277+
auto insertPt = saveInsertionPoint();
278+
if (auto dt = module.lookupSymbol<fir::DispatchTableOp>(name))
279+
return dt;
280+
setInsertionPoint(module.getBody(), module.getBody()->end());
281+
auto dt = create<fir::DispatchTableOp>(loc, name, mlir::Type{}, parentName);
282+
restoreInsertionPoint(insertPt);
283+
return dt;
284+
}
285+
274286
mlir::Value
275287
fir::FirOpBuilder::convertWithSemantics(mlir::Location loc, mlir::Type toTy,
276288
mlir::Value val,

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,30 +1051,30 @@ struct DispatchOpConversion : public FIROpConversion<fir::DispatchOp> {
10511051
}
10521052
};
10531053

1054-
/// Lower `fir.dispatch_table` operation. The dispatch table for a Fortran
1055-
/// derived type.
1054+
/// `fir.disptach_table` operation has no specific CodeGen. The operation is
1055+
/// only used to carry information during FIR to FIR passes.
10561056
struct DispatchTableOpConversion
10571057
: public FIROpConversion<fir::DispatchTableOp> {
10581058
using FIROpConversion::FIROpConversion;
10591059

10601060
mlir::LogicalResult
1061-
matchAndRewrite(fir::DispatchTableOp dispTab, OpAdaptor adaptor,
1061+
matchAndRewrite(fir::DispatchTableOp op, OpAdaptor,
10621062
mlir::ConversionPatternRewriter &rewriter) const override {
1063-
TODO(dispTab.getLoc(), "fir.dispatch_table codegen");
1064-
return mlir::failure();
1063+
rewriter.eraseOp(op);
1064+
return mlir::success();
10651065
}
10661066
};
10671067

1068-
/// Lower `fir.dt_entry` operation. An entry in a dispatch table; binds a
1069-
/// method-name to a function.
1068+
/// `fir.dt_entry` operation has no specific CodeGen. The operation is only used
1069+
/// to carry information during FIR to FIR passes.
10701070
struct DTEntryOpConversion : public FIROpConversion<fir::DTEntryOp> {
10711071
using FIROpConversion::FIROpConversion;
10721072

10731073
mlir::LogicalResult
1074-
matchAndRewrite(fir::DTEntryOp dtEnt, OpAdaptor adaptor,
1074+
matchAndRewrite(fir::DTEntryOp op, OpAdaptor,
10751075
mlir::ConversionPatternRewriter &rewriter) const override {
1076-
TODO(dtEnt.getLoc(), "fir.dt_entry codegen");
1077-
return mlir::failure();
1076+
rewriter.eraseOp(op);
1077+
return mlir::success();
10781078
}
10791079
};
10801080

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,14 +1092,19 @@ void fir::DispatchTableOp::appendTableEntry(mlir::Operation *op) {
10921092
mlir::ParseResult fir::DispatchTableOp::parse(mlir::OpAsmParser &parser,
10931093
mlir::OperationState &result) {
10941094
// Parse the name as a symbol reference attribute.
1095-
mlir::SymbolRefAttr nameAttr;
1096-
if (parser.parseAttribute(nameAttr, mlir::SymbolTable::getSymbolAttrName(),
1097-
result.attributes))
1095+
mlir::StringAttr nameAttr;
1096+
if (parser.parseSymbolName(nameAttr, mlir::SymbolTable::getSymbolAttrName(),
1097+
result.attributes))
10981098
return mlir::failure();
10991099

1100-
// Convert the parsed name attr into a string attr.
1101-
result.attributes.set(mlir::SymbolTable::getSymbolAttrName(),
1102-
nameAttr.getRootReference());
1100+
if (!failed(parser.parseOptionalKeyword(getExtendsKeyword()))) {
1101+
mlir::StringAttr parent;
1102+
if (parser.parseLParen() ||
1103+
parser.parseAttribute(parent, getParentAttrNameStr(),
1104+
result.attributes) ||
1105+
parser.parseRParen())
1106+
return mlir::failure();
1107+
}
11031108

11041109
// Parse the optional table body.
11051110
mlir::Region *body = result.addRegion();
@@ -1113,11 +1118,11 @@ mlir::ParseResult fir::DispatchTableOp::parse(mlir::OpAsmParser &parser,
11131118
}
11141119

11151120
void fir::DispatchTableOp::print(mlir::OpAsmPrinter &p) {
1116-
auto tableName = getOperation()
1117-
->getAttrOfType<mlir::StringAttr>(
1118-
mlir::SymbolTable::getSymbolAttrName())
1119-
.getValue();
1120-
p << " @" << tableName;
1121+
p << ' ';
1122+
p.printSymbolName(getSymName());
1123+
if (getParent())
1124+
p << ' ' << getExtendsKeyword() << '('
1125+
<< (*this)->getAttr(getParentAttrNameStr()) << ')';
11211126

11221127
mlir::Region &body = getOperation()->getRegion(0);
11231128
if (!body.empty()) {
@@ -1128,12 +1133,29 @@ void fir::DispatchTableOp::print(mlir::OpAsmPrinter &p) {
11281133
}
11291134

11301135
mlir::LogicalResult fir::DispatchTableOp::verify() {
1136+
if (getRegion().empty())
1137+
return mlir::success();
11311138
for (auto &op : getBlock())
11321139
if (!mlir::isa<fir::DTEntryOp, fir::FirEndOp>(op))
11331140
return op.emitOpError("dispatch table must contain dt_entry");
11341141
return mlir::success();
11351142
}
11361143

1144+
void fir::DispatchTableOp::build(mlir::OpBuilder &builder,
1145+
mlir::OperationState &result,
1146+
llvm::StringRef name, mlir::Type type,
1147+
llvm::StringRef parent,
1148+
llvm::ArrayRef<mlir::NamedAttribute> attrs) {
1149+
result.addRegion();
1150+
result.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
1151+
builder.getStringAttr(name));
1152+
if (!parent.empty())
1153+
result.addAttribute(getParentAttrNameStr(), builder.getStringAttr(parent));
1154+
// result.addAttribute(getSymbolAttrNameStr(),
1155+
// mlir::SymbolRefAttr::get(builder.getContext(), name));
1156+
result.addAttributes(attrs);
1157+
}
1158+
11371159
//===----------------------------------------------------------------------===//
11381160
// EmboxOp
11391161
//===----------------------------------------------------------------------===//

flang/test/Fir/Todo/dispatch_table.fir

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)