Revert "Move HIP fatbin sections farther away from .text"
[llvm-project.git] / mlir / docs / DefiningDialects / Assembly.md
blobaa6272e873587d5a424c1e1934f365ab938bdb32
1 # Customizing Assembly Behavior
3 [TOC]
5 ## Generating Aliases
7 To reduce verbosity in the resulting assembly, `AsmPrinter` can generate aliases for frequently used types and attributes.
9 For example, `!my_dialect.type<a=3,b=4,c=5,d=tuple,e=another_type>` and `#my_dialect.attr<a=3>` can be aliased to `!my_dialect_type` and `#my_dialect_attr`, simplifying further references.
11 To enable this, the owning dialect of these types/attributes can define an interface to hook into the `AsmPrinter`. This is effective only when the assembly is not printed in generic form.
13 ```cpp
14 // OpAsmDialectInterface is defined in
15 // https://github.com/llvm/llvm-project/blob/91ab10e8d6c256d841da1a1a1b47c334e08d95b9/mlir/include/mlir/IR/OpImplementation.h#L1738
16 struct MyDialectOpAsmDialectInterface : public OpAsmDialectInterface {
17  public:
18   using OpAsmDialectInterface::OpAsmDialectInterface;
20   AliasResult getAlias(Type type, raw_ostream& os) const override {
21     if (mlir::isa<MyType>(type)) {
22       os << "my_dialect_type";
23       // Could return OverridableAlias when
24       // allowing other dialect to override the alias.
25       //
26       // Other dialects are allowed to provide alias for
27       // type/attribute not owned by them
28       // but the final result would depend on the registration order
29       // of these dialects in the MLIRContext
30       return AliasResult::FinalAlias;
31     }
32     return AliasResult::NoAlias;
33   }
35   AliasResult getAlias(Attribute attr, raw_ostream& os) const override {
36     if (mlir::isa<MyAttribute>(attr)) {
37       os << "my_dialect_attr";
38       return AliasResult::FinalAlias;
39     }
40     return AliasResult::NoAlias;
41   }
44 void MyDialect::initialize() {
45   // register the interface to the dialect
46   addInterface<MyDialectOpAsmDialectInterface>();
48 ```
50 * If `getAlias` provides an alias with a trailing digit, `AsmPrinter` appends an underscore to avoid conflicts with autogenerated IDs.
51 * If multiple types/attributes have the same alias from `getAlias`, a number is appended to the alias to avoid conflicts.
53 ## Suggesting SSA/Block Names
55 An `Operation` can suggest the SSA name prefix using `OpAsmOpInterface`.
57 For example, `arith.constant` will suggest a name like `%c42_i32` for its result:
59 ```tablegen
60 include "mlir/IR/OpAsmInterface.td"
62 def Arith_ConstantOp : Op<Arith_Dialect, "constant",
63     [ConstantLike, Pure,
64      DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
65 ...
67 ```
69 And the corresponding method:
71 ```cpp
72 // from https://github.com/llvm/llvm-project/blob/5ce271ef74dd3325993c827f496e460ced41af11/mlir/lib/Dialect/Arith/IR/ArithOps.cpp#L184
73 void arith::ConstantOp::getAsmResultNames(
74     function_ref<void(Value, StringRef)> setNameFn) {
75   auto type = getType();
76   if (auto intCst = llvm::dyn_cast<IntegerAttr>(getValue())) {
77     auto intType = llvm::dyn_cast<IntegerType>(type);
79     // Sugar i1 constants with 'true' and 'false'.
80     if (intType && intType.getWidth() == 1)
81       return setNameFn(getResult(), (intCst.getInt() ? "true" : "false"));
83     // Otherwise, build a complex name with the value and type.
84     SmallString<32> specialNameBuffer;
85     llvm::raw_svector_ostream specialName(specialNameBuffer);
86     specialName << 'c' << intCst.getValue();
87     if (intType)
88       specialName << '_' << type;
89     setNameFn(getResult(), specialName.str());
90   } else {
91     setNameFn(getResult(), "cst");
92   }
94 ```
96 Similarly, an `Operation` can suggest the name for its block arguments using `getAsmBlockArgumentNames` method in `OpAsmOpInterface`.
98 For custom block names, `OpAsmOpInterface` has a method `getAsmBlockNames` so that
99 the operation can suggest a custom prefix instead of a generic `^bb0`.
101 ## Defining Default Dialect
103 An `Operation` can indicate that the nested region in it has a default dialect prefix, and the operations in the region could elide the dialect prefix.
105 For example, in a `func.func` op all `func` prefix could be omitted:
107 ```tablegen
108 include "mlir/IR/OpAsmInterface.td"
110 def FuncOp : Func_Op<"func", [
111   OpAsmOpInterface
112   ...
113 ]> {
114   let extraClassDeclaration = [{
115     /// Allow the dialect prefix to be omitted.
116     static StringRef getDefaultDialect() { return "func"; }
117   }];
121 ```mlir
122 func.func @main() {
123   // actually func.call
124   call @another()