mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-27 20:06:20 +00:00
[mlir][emitc] Add a cast op
This adds a cast operation that allows to perform an explicit type conversion. The cast op is emitted as a C-style cast. It can be applied to integer, float, index and EmitC types. Reviewed By: jpienaar Differential Revision: https://reviews.llvm.org/D123514
This commit is contained in:
parent
0d70bc990b
commit
84fe39a45b
@ -16,6 +16,7 @@
|
||||
include "mlir/Dialect/EmitC/IR/EmitCAttributes.td"
|
||||
include "mlir/Dialect/EmitC/IR/EmitCTypes.td"
|
||||
|
||||
include "mlir/Interfaces/CastInterfaces.td"
|
||||
include "mlir/Interfaces/SideEffectInterfaces.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -88,6 +89,33 @@ def EmitC_CallOp : EmitC_Op<"call", []> {
|
||||
let hasVerifier = 1;
|
||||
}
|
||||
|
||||
def EmitC_CastOp : EmitC_Op<"cast", [
|
||||
DeclareOpInterfaceMethods<CastOpInterface>,
|
||||
SameOperandsAndResultShape
|
||||
]> {
|
||||
let summary = "Cast operation";
|
||||
let description = [{
|
||||
The `cast` operation performs an explicit type conversion and is emitted
|
||||
as a C-style cast expression. It can be applied to integer, float, index
|
||||
and EmitC types.
|
||||
|
||||
Example:
|
||||
|
||||
```mlir
|
||||
// Cast from `int32_t` to `float`
|
||||
%0 = emitc.cast %arg0: i32 to f32
|
||||
|
||||
// Cast from `void` to `int32_t` pointer
|
||||
%1 = emitc.cast %arg1 :
|
||||
!emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
|
||||
```
|
||||
}];
|
||||
|
||||
let arguments = (ins AnyType:$source);
|
||||
let results = (outs AnyType:$dest);
|
||||
let assemblyFormat = "$source attr-dict `:` type($source) `to` type($dest)";
|
||||
}
|
||||
|
||||
def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
|
||||
let summary = "Constant operation";
|
||||
let description = [{
|
||||
|
@ -9,6 +9,7 @@ add_mlir_dialect_library(MLIREmitC
|
||||
MLIREmitCAttributesIncGen
|
||||
|
||||
LINK_LIBS PUBLIC
|
||||
MLIRCastInterfaces
|
||||
MLIRIR
|
||||
MLIRSideEffectInterfaces
|
||||
)
|
||||
|
@ -62,6 +62,19 @@ LogicalResult ApplyOp::verify() {
|
||||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CastOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
|
||||
Type input = inputs.front(), output = outputs.front();
|
||||
|
||||
return ((input.isa<IntegerType, FloatType, IndexType, emitc::OpaqueType,
|
||||
emitc::PointerType>()) &&
|
||||
(output.isa<IntegerType, FloatType, IndexType, emitc::OpaqueType,
|
||||
emitc::PointerType>()));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -383,6 +383,21 @@ static LogicalResult printOperation(CppEmitter &emitter,
|
||||
return success();
|
||||
}
|
||||
|
||||
static LogicalResult printOperation(CppEmitter &emitter, emitc::CastOp castOp) {
|
||||
raw_ostream &os = emitter.ostream();
|
||||
Operation &op = *castOp.getOperation();
|
||||
|
||||
if (failed(emitter.emitAssignPrefix(op)))
|
||||
return failure();
|
||||
os << "(";
|
||||
if (failed(emitter.emitType(op.getLoc(), op.getResult(0).getType())))
|
||||
return failure();
|
||||
os << ") ";
|
||||
os << emitter.getOrCreateName(castOp.getOperand());
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
static LogicalResult printOperation(CppEmitter &emitter,
|
||||
emitc::IncludeOp includeOp) {
|
||||
raw_ostream &os = emitter.ostream();
|
||||
@ -918,7 +933,7 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
|
||||
.Case<cf::BranchOp, cf::CondBranchOp>(
|
||||
[&](auto op) { return printOperation(*this, op); })
|
||||
// EmitC ops.
|
||||
.Case<emitc::ApplyOp, emitc::CallOp, emitc::ConstantOp,
|
||||
.Case<emitc::ApplyOp, emitc::CallOp, emitc::CastOp, emitc::ConstantOp,
|
||||
emitc::IncludeOp, emitc::VariableOp>(
|
||||
[&](auto op) { return printOperation(*this, op); })
|
||||
// Func ops.
|
||||
|
@ -93,3 +93,11 @@ func.func @var_attribute_return_type_2() {
|
||||
%c0 = "emitc.variable"(){value = "nullptr" : !emitc.ptr<i64>} : () -> !emitc.ptr<i32>
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func.func @cast_tensor(%arg : tensor<f32>) {
|
||||
// expected-error @+1 {{'emitc.cast' op operand type 'tensor<f32>' and result type 'tensor<f32>' are cast incompatible}}
|
||||
%1 = emitc.cast %arg: tensor<f32> to tensor<f32>
|
||||
return
|
||||
}
|
||||
|
@ -12,6 +12,11 @@ func.func @f(%arg0: i32, %f: !emitc.opaque<"int32_t">) {
|
||||
return
|
||||
}
|
||||
|
||||
func.func @cast(%arg0: i32) {
|
||||
%1 = emitc.cast %arg0: i32 to f32
|
||||
return
|
||||
}
|
||||
|
||||
func.func @c() {
|
||||
%1 = "emitc.constant"(){value = 42 : i32} : () -> i32
|
||||
return
|
||||
|
30
mlir/test/Target/Cpp/cast.mlir
Normal file
30
mlir/test/Target/Cpp/cast.mlir
Normal file
@ -0,0 +1,30 @@
|
||||
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
|
||||
// CHECK-LABEL: void cast
|
||||
func.func @cast(%arg0 : i32) {
|
||||
// CHECK-NEXT: uint32_t [[V1:[^ ]*]] = (uint32_t) [[V0:[^ ]*]]
|
||||
%1 = emitc.cast %arg0: i32 to ui32
|
||||
|
||||
// CHECK-NEXT: int64_t [[V4:[^ ]*]] = (int64_t) [[V0:[^ ]*]]
|
||||
%2 = emitc.cast %arg0: i32 to i64
|
||||
// CHECK-NEXT: int64_t [[V5:[^ ]*]] = (uint64_t) [[V0:[^ ]*]]
|
||||
%3 = emitc.cast %arg0: i32 to ui64
|
||||
|
||||
// CHECK-NEXT: float [[V4:[^ ]*]] = (float) [[V0:[^ ]*]]
|
||||
%4 = emitc.cast %arg0: i32 to f32
|
||||
// CHECK-NEXT: double [[V5:[^ ]*]] = (double) [[V0:[^ ]*]]
|
||||
%5 = emitc.cast %arg0: i32 to f64
|
||||
|
||||
// CHECK-NEXT: bool [[V6:[^ ]*]] = (bool) [[V0:[^ ]*]]
|
||||
%6 = emitc.cast %arg0: i32 to i1
|
||||
|
||||
// CHECK-NEXT: mytype [[V7:[^ ]*]] = (mytype) [[V0:[^ ]*]]
|
||||
%7 = emitc.cast %arg0: i32 to !emitc.opaque<"mytype">
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: void cast_ptr
|
||||
func.func @cast_ptr(%arg0 : !emitc.ptr<!emitc.opaque<"void">>) {
|
||||
// CHECK-NEXT: int32_t* [[V1:[^ ]*]] = (int32_t*) [[V0:[^ ]*]]
|
||||
%1 = emitc.cast %arg0 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
|
||||
return
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user