@@ -21,7 +21,9 @@ include "mlir/Interfaces/CastInterfaces.td"
2121include "mlir/Interfaces/ControlFlowInterfaces.td"
2222include "mlir/Interfaces/FunctionInterfaces.td"
2323include "mlir/Interfaces/SideEffectInterfaces.td"
24+ include "mlir/IR/OpAsmInterface.td"
2425include "mlir/IR/RegionKindInterface.td"
26+ include "mlir/IR/BuiltinAttributes.td"
2527
2628//===----------------------------------------------------------------------===//
2729// EmitC op definitions
@@ -55,6 +57,55 @@ def IntegerIndexOrOpaqueType : Type<CPred<"emitc::isIntegerIndexOrOpaqueType($_s
5557"integer, index or opaque type supported by EmitC">;
5658def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[EmitCFloatType, IntegerIndexOrOpaqueType]>;
5759
60+ def EmitC_TranslationUnitOp : EmitC_Op<"tu",
61+ [IsolatedFromAbove, NoRegionArguments, SymbolTable,
62+ OpAsmOpInterface
63+ ] # GraphRegionNoTerminator.traits> {
64+ let summary = "A translation unit container operation";
65+ let description = [{
66+ A `tu` represents a translation unit that can be emitted
67+ into a single C++ file.
68+
69+ `mlir-translate` emits only the translation unit selected via
70+ the `-translation-unit-id=id` flag. By default, no translation units are
71+ emitted.
72+
73+ Example:
74+
75+ ```mlir
76+ emitc.tu "main" {
77+ emitc.func @func_one() {
78+ emitc.return
79+ }
80+ }
81+ ```
82+ }];
83+
84+ let arguments = (ins Builtin_StringAttr:$id);
85+ let regions = (region SizedRegion<1>:$bodyRegion);
86+
87+ let assemblyFormat = "$id attr-dict-with-keyword $bodyRegion";
88+ let builders = [OpBuilder<(ins CArg<"StringRef">:$id)>];
89+ let extraClassDeclaration = [{
90+ /// Construct a module from the given location with an optional name.
91+ static TranslationUnitOp create(Location loc, StringRef name);
92+
93+ //===------------------------------------------------------------------===//
94+ // OpAsmOpInterface Methods
95+ //===------------------------------------------------------------------===//
96+
97+ /// EmitC ops in the body of the translation_unit can omit their 'emitc.'
98+ /// prefix in the assembly.
99+ static ::llvm::StringRef getDefaultDialect() {
100+ return "emitc";
101+ }
102+ }];
103+
104+ // We need to ensure that the body region has a block;
105+ // the auto-generated builders do not guarantee that.
106+ let skipDefaultBuilders = 1;
107+ }
108+
58109def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> {
59110 let summary = "Addition operation";
60111 let description = [{
@@ -241,6 +292,7 @@ def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", [CExpression]> {
241292 Arg<StrAttr, "the C++ function to call">:$callee,
242293 Arg<OptionalAttr<ArrayAttr>, "the order of operands and further attributes">:$args,
243294 Arg<OptionalAttr<ArrayAttr>, "template arguments">:$template_args,
295+ Arg<OptionalAttr<StrArrayAttr>, "template argument names">:$template_arg_names,
244296 Variadic<EmitCType>:$operands
245297 );
246298 let results = (outs Variadic<EmitCType>);
@@ -251,7 +303,7 @@ def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", [CExpression]> {
251303 "::mlir::ValueRange":$operands,
252304 CArg<"::mlir::ArrayAttr", "{}">:$args,
253305 CArg<"::mlir::ArrayAttr", "{}">:$template_args), [{
254- build($_builder, $_state, resultTypes, callee, args, template_args,
306+ build($_builder, $_state, resultTypes, callee, args, template_args, {},
255307 operands);
256308 }]
257309 >
@@ -265,8 +317,7 @@ def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", [CExpression]> {
265317
266318def EmitC_CastOp : EmitC_Op<"cast",
267319 [CExpression,
268- DeclareOpInterfaceMethods<CastOpInterface>,
269- SameOperandsAndResultShape]> {
320+ DeclareOpInterfaceMethods<CastOpInterface>]> {
270321 let summary = "Cast operation";
271322 let description = [{
272323 The `emitc.cast` operation performs an explicit type conversion and is emitted
@@ -285,9 +336,11 @@ def EmitC_CastOp : EmitC_Op<"cast",
285336 ```
286337 }];
287338
288- let arguments = (ins EmitCType:$source);
339+ let arguments = (ins EmitCType:$source,
340+ UnitAttr:$reference);
289341 let results = (outs EmitCType:$dest);
290- let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest)";
342+ let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest) (`ref` $reference^)?";
343+ let hasVerifier = 1;
291344}
292345
293346def EmitC_CmpOp : EmitC_BinaryOp<"cmp", [CExpression]> {
@@ -700,6 +753,12 @@ def EmitC_FuncOp : EmitC_Op<"func", [
700753
701754 /// Returns the result types of this function.
702755 ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }
756+
757+ //===------------------------------------------------------------------===//
758+ // SymbolOpInterface Methods
759+ //===------------------------------------------------------------------===//
760+
761+ bool isDeclaration() { return isExternal(); }
703762 }];
704763 let hasCustomAssemblyFormat = 1;
705764 let hasVerifier = 1;
@@ -730,7 +789,7 @@ def EmitC_ReturnOp : EmitC_Op<"return", [Pure, HasParent<"FuncOp">,
730789}
731790
732791def EmitC_IncludeOp
733- : EmitC_Op<"include", [HasParent<"ModuleOp"> ]> {
792+ : EmitC_Op<"include", []> {
734793 let summary = "Include operation";
735794 let description = [{
736795 The `emitc.include` operation allows to define a source file inclusion via the
@@ -1092,14 +1151,16 @@ def EmitC_GlobalOp : EmitC_Op<"global", [Symbol]> {
10921151 OptionalAttr<EmitC_OpaqueOrTypedAttr>:$initial_value,
10931152 UnitAttr:$extern_specifier,
10941153 UnitAttr:$static_specifier,
1095- UnitAttr:$const_specifier);
1154+ UnitAttr:$const_specifier,
1155+ UnitAttr:$reference);
10961156
10971157 let assemblyFormat = [{
10981158 (`extern` $extern_specifier^)?
10991159 (`static` $static_specifier^)?
11001160 (`const` $const_specifier^)?
11011161 $sym_name
11021162 `:` custom<EmitCGlobalOpTypeAndInitialValue>($type, $initial_value)
1163+ (`ref` $reference^)?
11031164 attr-dict
11041165 }];
11051166
@@ -1154,10 +1215,27 @@ def EmitC_VerbatimOp : EmitC_Op<"verbatim"> {
11541215 }
11551216 #endif
11561217 ```
1218+
1219+ If the `emitc.verbatim` op has operands, then the `value` is interpreted as
1220+ format string, where `{}` is a placeholder for an operand in their order.
1221+ For example, `emitc.verbatim "#pragma my src={} dst={}" %src, %dest : i32, i32`
1222+ would be emitted as `#pragma my src=a dst=b` if `%src` became `a` and
1223+ `%dest` became `b` in the C code.
1224+ `{{` in the format string is interpreted as a single `{` and doesn't introduce
1225+ a placeholder.
11571226 }];
11581227
1159- let arguments = (ins StrAttr:$value);
1160- let assemblyFormat = "$value attr-dict";
1228+ let extraClassDeclaration = [{
1229+ FailureOr<SmallVector<::mlir::emitc::ReplacementItem>> parseFormatString();
1230+ }];
1231+
1232+ let arguments = (ins StrAttr:$value,
1233+ Variadic<EmitCType>:$fmtArgs);
1234+
1235+ let builders = [OpBuilder<(ins "::mlir::StringAttr":$value), [{ build($_builder, $_state, value, {}); }] >];
1236+ let builders = [OpBuilder<(ins "::llvm::StringRef":$value), [{ build($_builder, $_state, value, {}); }] >];
1237+ let hasVerifier = 1;
1238+ let assemblyFormat = "$value (`args` $fmtArgs^ `:` type($fmtArgs))? attr-dict";
11611239}
11621240
11631241def EmitC_AssignOp : EmitC_Op<"assign", []> {
0 commit comments