Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang][nfc] replace fir.dispatch_table with more generic fir.type_info #68309

Merged
merged 1 commit into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions flang/include/flang/Lower/AbstractConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,10 @@ class AbstractConverter {

/// Register a runtime derived type information object symbol to ensure its
/// object will be generated as a global.
virtual void registerRuntimeTypeInfo(mlir::Location loc,
SymbolRef typeInfoSym) = 0;

virtual void registerDispatchTableInfo(
mlir::Location loc,
const Fortran::semantics::DerivedTypeSpec *typeSpec) = 0;
virtual void
registerTypeInfo(mlir::Location loc, SymbolRef typeInfoSym,
const Fortran::semantics::DerivedTypeSpec &typeSpec,
fir::RecordType type) = 0;

//===--------------------------------------------------------------------===//
// Locations
Expand Down
5 changes: 0 additions & 5 deletions flang/include/flang/Optimizer/Builder/FIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,6 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
bodyBuilder, linkage);
}

/// Create a fir::DispatchTable operation.
fir::DispatchTableOp createDispatchTableOp(mlir::Location loc,
llvm::StringRef name,
llvm::StringRef parentName);

/// Convert a StringRef string into a fir::StringLitOp.
fir::StringLitOp createStringLitOp(mlir::Location loc,
llvm::StringRef string);
Expand Down
65 changes: 47 additions & 18 deletions flang/include/flang/Optimizer/Dialect/FIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2778,6 +2778,10 @@ def fir_GlobalOp : fir_Op<"global", [IsolatedFromAbove, Symbol]> {
(*this)->getAttrOfType<mlir::StringAttr>(
mlir::SymbolTable::getSymbolAttrName()).getValue());
}

bool isInitialized() {
return getInitVal() || hasInitializationBody();
}
}];
}

Expand Down Expand Up @@ -2809,20 +2813,31 @@ def fir_GlobalLenOp : fir_Op<"global_len", []> {

def ImplicitFirTerminator : SingleBlockImplicitTerminator<"FirEndOp">;

def fir_DispatchTableOp : fir_Op<"dispatch_table",
def fir_TypeInfoOp : fir_Op<"type_info",
[IsolatedFromAbove, Symbol, ImplicitFirTerminator]> {
let summary = "Dispatch table definition";
let summary = "Derived type information";

let description = [{
Define a dispatch table for a derived type with type-bound procedures.
Define extra information about a !fir.type<> that represents
a Fortran derived type.

A dispatch table is an untyped symbol that contains a list of associations
The optional dispatch table region defines a dispatch table with the derived
type type-bound procedures. It contains a list of associations
between method identifiers and corresponding `FuncOp` symbols.

The ordering of associations in the map is determined by the front end.

The "no_init" flag indicates that this type has no components requiring default
initialization (including setting allocatable component to a clean deallocated
state).

The "no_destroy" flag indicates that there are no allocatable components
that require deallocation.

The "no_final" flag indicates that there are no final methods for this type,
for its parents ,or for components.

```mlir
fir.dispatch_table @_QDTMquuzTfoo {
fir.type_info @_QMquuzTfoo noinit nofinal : !fir.type<_QMquuzTfoo{i:i32}> dispatch_table {
fir.dt_entry method1, @_QFNMquuzTfooPmethod1AfooR
fir.dt_entry method2, @_QFNMquuzTfooPmethod2AfooII
}
Expand All @@ -2831,32 +2846,46 @@ def fir_DispatchTableOp : fir_Op<"dispatch_table",

let arguments = (ins
SymbolNameAttr:$sym_name,
OptionalAttr<StrAttr>:$parent
TypeAttr:$type,
OptionalAttr<TypeAttr>:$parent_type,
UnitAttr:$no_init,
UnitAttr:$no_destroy,
UnitAttr:$no_final
);

let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;

let regions = (region AnyRegion:$region);
let regions = (region MaxSizedRegion<1>:$dispatch_table);

let skipDefaultBuilders = 1;
let builders = [
OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
"llvm::StringRef":$parent,
OpBuilder<(ins "fir::RecordType":$type, "fir::RecordType":$parent_type,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>
];

let extraClassDeclaration = [{
static constexpr llvm::StringRef getParentAttrNameStr() { return "parent"; }
static constexpr llvm::StringRef getExtendsKeyword() { return "extends"; }
let assemblyFormat = [{
$sym_name (`noinit` $no_init^)? (`nodestroy` $no_destroy^)?
(`nofinal` $no_final^)? (`extends` $parent_type^)? attr-dict `:` $type
(`dispatch_table` $dispatch_table^)?
}];

mlir::Block &getBlock() {
return getRegion().front();
let extraClassDeclaration = [{
fir::RecordType getRecordType() {
return mlir::cast<fir::RecordType>(getType());
}
fir::RecordType getIfParentType() {
if (auto parentType = getParentType())
return mlir::cast<fir::RecordType>(*parentType);
return {};
}
std::optional<llvm::StringRef> getIfParentName() {
if (auto parentType = getIfParentType())
return parentType.getName();
return std::nullopt;
}
}];
}

def fir_DTEntryOp : fir_Op<"dt_entry", [HasParent<"DispatchTableOp">]> {
def fir_DTEntryOp : fir_Op<"dt_entry", [HasParent<"TypeInfoOp">]> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we really need an operation for the entry. We can maybe just store this directly in the TypeInfoOp. Anyway this is a comment for future clean up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, that is a good point. I agree we likely can do it with an array attribute of something and it may be more efficient.

The only drawback is that I do not know if this is possible to print attributes on new lines/several lines, and I think it would make the operation a bit harder to read/debug if it is a gigantic line (although binding tables are probably not that long usually, but there will also be the special bindings to describe at some point and the array components lower bounds).

I will try to think about this more when adding more info.

let summary = "map entry in a dispatch table";

let description = [{
Expand Down
15 changes: 8 additions & 7 deletions flang/include/flang/Optimizer/Support/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,22 @@ using BindingTables = llvm::DenseMap<llvm::StringRef, BindingTable>;
inline void buildBindingTables(BindingTables &bindingTables,
mlir::ModuleOp mod) {

// The binding tables are defined in FIR from lowering as fir.dispatch_table
// operation. Go through each binding tables and store the procedure name and
// The binding tables are defined in FIR after lowering inside fir.type_info
// operations. Go through each binding tables and store the procedure name and
// binding index for later use by the fir.dispatch conversion pattern.
for (auto dispatchTableOp : mod.getOps<fir::DispatchTableOp>()) {
for (auto typeInfo : mod.getOps<fir::TypeInfoOp>()) {
unsigned bindingIdx = 0;
BindingTable bindings;
if (dispatchTableOp.getRegion().empty()) {
bindingTables[dispatchTableOp.getSymName()] = bindings;
if (typeInfo.getDispatchTable().empty()) {
bindingTables[typeInfo.getSymName()] = bindings;
continue;
}
for (auto dtEntry : dispatchTableOp.getBlock().getOps<fir::DTEntryOp>()) {
for (auto dtEntry :
typeInfo.getDispatchTable().front().getOps<fir::DTEntryOp>()) {
bindings[dtEntry.getMethod()] = bindingIdx;
++bindingIdx;
}
bindingTables[dispatchTableOp.getSymName()] = bindings;
bindingTables[typeInfo.getSymName()] = bindings;
}
}

Expand Down
Loading
Loading