@@ -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>);
@@ -250,8 +302,9 @@ def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", [CExpression]> {
250302 "::llvm::StringRef":$callee,
251303 "::mlir::ValueRange":$operands,
252304 CArg<"::mlir::ArrayAttr", "{}">:$args,
253- CArg<"::mlir::ArrayAttr", "{}">:$template_args), [{
254- build($_builder, $_state, resultTypes, callee, args, template_args,
305+ CArg<"::mlir::ArrayAttr", "{}">:$template_args,
306+ CArg<"::mlir::ArrayAttr", "{}">:$template_arg_names), [{
307+ build($_builder, $_state, resultTypes, callee, args, template_args, template_arg_names,
255308 operands);
256309 }]
257310 >
@@ -265,8 +318,7 @@ def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", [CExpression]> {
265318
266319def EmitC_CastOp : EmitC_Op<"cast",
267320 [CExpression,
268- DeclareOpInterfaceMethods<CastOpInterface>,
269- SameOperandsAndResultShape]> {
321+ DeclareOpInterfaceMethods<CastOpInterface>]> {
270322 let summary = "Cast operation";
271323 let description = [{
272324 The `emitc.cast` operation performs an explicit type conversion and is emitted
@@ -285,9 +337,11 @@ def EmitC_CastOp : EmitC_Op<"cast",
285337 ```
286338 }];
287339
288- let arguments = (ins EmitCType:$source);
340+ let arguments = (ins EmitCType:$source,
341+ UnitAttr:$reference);
289342 let results = (outs EmitCType:$dest);
290- let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest)";
343+ let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest) (`ref` $reference^)?";
344+ let hasVerifier = 1;
291345}
292346
293347def EmitC_CmpOp : EmitC_BinaryOp<"cmp", [CExpression]> {
@@ -700,6 +754,12 @@ def EmitC_FuncOp : EmitC_Op<"func", [
700754
701755 /// Returns the result types of this function.
702756 ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); }
757+
758+ //===------------------------------------------------------------------===//
759+ // SymbolOpInterface Methods
760+ //===------------------------------------------------------------------===//
761+
762+ bool isDeclaration() { return isExternal(); }
703763 }];
704764 let hasCustomAssemblyFormat = 1;
705765 let hasVerifier = 1;
@@ -730,7 +790,7 @@ def EmitC_ReturnOp : EmitC_Op<"return", [Pure, HasParent<"FuncOp">,
730790}
731791
732792def EmitC_IncludeOp
733- : EmitC_Op<"include", [HasParent<"ModuleOp"> ]> {
793+ : EmitC_Op<"include", []> {
734794 let summary = "Include operation";
735795 let description = [{
736796 The `emitc.include` operation allows to define a source file inclusion via the
@@ -1123,14 +1183,16 @@ def EmitC_GlobalOp : EmitC_Op<"global", [Symbol]> {
11231183 OptionalAttr<EmitC_OpaqueOrTypedAttr>:$initial_value,
11241184 UnitAttr:$extern_specifier,
11251185 UnitAttr:$static_specifier,
1126- UnitAttr:$const_specifier);
1186+ UnitAttr:$const_specifier,
1187+ UnitAttr:$reference);
11271188
11281189 let assemblyFormat = [{
11291190 (`extern` $extern_specifier^)?
11301191 (`static` $static_specifier^)?
11311192 (`const` $const_specifier^)?
11321193 $sym_name
11331194 `:` custom<EmitCGlobalOpTypeAndInitialValue>($type, $initial_value)
1195+ (`ref` $reference^)?
11341196 attr-dict
11351197 }];
11361198
@@ -1186,10 +1248,27 @@ def EmitC_VerbatimOp : EmitC_Op<"verbatim"> {
11861248 }
11871249 #endif
11881250 ```
1251+
1252+ If the `emitc.verbatim` op has operands, then the `value` is interpreted as
1253+ format string, where `{}` is a placeholder for an operand in their order.
1254+ For example, `emitc.verbatim "#pragma my src={} dst={}" %src, %dest : i32, i32`
1255+ would be emitted as `#pragma my src=a dst=b` if `%src` became `a` and
1256+ `%dest` became `b` in the C code.
1257+ `{{` in the format string is interpreted as a single `{` and doesn't introduce
1258+ a placeholder.
11891259 }];
11901260
1191- let arguments = (ins StrAttr:$value);
1192- let assemblyFormat = "$value attr-dict";
1261+ let extraClassDeclaration = [{
1262+ FailureOr<SmallVector<::mlir::emitc::ReplacementItem>> parseFormatString();
1263+ }];
1264+
1265+ let arguments = (ins StrAttr:$value,
1266+ Variadic<EmitCType>:$fmtArgs);
1267+
1268+ let builders = [OpBuilder<(ins "::mlir::StringAttr":$value), [{ build($_builder, $_state, value, {}); }] >];
1269+ let builders = [OpBuilder<(ins "::llvm::StringRef":$value), [{ build($_builder, $_state, value, {}); }] >];
1270+ let hasVerifier = 1;
1271+ let assemblyFormat = "$value (`args` $fmtArgs^ `:` type($fmtArgs))? attr-dict";
11931272}
11941273
11951274def EmitC_AssignOp : EmitC_Op<"assign", []> {
0 commit comments