mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 22:17:23 +08:00
[mlir][emitc] Rename call op to call_opaque (#72494)
This renames the `emitc.call` op to `emitc.call_opaque` as the existing call op does not refer to the callee by symbol. The rename allows to introduce a new call op alongside with a future `emitc.func` op to model and facilitate functions and function calls.
This commit is contained in:
@@ -3,12 +3,12 @@ ops. Those can be translated to C/C++ via the Cpp emitter.
|
||||
|
||||
The following convention is followed:
|
||||
|
||||
* If template arguments are passed to an `emitc.call` operation, C++ is
|
||||
* If template arguments are passed to an `emitc.call_opaque` operation, C++ is
|
||||
generated.
|
||||
* If tensors are used, C++ is generated.
|
||||
* If multiple return values are used within in a functions or an `emitc.call`
|
||||
operation, C++11 is required.
|
||||
* If floating-point type template arguments are passed to an `emitc.call`
|
||||
* If multiple return values are used within in a functions or an
|
||||
`emitc.call_opaque` operation, C++11 is required.
|
||||
* If floating-point type template arguments are passed to an `emitc.call_opaque`
|
||||
operation, C++20 is required.
|
||||
* Else the generated code is compatible with C99.
|
||||
|
||||
|
||||
@@ -92,11 +92,12 @@ def EmitC_ApplyOp : EmitC_Op<"apply", []> {
|
||||
let hasVerifier = 1;
|
||||
}
|
||||
|
||||
def EmitC_CallOp : EmitC_Op<"call", []> {
|
||||
let summary = "Call operation";
|
||||
def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", []> {
|
||||
let summary = "Opaque call operation";
|
||||
let description = [{
|
||||
The `call` operation represents a C++ function call. The call allows
|
||||
specifying order of operands and attributes in the call as follows:
|
||||
The `call_opaque` operation represents a C++ function call. The callee
|
||||
can be an arbitrary non-empty string. The call allows specifying order
|
||||
of operands and attributes in the call as follows:
|
||||
|
||||
- integer value of index type refers to an operand;
|
||||
- attribute which will get lowered to constant value in call;
|
||||
@@ -105,10 +106,10 @@ def EmitC_CallOp : EmitC_Op<"call", []> {
|
||||
|
||||
```mlir
|
||||
// Custom form defining a call to `foo()`.
|
||||
%0 = emitc.call "foo" () : () -> i32
|
||||
%0 = emitc.call_opaque "foo" () : () -> i32
|
||||
|
||||
// Generic form of the same operation.
|
||||
%0 = "emitc.call"() {callee = "foo"} : () -> i32
|
||||
%0 = "emitc.call_opaque"() {callee = "foo"} : () -> i32
|
||||
```
|
||||
}];
|
||||
let arguments = (ins
|
||||
@@ -454,7 +455,8 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
|
||||
%1 = "emitc.variable"() {value = 0 : i32} : () -> i32
|
||||
%2 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
|
||||
%3 = emitc.apply "&"(%1) : (i32) -> !emitc.ptr<i32>
|
||||
emitc.call "write"(%2, %3) : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
|
||||
emitc.call_opaque "write"(%2, %3)
|
||||
: (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
|
||||
```
|
||||
}];
|
||||
|
||||
@@ -477,7 +479,7 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
|
||||
```mlir
|
||||
// Integer variable
|
||||
%0 = "emitc.variable"(){value = 42 : i32} : () -> i32
|
||||
%1 = emitc.call "foo"() : () -> (i32)
|
||||
%1 = emitc.call_opaque "foo"() : () -> (i32)
|
||||
|
||||
// Assign emitted as `... = ...;`
|
||||
"emitc.assign"(%0, %1) : (i32, i32) -> ()
|
||||
|
||||
@@ -131,7 +131,7 @@ bool CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
|
||||
// CallOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
LogicalResult emitc::CallOp::verify() {
|
||||
LogicalResult emitc::CallOpaqueOp::verify() {
|
||||
// Callee must not be empty.
|
||||
if (getCallee().empty())
|
||||
return emitOpError("callee must not be empty");
|
||||
|
||||
@@ -412,13 +412,14 @@ static LogicalResult printOperation(CppEmitter &emitter, func::CallOp callOp) {
|
||||
return success();
|
||||
}
|
||||
|
||||
static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
|
||||
static LogicalResult printOperation(CppEmitter &emitter,
|
||||
emitc::CallOpaqueOp callOpaqueOp) {
|
||||
raw_ostream &os = emitter.ostream();
|
||||
Operation &op = *callOp.getOperation();
|
||||
Operation &op = *callOpaqueOp.getOperation();
|
||||
|
||||
if (failed(emitter.emitAssignPrefix(op)))
|
||||
return failure();
|
||||
os << callOp.getCallee();
|
||||
os << callOpaqueOp.getCallee();
|
||||
|
||||
auto emitArgs = [&](Attribute attr) -> LogicalResult {
|
||||
if (auto t = dyn_cast<IntegerAttr>(attr)) {
|
||||
@@ -441,10 +442,10 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
|
||||
return success();
|
||||
};
|
||||
|
||||
if (callOp.getTemplateArgs()) {
|
||||
if (callOpaqueOp.getTemplateArgs()) {
|
||||
os << "<";
|
||||
if (failed(
|
||||
interleaveCommaWithError(*callOp.getTemplateArgs(), os, emitArgs)))
|
||||
if (failed(interleaveCommaWithError(*callOpaqueOp.getTemplateArgs(), os,
|
||||
emitArgs)))
|
||||
return failure();
|
||||
os << ">";
|
||||
}
|
||||
@@ -452,8 +453,8 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
|
||||
os << "(";
|
||||
|
||||
LogicalResult emittedArgs =
|
||||
callOp.getArgs()
|
||||
? interleaveCommaWithError(*callOp.getArgs(), os, emitArgs)
|
||||
callOpaqueOp.getArgs()
|
||||
? interleaveCommaWithError(*callOpaqueOp.getArgs(), os, emitArgs)
|
||||
: emitter.emitOperands(op);
|
||||
if (failed(emittedArgs))
|
||||
return failure();
|
||||
@@ -949,10 +950,11 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
|
||||
.Case<cf::BranchOp, cf::CondBranchOp>(
|
||||
[&](auto op) { return printOperation(*this, op); })
|
||||
// EmitC ops.
|
||||
.Case<emitc::AddOp, emitc::ApplyOp, emitc::AssignOp, emitc::CallOp,
|
||||
emitc::CastOp, emitc::CmpOp, emitc::ConstantOp, emitc::DivOp,
|
||||
emitc::ForOp, emitc::IfOp, emitc::IncludeOp, emitc::MulOp,
|
||||
emitc::RemOp, emitc::SubOp, emitc::VariableOp>(
|
||||
.Case<emitc::AddOp, emitc::ApplyOp, emitc::AssignOp,
|
||||
emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
|
||||
emitc::ConstantOp, emitc::DivOp, emitc::ForOp, emitc::IfOp,
|
||||
emitc::IncludeOp, emitc::MulOp, emitc::RemOp, emitc::SubOp,
|
||||
emitc::VariableOp>(
|
||||
[&](auto op) { return printOperation(*this, op); })
|
||||
// Func ops.
|
||||
.Case<func::CallOp, func::ConstantOp, func::FuncOp, func::ReturnOp>(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
func.func @test_if(%arg0: i1, %arg1: f32) {
|
||||
scf.if %arg0 {
|
||||
%0 = emitc.call "func_const"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -10,7 +10,7 @@ func.func @test_if(%arg0: i1, %arg1: f32) {
|
||||
// CHECK-SAME: %[[VAL_0:.*]]: i1,
|
||||
// CHECK-SAME: %[[VAL_1:.*]]: f32) {
|
||||
// CHECK-NEXT: emitc.if %[[VAL_0]] {
|
||||
// CHECK-NEXT: %[[VAL_2:.*]] = emitc.call "func_const"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_2:.*]] = emitc.call_opaque "func_const"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
@@ -18,9 +18,9 @@ func.func @test_if(%arg0: i1, %arg1: f32) {
|
||||
|
||||
func.func @test_if_else(%arg0: i1, %arg1: f32) {
|
||||
scf.if %arg0 {
|
||||
%0 = emitc.call "func_true"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_true"(%arg1) : (f32) -> i32
|
||||
} else {
|
||||
%0 = emitc.call "func_false"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_false"(%arg1) : (f32) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -28,9 +28,9 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
|
||||
// CHECK-SAME: %[[VAL_0:.*]]: i1,
|
||||
// CHECK-SAME: %[[VAL_1:.*]]: f32) {
|
||||
// CHECK-NEXT: emitc.if %[[VAL_0]] {
|
||||
// CHECK-NEXT: %[[VAL_2:.*]] = emitc.call "func_true"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_2:.*]] = emitc.call_opaque "func_true"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: } else {
|
||||
// CHECK-NEXT: %[[VAL_3:.*]] = emitc.call "func_false"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_3:.*]] = emitc.call_opaque "func_false"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
@@ -39,12 +39,12 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
|
||||
func.func @test_if_yield(%arg0: i1, %arg1: f32) {
|
||||
%0 = arith.constant 0 : i8
|
||||
%x, %y = scf.if %arg0 -> (i32, f64) {
|
||||
%1 = emitc.call "func_true_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call "func_true_2"(%arg1) : (f32) -> f64
|
||||
%1 = emitc.call_opaque "func_true_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call_opaque "func_true_2"(%arg1) : (f32) -> f64
|
||||
scf.yield %1, %2 : i32, f64
|
||||
} else {
|
||||
%1 = emitc.call "func_false_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call "func_false_2"(%arg1) : (f32) -> f64
|
||||
%1 = emitc.call_opaque "func_false_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call_opaque "func_false_2"(%arg1) : (f32) -> f64
|
||||
scf.yield %1, %2 : i32, f64
|
||||
}
|
||||
return
|
||||
@@ -56,13 +56,13 @@ func.func @test_if_yield(%arg0: i1, %arg1: f32) {
|
||||
// CHECK-NEXT: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
|
||||
// CHECK-NEXT: %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f64
|
||||
// CHECK-NEXT: emitc.if %[[VAL_0]] {
|
||||
// CHECK-NEXT: %[[VAL_5:.*]] = emitc.call "func_true_1"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_6:.*]] = emitc.call "func_true_2"(%[[VAL_1]]) : (f32) -> f64
|
||||
// CHECK-NEXT: %[[VAL_5:.*]] = emitc.call_opaque "func_true_1"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_6:.*]] = emitc.call_opaque "func_true_2"(%[[VAL_1]]) : (f32) -> f64
|
||||
// CHECK-NEXT: emitc.assign %[[VAL_5]] : i32 to %[[VAL_3]] : i32
|
||||
// CHECK-NEXT: emitc.assign %[[VAL_6]] : f64 to %[[VAL_4]] : f64
|
||||
// CHECK-NEXT: } else {
|
||||
// CHECK-NEXT: %[[VAL_7:.*]] = emitc.call "func_false_1"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_8:.*]] = emitc.call "func_false_2"(%[[VAL_1]]) : (f32) -> f64
|
||||
// CHECK-NEXT: %[[VAL_7:.*]] = emitc.call_opaque "func_false_1"(%[[VAL_1]]) : (f32) -> i32
|
||||
// CHECK-NEXT: %[[VAL_8:.*]] = emitc.call_opaque "func_false_2"(%[[VAL_1]]) : (f32) -> f64
|
||||
// CHECK-NEXT: emitc.assign %[[VAL_7]] : i32 to %[[VAL_3]] : i32
|
||||
// CHECK-NEXT: emitc.assign %[[VAL_8]] : f64 to %[[VAL_4]] : f64
|
||||
// CHECK-NEXT: }
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// CHECK-LABEL: func @opaque_attrs() {
|
||||
func.func @opaque_attrs() {
|
||||
// CHECK-NEXT: #emitc.opaque<"attr">
|
||||
emitc.call "f"() {args = [#emitc.opaque<"attr">]} : () -> ()
|
||||
emitc.call_opaque "f"() {args = [#emitc.opaque<"attr">]} : () -> ()
|
||||
// CHECK-NEXT: #emitc.opaque<"\22quoted_attr\22">
|
||||
emitc.call "f"() {args = [#emitc.opaque<"\"quoted_attr\"">]} : () -> ()
|
||||
emitc.call_opaque "f"() {args = [#emitc.opaque<"\"quoted_attr\"">]} : () -> ()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -25,48 +25,48 @@ func.func @empty_constant() {
|
||||
// -----
|
||||
|
||||
func.func @index_args_out_of_range_1() {
|
||||
// expected-error @+1 {{'emitc.call' op index argument is out of range}}
|
||||
emitc.call "test" () {args = [0 : index]} : () -> ()
|
||||
// expected-error @+1 {{'emitc.call_opaque' op index argument is out of range}}
|
||||
emitc.call_opaque "test" () {args = [0 : index]} : () -> ()
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @index_args_out_of_range_2(%arg : i32) {
|
||||
// expected-error @+1 {{'emitc.call' op index argument is out of range}}
|
||||
emitc.call "test" (%arg, %arg) {args = [2 : index]} : (i32, i32) -> ()
|
||||
// expected-error @+1 {{'emitc.call_opaque' op index argument is out of range}}
|
||||
emitc.call_opaque "test" (%arg, %arg) {args = [2 : index]} : (i32, i32) -> ()
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @empty_callee() {
|
||||
// expected-error @+1 {{'emitc.call' op callee must not be empty}}
|
||||
emitc.call "" () : () -> ()
|
||||
// expected-error @+1 {{'emitc.call_opaque' op callee must not be empty}}
|
||||
emitc.call_opaque "" () : () -> ()
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @nonetype_arg(%arg : i32) {
|
||||
// expected-error @+1 {{'emitc.call' op array argument has no type}}
|
||||
emitc.call "nonetype_arg"(%arg) {args = [0 : index, [0, 1, 2]]} : (i32) -> i32
|
||||
// expected-error @+1 {{'emitc.call_opaque' op array argument has no type}}
|
||||
emitc.call_opaque "nonetype_arg"(%arg) {args = [0 : index, [0, 1, 2]]} : (i32) -> i32
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @array_template_arg(%arg : i32) {
|
||||
// expected-error @+1 {{'emitc.call' op template argument has invalid type}}
|
||||
emitc.call "nonetype_template_arg"(%arg) {template_args = [[0, 1, 2]]} : (i32) -> i32
|
||||
// expected-error @+1 {{'emitc.call_opaque' op template argument has invalid type}}
|
||||
emitc.call_opaque "nonetype_template_arg"(%arg) {template_args = [[0, 1, 2]]} : (i32) -> i32
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @dense_template_argument(%arg : i32) {
|
||||
// expected-error @+1 {{'emitc.call' op template argument has invalid type}}
|
||||
emitc.call "dense_template_argument"(%arg) {template_args = [dense<[1.0, 1.0]> : tensor<2xf32>]} : (i32) -> i32
|
||||
// expected-error @+1 {{'emitc.call_opaque' op template argument has invalid type}}
|
||||
emitc.call_opaque "dense_template_argument"(%arg) {template_args = [dense<[1.0, 1.0]> : tensor<2xf32>]} : (i32) -> i32
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ emitc.include "test.h"
|
||||
|
||||
// CHECK-LABEL: func @f(%{{.*}}: i32, %{{.*}}: !emitc.opaque<"int32_t">) {
|
||||
func.func @f(%arg0: i32, %f: !emitc.opaque<"int32_t">) {
|
||||
%1 = "emitc.call"() {callee = "blah"} : () -> i64
|
||||
emitc.call "foo" (%1) {args = [
|
||||
%1 = "emitc.call_opaque"() {callee = "blah"} : () -> i64
|
||||
emitc.call_opaque "foo" (%1) {args = [
|
||||
0 : index, dense<[0, 1]> : tensor<2xi32>, 0 : index
|
||||
]} : (i64) -> ()
|
||||
return
|
||||
@@ -100,14 +100,14 @@ func.func @cmp(%arg0 : i32, %arg1 : f32, %arg2 : i64, %arg3 : f64, %arg4 : !emit
|
||||
|
||||
func.func @test_if(%arg0: i1, %arg1: f32) {
|
||||
emitc.if %arg0 {
|
||||
%0 = emitc.call "func_const"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func.func @test_if_explicit_yield(%arg0: i1, %arg1: f32) {
|
||||
emitc.if %arg0 {
|
||||
%0 = emitc.call "func_const"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
|
||||
emitc.yield
|
||||
}
|
||||
return
|
||||
@@ -115,9 +115,9 @@ func.func @test_if_explicit_yield(%arg0: i1, %arg1: f32) {
|
||||
|
||||
func.func @test_if_else(%arg0: i1, %arg1: f32) {
|
||||
emitc.if %arg0 {
|
||||
%0 = emitc.call "func_true"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_true"(%arg1) : (f32) -> i32
|
||||
} else {
|
||||
%0 = emitc.call "func_false"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_false"(%arg1) : (f32) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -130,14 +130,14 @@ func.func @test_assign(%arg1: f32) {
|
||||
|
||||
func.func @test_for(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
emitc.for %i0 = %arg0 to %arg1 step %arg2 {
|
||||
%0 = emitc.call "func_const"(%i0) : (index) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%i0) : (index) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func.func @test_for_explicit_yield(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
emitc.for %i0 = %arg0 to %arg1 step %arg2 {
|
||||
%0 = emitc.call "func_const"(%i0) : (index) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%i0) : (index) -> i32
|
||||
emitc.yield
|
||||
}
|
||||
return
|
||||
@@ -145,7 +145,7 @@ func.func @test_for_explicit_yield(%arg0 : index, %arg1 : index, %arg2 : index)
|
||||
|
||||
func.func @test_for_not_index_induction(%arg0 : i16, %arg1 : i16, %arg2 : i16) {
|
||||
emitc.for %i0 = %arg0 to %arg1 step %arg2 : i16 {
|
||||
%0 = emitc.call "func_const"(%i0) : (i16) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%i0) : (i16) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
// CHECK-LABEL: func @opaque_types() {
|
||||
func.func @opaque_types() {
|
||||
// CHECK-NEXT: !emitc.opaque<"int">
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"int">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"int">>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.opaque<"byte">
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"byte">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"byte">>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.opaque<"unsigned">
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"unsigned">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"unsigned">>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.opaque<"status_t">
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"status_t">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"status_t">>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.opaque<"std::vector<std::string>">
|
||||
emitc.call "f"() {template_args = [!emitc.opaque<"std::vector<std::string>">]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.opaque<"std::vector<std::string>">]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.opaque<"SmallVector<int*, 4>">
|
||||
emitc.call "f"() {template_args = [!emitc.opaque<"SmallVector<int*, 4>">]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.opaque<"SmallVector<int*, 4>">]} : () -> ()
|
||||
|
||||
return
|
||||
}
|
||||
@@ -23,19 +23,19 @@ func.func @opaque_types() {
|
||||
// CHECK-LABEL: func @pointer_types() {
|
||||
func.func @pointer_types() {
|
||||
// CHECK-NEXT: !emitc.ptr<i32>
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<i32>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<i32>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.ptr<i64>
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<i64>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<i64>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.ptr<f32>
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<f32>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<f32>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.ptr<f64>
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<f64>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<f64>]} : () -> ()
|
||||
// CHECK-NEXT: !emitc.ptr<i32>
|
||||
%0 = emitc.call "f"() : () -> (!emitc.ptr<i32>)
|
||||
%0 = emitc.call_opaque "f"() : () -> (!emitc.ptr<i32>)
|
||||
// CHECK-NEXT: (!emitc.ptr<i32>) -> !emitc.ptr<!emitc.ptr<i32>>
|
||||
%1 = emitc.call "f"(%0) : (!emitc.ptr<i32>) -> (!emitc.ptr<!emitc.ptr<i32>>)
|
||||
%1 = emitc.call_opaque "f"(%0) : (!emitc.ptr<i32>) -> (!emitc.ptr<!emitc.ptr<i32>>)
|
||||
// CHECK-NEXT: !emitc.ptr<!emitc.opaque<"int">>
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<!emitc.opaque<"int">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<!emitc.opaque<"int">>]} : () -> ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// CHECK-LABEL: void opaque_attrs() {
|
||||
func.func @opaque_attrs() {
|
||||
// CHECK-NEXT: f(OPAQUE_ENUM_VALUE);
|
||||
emitc.call "f"() {args = [#emitc.opaque<"OPAQUE_ENUM_VALUE">]} : () -> ()
|
||||
emitc.call_opaque "f"() {args = [#emitc.opaque<"OPAQUE_ENUM_VALUE">]} : () -> ()
|
||||
// CHECK-NEXT: f("some string");
|
||||
emitc.call "f"() {args = [#emitc.opaque<"\"some string\"">]} : () -> ()
|
||||
emitc.call_opaque "f"() {args = [#emitc.opaque<"\"some string\"">]} : () -> ()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT
|
||||
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s -check-prefix=CPP-DECLTOP
|
||||
|
||||
func.func @emitc_call() {
|
||||
%0 = emitc.call "func_a" () : () -> i32
|
||||
%1 = emitc.call "func_b" () : () -> i32
|
||||
func.func @emitc_call_opaque() {
|
||||
%0 = emitc.call_opaque "func_a" () : () -> i32
|
||||
%1 = emitc.call_opaque "func_b" () : () -> i32
|
||||
return
|
||||
}
|
||||
// CPP-DEFAULT: void emitc_call() {
|
||||
// CPP-DEFAULT: void emitc_call_opaque() {
|
||||
// CPP-DEFAULT-NEXT: int32_t [[V0:[^ ]*]] = func_a();
|
||||
// CPP-DEFAULT-NEXT: int32_t [[V1:[^ ]*]] = func_b();
|
||||
|
||||
// CPP-DECLTOP: void emitc_call() {
|
||||
// CPP-DECLTOP: void emitc_call_opaque() {
|
||||
// CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]];
|
||||
// CPP-DECLTOP-NEXT: int32_t [[V1:[^ ]*]];
|
||||
// CPP-DECLTOP-NEXT: [[V0:]] = func_a();
|
||||
// CPP-DECLTOP-NEXT: [[V1:]] = func_b();
|
||||
|
||||
|
||||
func.func @emitc_call_two_results() {
|
||||
func.func @emitc_call_opaque_two_results() {
|
||||
%0 = arith.constant 0 : index
|
||||
%1:2 = emitc.call "two_results" () : () -> (i32, i32)
|
||||
%1:2 = emitc.call_opaque "two_results" () : () -> (i32, i32)
|
||||
return
|
||||
}
|
||||
// CPP-DEFAULT: void emitc_call_two_results() {
|
||||
// CPP-DEFAULT: void emitc_call_opaque_two_results() {
|
||||
// CPP-DEFAULT-NEXT: size_t [[V1:[^ ]*]] = 0;
|
||||
// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]];
|
||||
// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]];
|
||||
// CPP-DEFAULT-NEXT: std::tie([[V2]], [[V3]]) = two_results();
|
||||
|
||||
// CPP-DECLTOP: void emitc_call_two_results() {
|
||||
// CPP-DECLTOP: void emitc_call_opaque_two_results() {
|
||||
// CPP-DECLTOP-NEXT: size_t [[V1:[^ ]*]];
|
||||
// CPP-DECLTOP-NEXT: int32_t [[V2:[^ ]*]];
|
||||
// CPP-DECLTOP-NEXT: int32_t [[V3:[^ ]*]];
|
||||
|
||||
@@ -8,13 +8,13 @@ emitc.include <"myheader.h">
|
||||
// CHECK: void test_foo_print() {
|
||||
func.func @test_foo_print() {
|
||||
// CHECK: [[V1:[^ ]*]] = foo::constant({0, 1});
|
||||
%0 = emitc.call "foo::constant"() {args = [dense<[0, 1]> : tensor<2xi32>]} : () -> (i32)
|
||||
%0 = emitc.call_opaque "foo::constant"() {args = [dense<[0, 1]> : tensor<2xi32>]} : () -> (i32)
|
||||
// CHECK: [[V2:[^ ]*]] = foo::op_and_attr({0, 1}, [[V1]]);
|
||||
%1 = emitc.call "foo::op_and_attr"(%0) {args = [dense<[0, 1]> : tensor<2xi32>, 0 : index]} : (i32) -> (i32)
|
||||
%1 = emitc.call_opaque "foo::op_and_attr"(%0) {args = [dense<[0, 1]> : tensor<2xi32>, 0 : index]} : (i32) -> (i32)
|
||||
// CHECK: [[V3:[^ ]*]] = foo::op_and_attr([[V2]], {0, 1});
|
||||
%2 = emitc.call "foo::op_and_attr"(%1) {args = [0 : index, dense<[0, 1]> : tensor<2xi32>]} : (i32) -> (i32)
|
||||
%2 = emitc.call_opaque "foo::op_and_attr"(%1) {args = [0 : index, dense<[0, 1]> : tensor<2xi32>]} : (i32) -> (i32)
|
||||
// CHECK: foo::print([[V3]]);
|
||||
emitc.call "foo::print"(%2): (i32) -> ()
|
||||
emitc.call_opaque "foo::print"(%2): (i32) -> ()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func.func @test_single_return(%arg0 : i32) -> i32 {
|
||||
// CHECK: std::tuple<int32_t, int32_t> test_multiple_return()
|
||||
func.func @test_multiple_return() -> (i32, i32) {
|
||||
// CHECK: std::tie([[V3:.*]], [[V4:.*]]) = foo::blah();
|
||||
%0:2 = emitc.call "foo::blah"() : () -> (i32, i32)
|
||||
%0:2 = emitc.call_opaque "foo::blah"() : () -> (i32, i32)
|
||||
// CHECK: [[V5:[^ ]*]] = test_single_return([[V3]]);
|
||||
%1 = call @test_single_return(%0#0) : (i32) -> i32
|
||||
// CHECK: return std::make_tuple([[V5]], [[V4]]);
|
||||
@@ -37,48 +37,48 @@ func.func @test_multiple_return() -> (i32, i32) {
|
||||
// CHECK: test_float
|
||||
func.func @test_float() {
|
||||
// CHECK: foo::constant({(float)0.0e+00, (float)1.000000000e+00})
|
||||
%0 = emitc.call "foo::constant"() {args = [dense<[0.000000e+00, 1.000000e+00]> : tensor<2xf32>]} : () -> f32
|
||||
%0 = emitc.call_opaque "foo::constant"() {args = [dense<[0.000000e+00, 1.000000e+00]> : tensor<2xf32>]} : () -> f32
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK: test_uint
|
||||
func.func @test_uint() {
|
||||
// CHECK: uint32_t
|
||||
%0 = emitc.call "foo::constant"() {args = [dense<[0, 1]> : tensor<2xui32>]} : () -> ui32
|
||||
%0 = emitc.call_opaque "foo::constant"() {args = [dense<[0, 1]> : tensor<2xui32>]} : () -> ui32
|
||||
// CHECK: uint64_t
|
||||
%1 = emitc.call "foo::constant"() {args = [dense<[0, 1]> : tensor<2xui64>]} : () -> ui64
|
||||
%1 = emitc.call_opaque "foo::constant"() {args = [dense<[0, 1]> : tensor<2xui64>]} : () -> ui64
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK: int64_t test_plus_int(int64_t [[V1]])
|
||||
func.func @test_plus_int(%arg0 : i64) -> i64 {
|
||||
// CHECK: mhlo::add([[V1]], [[V1]])
|
||||
%0 = emitc.call "mhlo::add"(%arg0, %arg0) {args = [0 : index, 1 : index]} : (i64, i64) -> i64
|
||||
%0 = emitc.call_opaque "mhlo::add"(%arg0, %arg0) {args = [0 : index, 1 : index]} : (i64, i64) -> i64
|
||||
return %0 : i64
|
||||
}
|
||||
|
||||
// CHECK: Tensor<float, 2> mixed_types(Tensor<double, 2> [[V1]])
|
||||
func.func @mixed_types(%arg0: tensor<2xf64>) -> tensor<2xf32> {
|
||||
// CHECK: foo::mixed_types([[V1]]);
|
||||
%0 = emitc.call "foo::mixed_types"(%arg0) {args = [0 : index]} : (tensor<2xf64>) -> tensor<2xf32>
|
||||
%0 = emitc.call_opaque "foo::mixed_types"(%arg0) {args = [0 : index]} : (tensor<2xf64>) -> tensor<2xf32>
|
||||
return %0 : tensor<2xf32>
|
||||
}
|
||||
|
||||
// CHECK: Tensor<uint64_t> mhlo_convert(Tensor<uint32_t> [[V1]])
|
||||
func.func @mhlo_convert(%arg0: tensor<ui32>) -> tensor<ui64> {
|
||||
// CHECK: mhlo::convert([[V1]]);
|
||||
%0 = emitc.call "mhlo::convert"(%arg0) {args = [0 : index]} : (tensor<ui32>) -> tensor<ui64>
|
||||
%0 = emitc.call_opaque "mhlo::convert"(%arg0) {args = [0 : index]} : (tensor<ui32>) -> tensor<ui64>
|
||||
return %0 : tensor<ui64>
|
||||
}
|
||||
|
||||
// CHECK: status_t opaque_types(bool [[V1:[^ ]*]], char [[V2:[^ ]*]]) {
|
||||
func.func @opaque_types(%arg0: !emitc.opaque<"bool">, %arg1: !emitc.opaque<"char">) -> !emitc.opaque<"status_t"> {
|
||||
// CHECK: int [[V3:[^ ]*]] = a([[V1]], [[V2]]);
|
||||
%0 = emitc.call "a"(%arg0, %arg1) : (!emitc.opaque<"bool">, !emitc.opaque<"char">) -> (!emitc.opaque<"int">)
|
||||
%0 = emitc.call_opaque "a"(%arg0, %arg1) : (!emitc.opaque<"bool">, !emitc.opaque<"char">) -> (!emitc.opaque<"int">)
|
||||
// CHECK: char [[V4:[^ ]*]] = b([[V3]]);
|
||||
%1 = emitc.call "b"(%0): (!emitc.opaque<"int">) -> (!emitc.opaque<"char">)
|
||||
%1 = emitc.call_opaque "b"(%0): (!emitc.opaque<"int">) -> (!emitc.opaque<"char">)
|
||||
// CHECK: status_t [[V5:[^ ]*]] = c([[V3]], [[V4]]);
|
||||
%2 = emitc.call "c"(%0, %1): (!emitc.opaque<"int">, !emitc.opaque<"char">) -> (!emitc.opaque<"status_t">)
|
||||
%2 = emitc.call_opaque "c"(%0, %1): (!emitc.opaque<"int">, !emitc.opaque<"char">) -> (!emitc.opaque<"status_t">)
|
||||
return %2 : !emitc.opaque<"status_t">
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ func.func @simple(i64, i1) -> i64 {
|
||||
^bb1:
|
||||
cf.br ^bb3(%a: i64)
|
||||
^bb2:
|
||||
%b = emitc.call "add"(%a, %a) : (i64, i64) -> i64
|
||||
%b = emitc.call_opaque "add"(%a, %a) : (i64, i64) -> i64
|
||||
cf.br ^bb3(%b: i64)
|
||||
^bb3(%c: i64):
|
||||
cf.br ^bb4(%c, %a : i64, i64)
|
||||
^bb4(%d : i64, %e : i64):
|
||||
%0 = emitc.call "add"(%d, %e) : (i64, i64) -> i64
|
||||
%0 = emitc.call_opaque "add"(%d, %e) : (i64, i64) -> i64
|
||||
return %0 : i64
|
||||
}
|
||||
// CPP-DECLTOP: int64_t simple(int64_t [[A:[^ ]*]], bool [[COND:[^ ]*]]) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
func.func @test_for(%arg0 : index, %arg1 : index, %arg2 : index) {
|
||||
emitc.for %i0 = %arg0 to %arg1 step %arg2 {
|
||||
%0 = emitc.call "f"() : () -> i32
|
||||
%0 = emitc.call_opaque "f"() : () -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -35,8 +35,8 @@ func.func @test_for_yield() {
|
||||
emitc.assign %s0 : i32 to %2 : i32
|
||||
emitc.assign %p0 : f32 to %3 : f32
|
||||
emitc.for %iter = %start to %stop step %step {
|
||||
%sn = emitc.call "add"(%2, %iter) : (i32, index) -> i32
|
||||
%pn = emitc.call "mul"(%3, %iter) : (f32, index) -> f32
|
||||
%sn = emitc.call_opaque "add"(%2, %iter) : (i32, index) -> i32
|
||||
%pn = emitc.call_opaque "mul"(%3, %iter) : (f32, index) -> f32
|
||||
emitc.assign %sn : i32 to %2 : i32
|
||||
emitc.assign %pn : f32 to %3 : f32
|
||||
emitc.yield
|
||||
@@ -116,8 +116,8 @@ func.func @test_for_yield_2() {
|
||||
emitc.assign %s0 : i32 to %2 : i32
|
||||
emitc.assign %p0 : f32 to %3 : f32
|
||||
emitc.for %iter = %start to %stop step %step {
|
||||
%sn = emitc.call "add"(%2, %iter) : (i32, index) -> i32
|
||||
%pn = emitc.call "mul"(%3, %iter) : (f32, index) -> f32
|
||||
%sn = emitc.call_opaque "add"(%2, %iter) : (i32, index) -> i32
|
||||
%pn = emitc.call_opaque "mul"(%3, %iter) : (f32, index) -> f32
|
||||
emitc.assign %sn : i32 to %2 : i32
|
||||
emitc.assign %pn : f32 to %3 : f32
|
||||
emitc.yield
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
func.func @test_if(%arg0: i1, %arg1: f32) {
|
||||
emitc.if %arg0 {
|
||||
%0 = emitc.call "func_const"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -23,9 +23,9 @@ func.func @test_if(%arg0: i1, %arg1: f32) {
|
||||
|
||||
func.func @test_if_else(%arg0: i1, %arg1: f32) {
|
||||
emitc.if %arg0 {
|
||||
%0 = emitc.call "func_true"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_true"(%arg1) : (f32) -> i32
|
||||
} else {
|
||||
%0 = emitc.call "func_false"(%arg1) : (f32) -> i32
|
||||
%0 = emitc.call_opaque "func_false"(%arg1) : (f32) -> i32
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -53,13 +53,13 @@ func.func @test_if_yield(%arg0: i1, %arg1: f32) {
|
||||
%x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
|
||||
%y = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f64
|
||||
emitc.if %arg0 {
|
||||
%1 = emitc.call "func_true_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call "func_true_2"(%arg1) : (f32) -> f64
|
||||
%1 = emitc.call_opaque "func_true_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call_opaque "func_true_2"(%arg1) : (f32) -> f64
|
||||
emitc.assign %1 : i32 to %x : i32
|
||||
emitc.assign %2 : f64 to %y : f64
|
||||
} else {
|
||||
%1 = emitc.call "func_false_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call "func_false_2"(%arg1) : (f32) -> f64
|
||||
%1 = emitc.call_opaque "func_false_1"(%arg1) : (f32) -> i32
|
||||
%2 = emitc.call_opaque "func_false_2"(%arg1) : (f32) -> f64
|
||||
emitc.assign %1 : i32 to %x : i32
|
||||
emitc.assign %2 : f64 to %y : f64
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
func.func @emitc_call_operand() {
|
||||
%p0 = emitc.literal "M_PI" : f32
|
||||
%1 = emitc.call "foo"(%p0) : (f32) -> f32
|
||||
%1 = emitc.call_opaque "foo"(%p0) : (f32) -> f32
|
||||
return
|
||||
}
|
||||
// CPP-DEFAULT: void emitc_call_operand() {
|
||||
@@ -15,7 +15,7 @@ func.func @emitc_call_operand() {
|
||||
|
||||
func.func @emitc_call_operand_arg() {
|
||||
%p0 = emitc.literal "M_PI" : f32
|
||||
%1 = emitc.call "bar"(%p0) {args = [42 : i32, 0 : index]} : (f32) -> f32
|
||||
%1 = emitc.call_opaque "bar"(%p0) {args = [42 : i32, 0 : index]} : (f32) -> f32
|
||||
return
|
||||
}
|
||||
// CPP-DEFAULT: void emitc_call_operand_arg() {
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
// CHECK-LABEL: void opaque_types() {
|
||||
func.func @opaque_types() {
|
||||
// CHECK-NEXT: f<int>();
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"int">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"int">>]} : () -> ()
|
||||
// CHECK-NEXT: f<byte>();
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"byte">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"byte">>]} : () -> ()
|
||||
// CHECK-NEXT: f<unsigned>();
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"unsigned">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"unsigned">>]} : () -> ()
|
||||
// CHECK-NEXT: f<status_t>();
|
||||
emitc.call "f"() {template_args = [!emitc<opaque<"status_t">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc<opaque<"status_t">>]} : () -> ()
|
||||
// CHECK-NEXT: f<std::vector<std::string>>();
|
||||
emitc.call "f"() {template_args = [!emitc.opaque<"std::vector<std::string>">]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.opaque<"std::vector<std::string>">]} : () -> ()
|
||||
|
||||
return
|
||||
}
|
||||
@@ -19,19 +19,19 @@ func.func @opaque_types() {
|
||||
// CHECK-LABEL: void ptr_types() {
|
||||
func.func @ptr_types() {
|
||||
// CHECK-NEXT: f<int32_t*>();
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<i32>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<i32>]} : () -> ()
|
||||
// CHECK-NEXT: f<int64_t*>();
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<i64>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<i64>]} : () -> ()
|
||||
// CHECK-NEXT: f<float*>();
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<f32>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<f32>]} : () -> ()
|
||||
// CHECK-NEXT: f<double*>();
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<f64>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<f64>]} : () -> ()
|
||||
// CHECK-NEXT: int32_t* [[V0:[^ ]*]] = f();
|
||||
%0 = emitc.call "f"() : () -> (!emitc.ptr<i32>)
|
||||
%0 = emitc.call_opaque "f"() : () -> (!emitc.ptr<i32>)
|
||||
// CHECK-NEXT: int32_t** [[V1:[^ ]*]] = f([[V0:[^ ]*]]);
|
||||
%1 = emitc.call "f"(%0) : (!emitc.ptr<i32>) -> (!emitc.ptr<!emitc.ptr<i32>>)
|
||||
%1 = emitc.call_opaque "f"(%0) : (!emitc.ptr<i32>) -> (!emitc.ptr<!emitc.ptr<i32>>)
|
||||
// CHECK-NEXT: f<int*>();
|
||||
emitc.call "f"() {template_args = [!emitc.ptr<!emitc.opaque<"int">>]} : () -> ()
|
||||
emitc.call_opaque "f"() {template_args = [!emitc.ptr<!emitc.opaque<"int">>]} : () -> ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user