Skip to content

Commit 4300427

Browse files
committed
mlir: add an operation to EmitC for function template instantiation
This commit adds an `emitc.instantiate_function_template` operation to allow for the expression of function template instantiation. Without this operation, there is no easy way to express a C++ program like: ``` auto x = ...; auto y = ...; const void* fptr = &f<decltype(x), decltype(y)>; ``` Doing so is necessary to generate code that interacts with some lower level APIs for launching parallel work into runtime systems.
1 parent 7c94a22 commit 4300427

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,5 +1260,32 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
12601260
let assemblyFormat = "$value `[` $indices `]` attr-dict `:` functional-type(operands, results)";
12611261
}
12621262

1263+
def EmitC_InstantiateFunctionTemplateOp : EmitC_Op<"instantiate_function_template", []> {
1264+
let summary = "Instantiate template operation";
1265+
let description = [{
1266+
Instantiate a function template with a given set of types
1267+
(given by the values as argument to this operation) to obtain
1268+
a function pointer.
1269+
1270+
Example:
1271+
1272+
```mlir
1273+
%c1 = "emitc.constant"() <{value = 7 : i32}> : () -> i32
1274+
%0 = emitc.instantiate_function_template "func_template"<%c1> : (i32) -> !emitc.ptr<!emitc.opaque<"void">>
1275+
```
1276+
Translates to the C++:
1277+
```c++
1278+
int32_t v1 = 7;
1279+
void* v2 = &func_template<decltype(v1)>;
1280+
```
1281+
}];
1282+
let arguments = (ins
1283+
Arg<StrAttr, "the C++ function to instantiate">:$callee,
1284+
Variadic<EmitCType>:$args
1285+
);
1286+
let results = (outs EmitC_PointerType);
1287+
let assemblyFormat = "$callee `<` $args `>` attr-dict `:` functional-type($args, results)";
1288+
}
1289+
12631290

12641291
#endif // MLIR_DIALECT_EMITC_IR_EMITC

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,30 @@ static LogicalResult printOperation(CppEmitter &emitter,
656656
return success();
657657
}
658658

659+
static LogicalResult
660+
printOperation(CppEmitter &emitter,
661+
emitc::InstantiateFunctionTemplateOp instOp) {
662+
663+
raw_ostream &os = emitter.ostream();
664+
Operation &op = *instOp.getOperation();
665+
666+
if (failed(emitter.emitAssignPrefix(op)))
667+
return failure();
668+
os << "&" << instOp.getCallee() << "<";
669+
670+
auto emitArgs = [&](mlir::Value val) -> LogicalResult {
671+
os << "decltype(";
672+
if (failed(emitter.emitOperand(val)))
673+
return failure();
674+
os << ")";
675+
return success();
676+
};
677+
if (failed(interleaveCommaWithError(instOp.getArgs(), os, emitArgs)))
678+
return failure();
679+
os << ">";
680+
return success();
681+
}
682+
659683
static LogicalResult printOperation(CppEmitter &emitter,
660684
emitc::ApplyOp applyOp) {
661685
raw_ostream &os = emitter.ostream();
@@ -1508,6 +1532,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
15081532
.Case<func::CallOp, func::FuncOp, func::ReturnOp>(
15091533
[&](auto op) { return printOperation(*this, op); })
15101534
.Case<emitc::LiteralOp>([&](auto op) { return success(); })
1535+
.Case<emitc::InstantiateFunctionTemplateOp>(
1536+
[&](auto op) { return printOperation(*this, op); })
15111537
.Default([&](Operation *) {
15121538
return op.emitOpError("unable to find printer for op");
15131539
});

mlir/test/Dialect/EmitC/ops.mlir

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ func.func @test_subscript(%arg0 : !emitc.array<2x3xf32>, %arg1 : !emitc.ptr<i32>
224224
return
225225
}
226226

227+
func.func @test_instantiate_template() {
228+
%c1 = "emitc.constant"() <{value = 7 : i32}> : () -> i32
229+
%0 = emitc.instantiate_function_template "func_template"<%c1> : (i32) -> !emitc.ptr<!emitc.opaque<"void">>
230+
return
231+
}
232+
227233
emitc.verbatim "#ifdef __cplusplus"
228234
emitc.verbatim "extern \"C\" {"
229235
emitc.verbatim "#endif // __cplusplus"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT
2+
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s -check-prefix=CPP-DECLTOP
3+
4+
func.func @emitc_instantiate_template() {
5+
%c1 = "emitc.constant"() <{value = 7 : i32}> : () -> i32
6+
%0 = emitc.instantiate_function_template "func_template"<%c1> : (i32) -> !emitc.ptr<!emitc.opaque<"void">>
7+
return
8+
}
9+
// CPP-DEFAULT: void emitc_instantiate_template() {
10+
// CPP-DEFAULT-NEXT: int32_t [[V0:[^ ]*]] = 7;
11+
// CPP-DEFAULT-NEXT: void* [[V1:[^ ]*]] = &func_template<decltype([[V0]])>;
12+
13+
// CPP-DECLTOP: void emitc_instantiate_template() {
14+
// CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]];
15+
// CPP-DECLTOP-NEXT: void* [[V1:[^ ]*]];
16+
// CPP-DECLTOP-NEXT: [[V0]] = 7;
17+
// CPP-DECLTOP-NEXT: [[V1]] = &func_template<decltype([[V0]])>;

0 commit comments

Comments
 (0)