Skip to content

Commit ab8cc1b

Browse files
author
Simon Camphausen
committed
[mlir][EmitC] Add verbatim op
This operation can be used in situations where a more suitable operation is not yet implemented in the dialect or where preprocessor directives interfere with the structure of the code.
1 parent 955417a commit ab8cc1b

File tree

6 files changed

+107
-6
lines changed

6 files changed

+107
-6
lines changed

mlir/include/mlir/Dialect/EmitC/IR/EmitC.td

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,45 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
544544
let hasVerifier = 1;
545545
}
546546

547+
def EmitC_VerbatimOp : EmitC_Op<"verbatim"> {
548+
let summary = "Verbatim operation";
549+
let description = [{
550+
The `verbatim` operation produces no results and the value is emitted as is
551+
durung translation. If `trailing_semicolon` is present an additional
552+
semicolon is emitted.
553+
554+
Note: Use with caution. This operation can have arbitrary effects on the
555+
semantics of the emitted code. Use semantically more meaningful operations
556+
whenever possible. Additionally this op is *NOT* intended to be used to
557+
inject large snippets of code.
558+
559+
This operation can be used in situations where a more suitable operation is
560+
not yet implemented in the dialect or where preprocessor directives
561+
interfere with the structure of the code. One example of this is to declare
562+
the linkage of external symbols to make the generated code usable in both C
563+
and C++ contexts:
564+
565+
```c++
566+
#ifdef __cplusplus
567+
extern "C" {
568+
#endif
569+
570+
...
571+
572+
#ifdef __cplusplus
573+
}
574+
#endif
575+
```
576+
}];
577+
578+
let arguments = (ins
579+
StrAttr:$value,
580+
UnitAttr:$trailing_semicolon
581+
);
582+
let assemblyFormat = "$value (`trailing_semicolon` $trailing_semicolon^)? attr-dict";
583+
let hasVerifier = 1;
584+
}
585+
547586
def EmitC_AssignOp : EmitC_Op<"assign", []> {
548587
let summary = "Assign operation";
549588
let description = [{

mlir/lib/Dialect/EmitC/IR/EmitC.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,17 @@ LogicalResult emitc::VariableOp::verify() {
584584
return verifyInitializationAttribute(getOperation(), getValueAttr());
585585
}
586586

587+
//===----------------------------------------------------------------------===//
588+
// VerbatimOp
589+
//===----------------------------------------------------------------------===//
590+
591+
LogicalResult emitc::VerbatimOp::verify() {
592+
if (getValue().back() == ';')
593+
return emitOpError() << "';' not allowed as the last character, use the "
594+
"`trailing_semicolon` attribute instead";
595+
return success();
596+
}
597+
587598
//===----------------------------------------------------------------------===//
588599
// YieldOp
589600
//===----------------------------------------------------------------------===//

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,17 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::CmpOp cmpOp) {
429429
return printBinaryOperation(emitter, operation, binaryOperator);
430430
}
431431

432+
static LogicalResult printOperation(CppEmitter &emitter,
433+
emitc::VerbatimOp verbatimOp) {
434+
raw_ostream &os = emitter.ostream();
435+
436+
os << verbatimOp.getValue();
437+
438+
if (verbatimOp.getTrailingSemicolon())
439+
os << ";";
440+
return success();
441+
}
442+
432443
static LogicalResult printOperation(CppEmitter &emitter,
433444
cf::BranchOp branchOp) {
434445
raw_ostream &os = emitter.ostream();
@@ -814,11 +825,10 @@ static LogicalResult printOperation(CppEmitter &emitter,
814825
for (Operation &op : block.getOperations()) {
815826
// When generating code for an emitc.if or cf.cond_br op no semicolon
816827
// needs to be printed after the closing brace.
817-
// When generating code for an emitc.for op, printing a trailing semicolon
818-
// is handled within the printOperation function.
819-
bool trailingSemicolon =
820-
!isa<cf::CondBranchOp, emitc::ForOp, emitc::IfOp, emitc::LiteralOp>(
821-
op);
828+
// When generating code for an emitc.for and emitc.verbatim op, printing a
829+
// trailing semicolon is handled within the printOperation function.
830+
bool trailingSemicolon = !isa<cf::CondBranchOp, emitc::ForOp, emitc::IfOp,
831+
emitc::LiteralOp, emitc::VerbatimOp>(op);
822832

823833
if (failed(emitter.emitOperation(
824834
op, /*trailingSemicolon=*/trailingSemicolon)))
@@ -1144,7 +1154,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
11441154
emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
11451155
emitc::ConstantOp, emitc::DivOp, emitc::ExpressionOp,
11461156
emitc::ForOp, emitc::IfOp, emitc::IncludeOp, emitc::MulOp,
1147-
emitc::RemOp, emitc::SubOp, emitc::VariableOp>(
1157+
emitc::RemOp, emitc::SubOp, emitc::VariableOp,
1158+
emitc::VerbatimOp>(
11481159
[&](auto op) { return printOperation(*this, op); })
11491160
// Func ops.
11501161
.Case<func::CallOp, func::ConstantOp, func::FuncOp, func::ReturnOp>(

mlir/test/Dialect/EmitC/invalid_ops.mlir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,11 @@ func.func @test_expression_multiple_results(%arg0: i32) -> i32 {
289289
}
290290
return %r : i32
291291
}
292+
293+
// -----
294+
295+
func.func @verbatim_trailing_semicolon() {
296+
// expected-error @+1 {{'emitc.verbatim' op ';' not allowed as the last character, use the `trailing_semicolon` attribute instead}}
297+
emitc.verbatim "typedef int32_t i32;"
298+
return
299+
}

mlir/test/Dialect/EmitC/ops.mlir

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,14 @@ func.func @test_for_not_index_induction(%arg0 : i16, %arg1 : i16, %arg2 : i16) {
166166
}
167167
return
168168
}
169+
170+
emitc.verbatim "#ifdef __cplusplus"
171+
emitc.verbatim "extern \"C\" {"
172+
emitc.verbatim "#endif // __cplusplus"
173+
174+
emitc.verbatim "#ifdef __cplusplus"
175+
emitc.verbatim "} // extern \"C\""
176+
emitc.verbatim "#endif // __cplusplus"
177+
178+
emitc.verbatim "typedef int32_t i32" {trailing_semicolon = unit}
179+
emitc.verbatim "typedef float f32" trailing_semicolon

mlir/test/Target/Cpp/verbatim.mlir

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
2+
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s
3+
4+
5+
emitc.verbatim "#ifdef __cplusplus"
6+
// CHECK: #ifdef __cplusplus
7+
emitc.verbatim "extern \"C\" {"
8+
// CHECK-NEXT: extern "C" {
9+
emitc.verbatim "#endif // __cplusplus"
10+
// CHECK-NEXT: #endif // __cplusplus
11+
emitc.verbatim "#ifdef __cplusplus"
12+
// CHECK-NEXT: #ifdef __cplusplus
13+
emitc.verbatim "} // extern \"C\""
14+
// CHECK-NEXT: } // extern "C"
15+
emitc.verbatim "#endif // __cplusplus"
16+
// CHECK-NEXT: #endif // __cplusplus
17+
18+
emitc.verbatim "typedef int32_t i32" {trailing_semicolon = unit}
19+
// CHECK-NEXT: typedef int32_t i32;
20+
emitc.verbatim "typedef float f32" trailing_semicolon
21+
// CHECK-NEXT: typedef float f32;

0 commit comments

Comments
 (0)