Skip to content

Commit

Permalink
[OM] Rework ClassOp to use return style for class fields (#7537)
Browse files Browse the repository at this point in the history
This changes the OM dialect Class/ExternClass to use a return style
field name/type specifier syntax and, for non-extern class, a terminator
op in the style of hw.output.
  • Loading branch information
leonardt authored Oct 21, 2024
1 parent f85865e commit 3a9ccf9
Show file tree
Hide file tree
Showing 25 changed files with 890 additions and 635 deletions.
1 change: 1 addition & 0 deletions include/circt/Dialect/OM/OMOpInterfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define CIRCT_DIALECT_OM_OMOPINTERFACES_H

#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OpImplementation.h"
#include "llvm/ADT/APSInt.h"

#include "circt/Dialect/OM/OMOpInterfaces.h.inc"
Expand Down
25 changes: 9 additions & 16 deletions include/circt/Dialect/OM/OMOpInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,19 @@ def ClassLike : OpInterface<"ClassLike"> {
"mlir::ArrayAttr", "getFormalParamNames", (ins)>,
InterfaceMethod<"Get the class-like formal parameter names attribute name",
"mlir::StringAttr", "getFormalParamNamesAttrName", (ins)>,
InterfaceMethod<"Get the class-like dictionary mapping field names to type",
"mlir::DictionaryAttr", "getFieldTypes", (ins)>,
InterfaceMethod<"Get the class-like body region",
"mlir::Region &", "getBody", (ins)>,
InterfaceMethod<"Get the class-like body block",
"mlir::Block *", "getBodyBlock", (ins),
/*methodBody=*/[{ return $_op.getBodyBlock(); }]>
];
}

def ClassFieldLike : OpInterface<"ClassFieldLike"> {
let cppNamespace = "circt::om";

let description = [{
Common functionality for class-like field operations.
}];

let methods = [
InterfaceMethod<"Get the class-like field's type",
"mlir::Type", "getType", (ins)>,
InterfaceMethod<"Get the class-like field's name attribute",
"mlir::StringAttr", "getNameAttr", (ins)>
/*methodBody=*/[{ return $_op.getBodyBlock(); }]>,
InterfaceMethod<"Get the class-like field type",
"std::optional<mlir::Type>", "getFieldType", (ins "mlir::StringAttr":$field)>,
InterfaceMethod<"Get the class-like field names",
"mlir::ArrayAttr", "getFieldNames", (ins)>,
InterfaceMethod<"Replace field types dictionary attr",
"void", "replaceFieldTypes", (ins "mlir::AttrTypeReplacer":$replacer)>,
];
}

Expand Down
1 change: 1 addition & 0 deletions include/circt/Dialect/OM/OMOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"

#define GET_OP_CLASSES
Expand Down
108 changes: 75 additions & 33 deletions include/circt/Dialect/OM/OMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef CIRCT_DIALECT_OM_OMOPS_TD
#define CIRCT_DIALECT_OM_OMOPS_TD

include "mlir/Interfaces/ControlFlowInterfaces.td"
include "circt/Dialect/OM/OMDialect.td"
include "circt/Dialect/OM/OMEnums.td"
include "circt/Dialect/OM/OMOpInterfaces.td"
Expand All @@ -33,40 +34,73 @@ class OMOp<string mnemonic, list<Trait> traits = []> :

class OMClassLike<string mnemonic, list<Trait> traits = []> :
OMOp<mnemonic, traits # [
SingleBlock, NoTerminator, Symbol, RegionKindInterface, IsolatedFromAbove,
Symbol, RegionKindInterface, IsolatedFromAbove,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>,
DeclareOpInterfaceMethods<ClassLike>]> {

let arguments = (ins
SymbolNameAttr:$sym_name,
StrArrayAttr:$formalParamNames
StrArrayAttr:$formalParamNames,
ArrayAttr:$fieldNames,
DictionaryAttr:$fieldTypes
);

let regions = (region
SizedRegion<1>:$body
);

let builders = [
OpBuilder<(ins "::mlir::Twine":$name)>,
OpBuilder<(ins "::mlir::Twine":$name,
"::mlir::ArrayRef<::mlir::StringRef>":$formalParamNames)>,
"::mlir::ArrayRef<::mlir::StringRef>":$formalParamNames,
"::mlir::ArrayRef<::mlir::Attribute>":$fieldNames,
"::mlir::ArrayRef<::mlir::NamedAttribute>":$fieldTypes), [{
build(odsBuilder, odsState, odsBuilder.getStringAttr(name),
odsBuilder.getStrArrayAttr(formalParamNames),
odsBuilder.getArrayAttr(fieldNames),
odsBuilder.getDictionaryAttr(fieldTypes));
}]>,
OpBuilder<(ins "::mlir::Twine":$name,
"::mlir::ArrayRef<::mlir::StringRef>":$formalParamNames), [{
build(odsBuilder, odsState, odsBuilder.getStringAttr(name),
odsBuilder.getStrArrayAttr(formalParamNames));
}]>,
OpBuilder<(ins "::mlir::Twine":$name), [{
build(odsBuilder, odsState, odsBuilder.getStringAttr(name),
odsBuilder.getStrArrayAttr({}));
}]>,
OpBuilder<(ins "::mlir::Twine":$name,
"::mlir::ArrayAttr":$fieldNames,
"::mlir::DictionaryAttr":$fieldTypes), [{
build(odsBuilder, odsState, odsBuilder.getStringAttr(name),
odsBuilder.getStrArrayAttr({}), fieldNames, fieldTypes);
}]>,
OpBuilder<(ins "::mlir::Twine":$name,
"::mlir::ArrayRef<::mlir::StringRef>":$formalParamNames,
"::mlir::ArrayAttr":$fieldNames,
"::mlir::DictionaryAttr":$fieldTypes), [{
build(odsBuilder, odsState, odsBuilder.getStringAttr(name),
odsBuilder.getStrArrayAttr(formalParamNames), fieldNames,
fieldTypes);
}]>,
OpBuilder<(ins "::mlir::StringAttr":$name,
"::mlir::ArrayAttr":$formalParamNames), [{
build(odsBuilder, odsState, name, formalParamNames,
odsBuilder.getArrayAttr({}), odsBuilder.getDictionaryAttr({}));

}]>
];

let hasCustomAssemblyFormat = 1;

let hasVerifier = 1;
}

class OMClassFieldLike<string mnemonic, list<Trait> traits = []> :
OMOp<mnemonic, traits # [
DeclareOpInterfaceMethods<ClassFieldLike>]> {
}

//===----------------------------------------------------------------------===//
// Class definitions
//===----------------------------------------------------------------------===//

def ClassOp : OMClassLike<"class"> {
def ClassOp : OMClassLike<"class", [
SingleBlockImplicitTerminator<"ClassFieldsOp">]> {
let extraClassDeclaration = [{
mlir::Block *getBodyBlock() { return &getBody().front(); }
// This builds a ClassOp, and populates it with the CLassFieldOps.
Expand All @@ -82,26 +116,46 @@ def ClassOp : OMClassLike<"class"> {
static mlir::RegionKind getRegionKind(unsigned index) {
return mlir::RegionKind::Graph;
}
}];
}

def ClassFieldOp : OMClassFieldLike<"class.field",
[HasParent<"ClassOp">]> {
let arguments = (ins
SymbolNameAttr:$name,
AnyType:$value
);
circt::om::ClassFieldsOp getFieldsOp() {
return mlir::cast<ClassFieldsOp>(this->getBodyBlock()->getTerminator());
}

let assemblyFormat = [{
$name `,` $value attr-dict `:` type($value)
// The addFields API encapsulates the logic used to represent field
// locations under the hood. Users should invoke this method rather
// than construct the operation directly, otherwise logic to retrieve
// the field location will break.
// This is required because MLIR's FusedLoc uses a "set" semantics where a
// single location is used to represent multiple fields with the same
// location. The OM implementation uses the metadata attribute on FusedLoc
// to store the original array of locations, so that the specific location
// of a field may be easily retrieved by index using the
// `getFieldLocByIndex` API.
void addFields(mlir::OpBuilder &builder, mlir::ArrayRef<mlir::Location>
locs, mlir::ArrayRef<mlir::Value> values);

// Return the location for a field referenced by index in the fieldNames
// array attribute. If the field has a location added by addFields API,
// its location will be retrieved from the array of per field locations.
// Otherwise, it will inherit the location of the class op Using this with
// a ClassFieldsOp that has been constructed with a FusedLoc but not
// following the internal storage format of `addFields` will result in an
// assertion error
mlir::Location getFieldLocByIndex(size_t i);
}];
}

def ClassFieldsOp : OMOp<"class.fields", [Terminator, ReturnLike, Pure,
HasParent<"ClassOp">]> {
let arguments = (ins Variadic<AnyType>:$fields);
let assemblyFormat = "attr-dict ($fields^ `:` qualified(type($fields)))?";
}

//===----------------------------------------------------------------------===//
// External class definitions
//===----------------------------------------------------------------------===//

def ClassExternOp : OMClassLike<"class.extern"> {
def ClassExternOp : OMClassLike<"class.extern", [NoTerminator]> {
let extraClassDeclaration = [{
mlir::Block *getBodyBlock() { return &getBody().front(); }

Expand All @@ -112,18 +166,6 @@ def ClassExternOp : OMClassLike<"class.extern"> {
}];
}

def ClassExternFieldOp : OMClassFieldLike<"class.extern.field",
[HasParent<"ClassExternOp">]> {
let arguments = (ins
SymbolNameAttr:$name,
TypeAttr:$type
);

let assemblyFormat = [{
$name attr-dict `:` $type
}];
}

//===----------------------------------------------------------------------===//
// Object instantiations and fields
//===----------------------------------------------------------------------===//
Expand Down
Loading

0 comments on commit 3a9ccf9

Please sign in to comment.