cir.alloc_exception
(cir::AllocException)Defines a scope-local variable
Syntax:
operation ::= `cir.alloc_exception` `(` $allocType `)` `->` type($addr) attr-dict
Implements a slightly higher level __cxa_allocate_exception:
void *__cxa_allocate_exception(size_t thrown_size);
If operation fails, program terminates, not throw.
Example:
// if (b == 0) {
// ...
// throw "...";
cir.if %10 {
%11 = cir.alloc_exception(!cir.ptr<!u8i>) -> <!cir.ptr<!u8i>>
... // store exception content into %11
cir.throw(%11 : !cir.ptr<!cir.ptr<!u8i>>, ...
Attribute | MLIR Type | Description |
---|---|---|
allocType | ::mlir::TypeAttr | any type attribute |
Result | Description |
---|---|
addr | CIR pointer type |
cir.alloca
(cir::AllocaOp)Defines a scope-local variable
Syntax:
operation ::= `cir.alloca` $allocaType `,` `cir.ptr` type($addr) `,`
($dynAllocSize^ `:` type($dynAllocSize) `,`)?
`[` $name
(`,` `init` $init^)?
`]`
(`ast` $ast^)? attr-dict
The cir.alloca
operation defines a scope-local variable.
The presence init
attribute indicates that the local variable represented by this alloca was originally initialized in C/C++ source code. In such cases, the first use contains the initialization (a cir.store, a cir.call to a ctor, etc).
The dynAllocSize
specifies the size to dynamically allocate on the stack and ignores the allocation size based on the original type. This is useful when handling VLAs and is omitted when declaring regular local variables.
The result type is a pointer to the input's type.
Example:
// int count = 3;
%0 = cir.alloca i32, !cir.ptr<i32>, ["count", init] {alignment = 4 : i64}
// int *ptr;
%1 = cir.alloca !cir.ptr<i32>, cir.ptr <!cir.ptr<i32>>, ["ptr"] {alignment = 8 : i64}
...
Attribute | MLIR Type | Description |
---|---|---|
allocaType | ::mlir::TypeAttr | any type attribute |
name | ::mlir::StringAttr | string attribute |
init | ::mlir::UnitAttr | unit attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute whose minimum value is 0 |
ast | ::mlir::cir::ASTVarDeclInterface | ASTVarDeclInterface instance |
Operand | Description |
---|---|
dynAllocSize | Integer type with arbitrary precision up to a fixed limit |
Result | Description |
---|---|
addr | CIR pointer type |
cir.await
(cir::AwaitOp)Wraps C++ co_await implicit logic
Syntax:
operation ::= `cir.await` `(` $kind `,`
`ready` `:` $ready `,`
`suspend` `:` $suspend `,`
`resume` `:` $resume `,`
`)`
attr-dict
The under the hood effect of using C++ co_await expr
roughly translates to:
// co_await expr;
auto &&x = CommonExpr();
if (!x.await_ready()) {
...
x.await_suspend(...);
...
}
x.await_resume();
cir.await
represents this logic by using 3 regions:
Breaking this up in regions allow individual scrutiny of conditions which might lead to folding some of them out. Lowerings coming out of CIR, e.g. LLVM, should use the suspend
region to track more lower level codegen (e.g. intrinsic emission for coro.save/coro.suspend).
There are also 3 flavors of cir.await
available:
init
: compiler generated initial suspend via implicit co_await
.user
: also known as normal, representing user written co_await's.final
: compiler generated final suspend via implicit co_await
.From the C++ snippet we get:
cir.scope {
... // auto &&x = CommonExpr();
cir.await(user, ready : {
... // x.await_ready()
}, suspend : {
... // x.await_suspend()
}, resume : {
... // x.await_resume()
})
}
Note that resulution of the common expression is assumed to happen as part of the enclosing await scope.
Traits: NoRegionArguments
, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, RegionBranchOpInterface
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::AwaitKindAttr | await kind |
cir.base_class_addr
(cir::BaseClassAddrOp)Get the base class address for a class/struct
Syntax:
operation ::= `cir.base_class_addr` `(`
$derived_addr `:` `cir.ptr` type($derived_addr)
`)` `->` `cir.ptr` type($base_addr) attr-dict
The cir.base_class_addr
operaration gets the address of a particular base class given a derived class pointer.
Example:
TBD
Operand | Description |
---|---|
derived_addr | CIR pointer type |
Result | Description |
---|---|
base_addr | CIR pointer type |
cir.binop
(cir::BinOp)Binary operations (arith and logic)
Syntax:
operation ::= `cir.binop` `(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) attr-dict
cir.binop performs the binary operation according to the specified opcode kind: [mul, div, rem, add, sub, and, xor, or].
It requires two input operands and has one result, all types should be the same.
%7 = cir.binop(add, %1, %2) : !s32i
%7 = cir.binop(mul, %1, %2) : !u8i
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
, SameTypeOperands
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::BinOpKindAttr | binary operation (arith and logic) kind |
Operand | Description |
---|---|
lhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
rhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.brcond
(cir::BrCondOp)Conditional branch
Syntax:
operation ::= `cir.brcond` $cond
$destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?
`,`
$destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?
attr-dict
The cir.brcond %cond, ^bb0, ^bb1
branches to ‘bb0' block in case %cond (which must be a !cir.bool type) evaluates to true, otherwise it branches to ‘bb1'.
Example:
...
cir.brcond %a, ^bb3, ^bb4
^bb3:
cir.return
^bb4:
cir.yield
Traits: AlwaysSpeculatableImplTrait
, SameVariadicOperandSize
, Terminator
Interfaces: BranchOpInterface
, ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
cond | CIR bool type |
destOperandsTrue | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
destOperandsFalse | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Successor | Description |
---|---|
destTrue | any successor |
destFalse | any successor |
cir.br
(cir::BrOp)Unconditional branch
Syntax:
operation ::= `cir.br` $dest (`(` $destOperands^ `:` type($destOperands) `)`)? attr-dict
The cir.br
branches unconditionally to a block. Used to represent C/C++ goto's and general block branching.
Example:
...
cir.br ^bb3
^bb3:
cir.return
Traits: AlwaysSpeculatableImplTrait
, Terminator
Interfaces: BranchOpInterface
, ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
destOperands | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Successor | Description |
---|---|
dest | any successor |
cir.break
(cir::BreakOp)C/C++ break
statement equivalent
Syntax:
operation ::= `cir.break` attr-dict
The cir.break
operation is used to cease the control flow to the parent operation, exiting its region's control flow. It is only allowed if it is within a breakable operation (loops and switch
).
Traits: Terminator
cir.asm
(cir::InlineAsmOp)Syntax:
operation ::= `cir.asm` `(`$asm_flavor`,` `{` $asm_string $constraints `}` `)` attr-dict
`:` type($res)
The cir.asm
operation represents C/C++ asm inline.
CIR constraints strings follow barelly the same rules that are established for the C level assembler constraints with several differences caused by clang::AsmStmt processing.
Thus, numbers that appears in the constraint string may also refer to:
Example:
__asm__("foo" : : : );
__asm__("bar $42 %[val]" : [val] "=r" (x), "+&r"(x));
__asm__("baz $42 %[val]" : [val] "=r" (x), "+&r"(x) : "[val]"(y));
cir.asm(x86_att, {"foo" ""})
cir.asm(x86_att, {"bar $$42 $0" "=r,=&r,1"})
cir.asm(x86_att, {"baz $$42 $0" "=r,=&r,0,1"})
Traits: RecursiveMemoryEffects
Attribute | MLIR Type | Description |
---|---|---|
asm_string | ::mlir::StringAttr | string attribute |
constraints | ::mlir::StringAttr | string attribute |
asm_flavor | ::mlir::cir::AsmFlavorAttr | ATT or Intel |
Result | Description |
---|---|
res | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.call
(cir::CallOp)Call operation
Direct and indirect calls.
For direct calls, the call
operation represents a direct call to a function that is within the same symbol scope as the call. The operands and result types of the call must match the specified function type. The callee is encoded as a aymbol reference attribute named "callee".
For indirect calls, the first mlir::Operation
operand is the call target.
Given the way indirect calls are encoded, avoid using mlir::Operation
methods to walk the operands for this operation, instead use the methods provided by CIRCallOpInterface
. ``
Example:
// Direct call
%2 = cir.call @my_add(%0, %1) : (f32, f32) -> f32
...
// Indirect call
%20 = cir.call %18(%17)
Interfaces: CIRCallOpInterface
, CallOpInterface
, SymbolUserOpInterface
Attribute | MLIR Type | Description |
---|---|---|
callee | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
ast | ::mlir::cir::ASTCallExprInterface | ASTCallExprInterface instance |
Operand | Description |
---|---|
operands | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
«unnamed» | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.cast
(cir::CastOp)Conversion between values of different types
Syntax:
operation ::= `cir.cast` `(` $kind `,` $src `:` type($src) `)`
`,` type($result) attr-dict
Apply C/C++ usual conversions rules between values. Currently supported kinds:
array_to_ptrdecay
bitcast
integral
int_to_bool
int_to_float
floating
float_to_int
float_to_bool
ptr_to_int
ptr_to_bool
bool_to_int
bool_to_float
This is effectively a subset of the rules from llvm-project/clang/include/clang/AST/OperationKinds.def
; but note that some of the conversions aren't implemented in terms of cir.cast
, lvalue-to-rvalue
for instance is modeled as a regular cir.load
.
%4 = cir.cast (int_to_bool, %3 : i32), !cir.bool
...
%x = cir.cast(array_to_ptrdecay, %0 : !cir.ptr<!cir.array<i32 x 10>>), !cir.ptr<i32>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::CastKindAttr | cast kind |
Operand | Description |
---|---|
src | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.catch
(cir::CatchOp)Catch operation
Syntax:
operation ::= `cir.catch` `(`
$exception_info `:` type($exception_info) `,`
custom<CatchOp>($regions, $catchers)
`)` attr-dict
Traits: NoRegionArguments
, RecursivelySpeculatableImplTrait
, SameVariadicOperandSize
Interfaces: ConditionallySpeculatable
, RegionBranchOpInterface
Attribute | MLIR Type | Description |
---|---|---|
catchers | ::mlir::ArrayAttr | array attribute |
Operand | Description |
---|---|
exception_info | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.catch_param
(cir::CatchParamOp)Materialize the catch clause formal parameter
Syntax:
operation ::= `cir.catch_param` `(` $exception_info `)` `->` qualified(type($param)) attr-dict
The cir.catch_param
binds to a the C/C++ catch clause param and allow it to be materialized. This operantion grabs the param by looking into a exception info !cir.eh_info
argument.
Example:
// TBD
Operand | Description |
---|---|
exception_info | !cir.eh_info* |
Result | Description |
---|---|
param | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.ceil
(cir::CeilOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.ceil` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.cmp
(cir::CmpOp)Compare values two values and produce a boolean result
Syntax:
operation ::= `cir.cmp` `(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,` type($result) attr-dict
cir.cmp
compares two input operands of the same type and produces a cir.bool
result. The kinds of comparison available are: [lt,gt,ge,eq,ne]
%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
Traits: AlwaysSpeculatableImplTrait
, SameTypeOperands
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::CmpOpKindAttr | compare operation kind |
Operand | Description |
---|---|
lhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
rhs | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.condition
(cir::ConditionOp)Loop continuation condition.
Syntax:
operation ::= `cir.condition` `(` $condition `)` attr-dict
The cir.condition
terminates conditional regions. It takes a single cir.bool
operand and, depending on its value, may branch to different regions:
cond
region of a cir.loop
, it continues the loop if true, or exits it if false.ready
region of a cir.await
, it branches to the resume
region when true, and to the suspend
region when false.Example:
cir.loop for(cond : {
cir.condition(%arg0) // Branches to `step` region or exits.
}, step : {
[...]
}) {
[...]
}
cir.await(user, ready : {
cir.condition(%arg0) // Branches to `resume` or `suspend` region.
}, suspend : {
[...]
}, resume : {
[...]
},)
Traits: Terminator
Interfaces: RegionBranchTerminatorOpInterface
Operand | Description |
---|---|
condition | CIR bool type |
cir.const
(cir::ConstantOp)Defines a CIR constant
Syntax:
operation ::= `cir.const` `(` custom<ConstantValue>($value) `)` attr-dict `:` type($res)
The cir.const
operation turns a literal into an SSA value. The data is attached to the operation as an attribute.
%0 = cir.const(42 : i32) : i32
%1 = cir.const(4.2 : f32) : f32
%2 = cir.const(nullptr : !cir.ptr<i32>) : !cir.ptr<i32>
Traits: AlwaysSpeculatableImplTrait
, ConstantLike
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
value | ::mlir::TypedAttr | TypedAttr instance |
Result | Description |
---|---|
res | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.continue
(cir::ContinueOp)C/C++ continue
statement equivalent
Syntax:
operation ::= `cir.continue` attr-dict
The cir.continue
operation is used to continue execution to the next iteration of a loop. It is only allowed within cir.loop
regions.
Traits: Terminator
cir.copy
(cir::CopyOp)Copies contents from a CIR pointer to another
Syntax:
operation ::= `cir.copy` $src `to` $dst attr-dict `:` qualified(type($dst))
Given two CIR pointers, src
and dst
, cir.copy
will copy the memory pointed by src
to the memory pointed by dst
.
The amount of bytes copied is inferred from the pointee type. Naturally, the pointee type of both src
and dst
must match and must implement the DataLayoutTypeInterface
.
Examples:
// Copying contents from one struct to another:
cir.copy %0 to %1 : !cir.ptr<!struct_ty>
Traits: SameTypeOperands
Operand | Description |
---|---|
dst | CIR pointer type |
src | CIR pointer type |
cir.cos
(cir::CosOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.cos` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.do
(cir::DoWhileOp)C/C++ do-while loop
Syntax:
operation ::= `cir.do` $body `while` $cond attr-dict
Represents a C/C++ do-while loop. Identical to cir.while
but the condition is evaluated after the body.
Example:
cir.do {
cir.break
^bb2:
cir.yield
} while {
cir.condition %cond : cir.bool
}
Traits: NoRegionArguments
Interfaces: LoopLikeOpInterface
, LoopOpInterface
, RegionBranchOpInterface
cir.exp2
(cir::Exp2Op)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.exp2` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.exp
(cir::ExpOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.exp` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.fabs
(cir::FAbsOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.fabs` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.floor
(cir::FloorOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.floor` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.for
(cir::ForOp)C/C++ for loop counterpart
Syntax:
operation ::= `cir.for` `:` `cond` $cond
`body` $body
`step` $step
attr-dict
Represents a C/C++ for loop. It consists of three regions:
cond
: single block region with the loop's condition. Should be terminated with a cir.condition
operation.body
: contains the loop body and an arbitrary number of blocks.step
: single block region with the loop's step.Example:
cir.for cond {
cir.condition(%val)
} body {
cir.break
^bb2:
cir.yield
} step {
cir.yield
}
Traits: NoRegionArguments
Interfaces: LoopLikeOpInterface
, LoopOpInterface
, RegionBranchOpInterface
cir.func
(cir::FuncOp)Declare or define a function
Similar to mlir::FuncOp
built-in:
Operations within the function cannot implicitly capture values defined outside of the function, i.e. Functions are
IsolatedFromAbove
. All external references must use function arguments or attributes that establish a symbolic connection (e.g. symbols referenced by name via a string attribute like SymbolRefAttr). An external function declaration (used when referring to a function declared in some other module) has no body. While the MLIR textual form provides a nice inline syntax for function arguments, they are internally represented as "block arguments" to the first block in the region.Only dialect attribute names may be specified in the attribute dictionaries for function arguments, results, or the function itself.
The function linkage information is specified by linkage
, as defined by GlobalLinkageKind
attribute.
A compiler builtin function must be marked as builtin
for further processing when lowering from CIR.
The coroutine
keyword is used to mark coroutine function, which requires at least one cir.await
instruction to be used in its body.
The lambda
translates to a C++ operator()
that implements a lambda, this allow callsites to make certain assumptions about the real function nature when writing analysis. The verifier should, but do act on this keyword yet.
The no_proto
keyword is used to identify functions that were declared without a prototype and, consequently, may contain calls with invalid arguments and undefined behavior.
The extra_attrs
, which is an aggregate of function-specific attributes is required and mandatory to describle additional attributes that are not listed above. Though mandatory, the prining of the attribute can be omitted if it is empty.
Example:
// External function definitions.
cir.func @abort()
// A function with internal linkage.
cir.func internal @count(%x: i64) -> (i64)
return %x : i64
}
// Linkage information
cir.func linkonce_odr @some_method(...)
// Builtin function
cir.func builtin @__builtin_coro_end(!cir.ptr<i8>, !cir.bool) -> !cir.bool
// Coroutine
cir.func coroutine @_Z10silly_taskv() -> !CoroTask {
...
cir.await(...)
...
}
Traits: AutomaticAllocationScope
, IsolatedFromAbove
Interfaces: CallableOpInterface
, FunctionOpInterface
, Symbol
Attribute | MLIR Type | Description |
---|---|---|
sym_name | ::mlir::StringAttr | string attribute |
function_type | ::mlir::TypeAttr | type attribute of CIR function type |
builtin | ::mlir::UnitAttr | unit attribute |
coroutine | ::mlir::UnitAttr | unit attribute |
lambda | ::mlir::UnitAttr | unit attribute |
no_proto | ::mlir::UnitAttr | unit attribute |
linkage | ::mlir::cir::GlobalLinkageKindAttr | Linkage type/kind |
extra_attrs | ::mlir::cir::ExtraFuncAttributesAttr | Represents aggregated attributes for a function |
sym_visibility | ::mlir::StringAttr | string attribute |
arg_attrs | ::mlir::ArrayAttr | Array of dictionary attributes |
res_attrs | ::mlir::ArrayAttr | Array of dictionary attributes |
aliasee | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
ast | ::mlir::Attribute | AST Function attribute |
cir.get_bitfield
(cir::GetBitfieldOp)Get a bitfield
Syntax:
operation ::= `cir.get_bitfield` `(`$bitfield_info `,` $addr attr-dict `:`
qualified(type($addr)) `)` `->` type($result)
The cir.get_bitfield
operation provides a load-like access to a bit field of a record.
It expects a name if a bit field, a pointer to a storage in the base record, a type of the storage, a name of the bitfield, a size the bit field, an offset of the bit field and a sign.
A unit attribute volatile
can be used to indicate a volatile load of the bitfield.
Example: Suppose we have a struct with multiple bitfields stored in different storages. The cir.get_bitfield
operation gets the value of the bitfield
typedef struct {
int a : 4;
int b : 27;
int c : 17;
int d : 2;
int e : 15;
} S;
int load_bitfield(S& s) {
return s.d;
}
// 'd' is in the storage with the index 1
!struct_type = !cir.struct<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>
#bfi_d = #cir.bitfield_info<name = "d", storage_type = !u32i, size = 2, offset = 17, is_signed = true>
%2 = cir.load %0 : cir.ptr <!cir.ptr<!struct_type>>, !cir.ptr<!struct_type>
%3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!struct_type> -> !cir.ptr<!u32i>
%4 = cir.get_bitfield(#bfi_d, %3 : !cir.ptr<!u32i>) -> !s32i
Attribute | MLIR Type | Description |
---|---|---|
bitfield_info | ::mlir::cir::BitfieldInfoAttr | Represents a bit field info |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operand | Description |
---|---|
addr | CIR pointer type |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.get_global
(cir::GetGlobalOp)Get the address of a global variable
Syntax:
operation ::= `cir.get_global` $name `:` `cir.ptr` type($addr) attr-dict
The cir.get_global
operation retrieves the address pointing to a named global variable. If the global variable is marked constant, writing to the resulting address (such as through a cir.store
operation) is undefined. Resulting type must always be a !cir.ptr<...>
type.
Example:
%x = cir.get_global @foo : !cir.ptr<i32>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
, SymbolUserOpInterface
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
name | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Result | Description |
---|---|
addr | CIR pointer type |
cir.get_member
(cir::GetMemberOp)Get the address of a member of a struct
Syntax:
operation ::= `cir.get_member` $addr `[` $index_attr `]` attr-dict
`:` qualified(type($addr)) `->` qualified(type($result))
The cir.get_member
operation gets the address of a particular named member from the input record.
It expects a pointer to the base record as well as the name of the member and its field index.
Example:
// Suppose we have a struct with multiple members.
!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 32>
!struct_ty = !cir.struct<"struct.Bar" {!s32i, !s8i}>
// Get the address of the member at index 1.
%1 = cir.get_member %0[1] {name = "i"} : (!cir.ptr<!struct_ty>) -> !cir.ptr<!s8i>
Attribute | MLIR Type | Description |
---|---|---|
name | ::mlir::StringAttr | string attribute |
index_attr | ::mlir::IntegerAttr | index attribute |
Operand | Description |
---|---|
addr | CIR pointer type |
Result | Description |
---|---|
result | CIR pointer type |
cir.global
(cir::GlobalOp)Declares or defines a global variable
Syntax:
operation ::= `cir.global` ($sym_visibility^)?
(`constant` $constant^)?
$linkage
$sym_name
custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value, $ctorRegion, $dtorRegion)
attr-dict
The cir.global
operation declares or defines a named global variable.
The backing memory for the variable is allocated statically and is described by the type of the variable.
The operation is a declaration if no inital_value
is specified, else it is a definition.
The global variable can also be marked constant using the constant
unit attribute. Writing to such constant global variables is undefined.
The linkage
tracks C/C++ linkage types, currently very similar to LLVM's. Symbol visibility in sym_visibility
is defined in terms of MLIR's visibility and verified to be in accordance to linkage
.
Example:
// Public and constant variable with initial value.
cir.global public constant @c : i32 = 4;
Traits: NoRegionArguments
Interfaces: RegionBranchOpInterface
, Symbol
Attribute | MLIR Type | Description |
---|---|---|
sym_name | ::mlir::StringAttr | string attribute |
sym_visibility | ::mlir::StringAttr | string attribute |
sym_type | ::mlir::TypeAttr | any type attribute |
linkage | ::mlir::cir::GlobalLinkageKindAttr | Linkage type/kind |
initial_value | ::mlir::Attribute | any attribute |
constant | ::mlir::UnitAttr | unit attribute |
alignment | ::mlir::IntegerAttr | 64-bit signless integer attribute |
ast | ::mlir::cir::ASTVarDeclInterface | ASTVarDeclInterface instance |
section | ::mlir::StringAttr | string attribute |
cir.if
(cir::IfOp)The if-then-else operation
The cir.if
operation represents an if-then-else construct for conditionally executing two regions of code. The operand is a cir.bool
type.
Examples:
cir.if %b {
...
} else {
...
}
cir.if %c {
...
}
cir.if %c {
...
cir.br ^a
^a:
cir.yield
}
cir.if
defines no values and the ‘else' can be omitted. cir.yield
must explicitly terminate the region if it has more than one block.
Traits: AutomaticAllocationScope
, NoRegionArguments
, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, RegionBranchOpInterface
Operand | Description |
---|---|
condition | CIR bool type |
cir.iterator_begin
(cir::IterBeginOp)Returns an iterator to the first element of a container
Syntax:
operation ::= `cir.iterator_begin` `(`
$original_fn `,` $container `:` type($container)
`)` `->` type($result) attr-dict
Attribute | MLIR Type | Description |
---|---|---|
original_fn | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operand | Description |
---|---|
container | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.iterator_end
(cir::IterEndOp)Returns an iterator to the element following the last element of a container
Syntax:
operation ::= `cir.iterator_end` `(`
$original_fn `,` $container `:` type($container)
`)` `->` type($result) attr-dict
Attribute | MLIR Type | Description |
---|---|---|
original_fn | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operand | Description |
---|---|
container | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.load
(cir::LoadOp)Load value from memory adddress
Syntax:
operation ::= `cir.load` (`deref` $isDeref^)? (`volatile` $is_volatile^)?
$addr `:` `cir.ptr` type($addr) `,` type($result) attr-dict
cir.load
reads a value (lvalue to rvalue conversion) given an address backed up by a cir.ptr
type. A unit attribute deref
can be used to mark the resulting value as used by another operation to dereference a pointer. A unit attribute volatile
can be used to indicate a volatile loading.
Example:
// Read from local variable, address in %0.
%1 = cir.load %0 : !cir.ptr<i32>, i32
// Load address from memory at address %0. %3 is used by at least one
// operation that dereferences a pointer.
%3 = cir.load deref %0 : cir.ptr <!cir.ptr<i32>>
// Perform a volatile load from address in %0.
%4 = cir.load volatile %0 : !cir.ptr<i32>, i32
Interfaces: InferTypeOpInterface
Attribute | MLIR Type | Description |
---|---|---|
isDeref | ::mlir::UnitAttr | unit attribute |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operand | Description |
---|---|
addr | CIR pointer type |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.log10
(cir::Log10Op)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.log10` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.log2
(cir::Log2Op)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.log2` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.log
(cir::LogOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.log` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.libc.memchr
(cir::MemChrOp)Libc's memchr
Syntax:
operation ::= `cir.libc.memchr` `(`
$src `,` $pattern `,` $len `)` attr-dict
Search for pattern
in data range from src
to src
+ len
. provides a bound to the search in src
. result
is a pointer to found pattern
or a null pointer.
Examples:
%p = cir.libc.memchr(%src, %pattern, %len) -> !cir.ptr<!void>
Interfaces: InferTypeOpInterface
Operand | Description |
---|---|
src | void* |
pattern | 32-bit signed integer |
len | 64-bit unsigned integer |
Result | Description |
---|---|
result | void* |
cir.libc.memcpy
(cir::MemCpyOp)Equivalent to libc's memcpy
Syntax:
operation ::= `cir.libc.memcpy` $len `bytes` `from` $src `to` $dst attr-dict
`:` type($len) `` `,` qualified(type($src)) `->` qualified(type($dst))
Given two CIR pointers, src
and dst
, cir.libc.memcpy
will copy len
bytes from the memory pointed by src
to the memory pointed by dst
.
While cir.copy
is meant to be used for implicit copies in the code where the length of the copy is known, cir.memcpy
copies only from and to void pointers, requiring the copy length to be passed as an argument.
Examples:
// Copying 2 bytes from one array to a struct:
%2 = cir.const(#cir.int<2> : !u32i) : !u32i
cir.libc.memcpy %2 bytes from %arr to %struct : !cir.ptr<!arr> -> !cir.ptr<!struct>
Operand | Description |
---|---|
dst | CIR pointer type |
src | CIR pointer type |
len | Integer type with arbitrary precision up to a fixed limit |
cir.nearbyint
(cir::NearbyintOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.nearbyint` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.objsize
(cir::ObjSizeOp)Conversion between values of different types
Syntax:
operation ::= `cir.objsize` `(`
$ptr `:` type($ptr) `,`
$kind
(`,` `dynamic` $dynamic^)?
`)`
`->` type($result) attr-dict
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::SizeInfoTypeAttr | size info type |
dynamic | ::mlir::UnitAttr | unit attribute |
Operand | Description |
---|---|
ptr | CIR pointer type |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.ptr_diff
(cir::PtrDiffOp)Pointer subtraction arithmetic
Syntax:
operation ::= `cir.ptr_diff` `(` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `->` qualified(type($result)) attr-dict
cir.ptr_diff
performs a subtraction between two pointer types with the same element type and produces a mlir::cir::IntType
result.
Note that the result considers the pointer size according to the ABI for the pointee sizes, e.g. the subtraction between two !cir.ptr<!u64i>
might yield 1, meaning 8 bytes, whereas for void
or function type pointees, yielding 8 means 8 bytes.
%7 = "cir.ptr_diff"(%0, %1) : !cir.ptr<!u64i> -> !u64i
Traits: AlwaysSpeculatableImplTrait
, SameTypeOperands
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
lhs | CIR pointer type |
rhs | CIR pointer type |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.ptr_stride
(cir::PtrStrideOp)Pointer access with stride
Syntax:
operation ::= `cir.ptr_stride` `(` $base `:` qualified(type($base)) `,` $stride `:` qualified(type($stride)) `)`
`,` qualified(type($result)) attr-dict
Given a base pointer as first operand, provides a new pointer after applying a stride (second operand).
%3 = cir.const(0 : i32) : i32
%4 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32), !cir.ptr<i32>
Traits: AlwaysSpeculatableImplTrait
, SameFirstOperandAndResultType
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
base | CIR pointer type |
stride | Integer type with arbitrary precision up to a fixed limit |
Result | Description |
---|---|
result | CIR pointer type |
cir.resume
(cir::ResumeOp)Resumes execution after not catching exceptions
Syntax:
operation ::= `cir.resume` attr-dict
The cir.resume
operation terminates a region on cir.catch
, "resuming" or continuing the unwind process.
Examples:
cir.catch ... {
...
fallback { cir.resume };
}
Traits: HasParent<CatchOp>
, ReturnLike
, Terminator
Interfaces: RegionBranchTerminatorOpInterface
cir.return
(cir::ReturnOp)Return from function
Syntax:
operation ::= `cir.return` ($input^ `:` type($input))? attr-dict
The "return" operation represents a return operation within a function. The operation takes an optional operand and produces no results. The operand type must match the signature of the function that contains the operation.
func @foo() -> i32 {
...
cir.return %0 : i32
}
Traits: HasParent<FuncOp, ScopeOp, IfOp, SwitchOp, DoWhileOp, WhileOp, ForOp>
, Terminator
Operand | Description |
---|---|
input | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.rint
(cir::RintOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.rint` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.round
(cir::RoundOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.round` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.scope
(cir::ScopeOp)Represents a C/C++ scope
Syntax:
operation ::= `cir.scope` custom<OmittedTerminatorRegion>($scopeRegion) (`:` type($results)^)? attr-dict
cir.scope
contains one region and defines a strict "scope" for all new values produced within its blocks.
The region can contain an arbitrary number of blocks but usually defaults to one and can optionally return a value (useful for representing values coming out of C++ full-expressions) via cir.yield
:
%rvalue = cir.scope {
...
cir.yield %value
}
If cir.scope
yields no value, the cir.yield
can be left out, and will be inserted implicitly.
Traits: AutomaticAllocationScope
, NoRegionArguments
, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, RegionBranchOpInterface
Result | Description |
---|---|
results | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.set_bitfield
(cir::SetBitfieldOp)Set a bitfield
Syntax:
operation ::= `cir.set_bitfield` `(`$bitfield_info`,` $dst`:`qualified(type($dst))`,`
$src`:`type($src) `)` attr-dict `->` type($result)
The cir.set_bitfield
operation provides a store-like access to a bit field of a record.
It expects an address of a storage where to store, a type of the storage, a value being stored, a name of a bit field, a pointer to the storage in the base record, a size of the storage, a size the bit field, an offset of the bit field and a sign. Returns a value being stored.
A unit attribute volatile
can be used to indicate a volatile load of the bitfield.
Example. Suppose we have a struct with multiple bitfields stored in different storages. The cir.set_bitfield
operation sets the value of the bitfield.
typedef struct {
int a : 4;
int b : 27;
int c : 17;
int d : 2;
int e : 15;
} S;
void store_bitfield(S& s) {
s.d = 3;
}
// 'd' is in the storage with the index 1
!struct_type = !cir.struct<struct "S" {!cir.int<u, 32>, !cir.int<u, 32>, !cir.int<u, 16>} #cir.record.decl.ast>
#bfi_d = #cir.bitfield_info<name = "d", storage_type = !u32i, size = 2, offset = 17, is_signed = true>
%1 = cir.const(#cir.int<3> : !s32i) : !s32i
%2 = cir.load %0 : cir.ptr <!cir.ptr<!struct_type>>, !cir.ptr<!struct_type>
%3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!struct_type> -> !cir.ptr<!u32i>
%4 = cir.set_bitfield(#bfi_d, %3 : !cir.ptr<!u32i>, %1 : !s32i) -> !s32i
Attribute | MLIR Type | Description |
---|---|---|
bitfield_info | ::mlir::cir::BitfieldInfoAttr | Represents a bit field info |
is_volatile | ::mlir::UnitAttr | unit attribute |
Operand | Description |
---|---|
dst | CIR pointer type |
src | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.shift
(cir::ShiftOp)Shift
Syntax:
operation ::= `cir.shift` `(`
(`left` $isShiftleft^) : (`right`)?
`,` $value `:` type($value)
`,` $amount `:` type($amount)
`)` `->` type($result) attr-dict
Shift left
or right
, according to the first operand. Second operand is the shift target and the third the amount.
%7 = cir.shift(left, %1 : !u64i, %4 : !s32i) -> !u64i
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
isShiftleft | ::mlir::UnitAttr | unit attribute |
Operand | Description |
---|---|
value | Integer type with arbitrary precision up to a fixed limit |
amount | Integer type with arbitrary precision up to a fixed limit |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit |
cir.sin
(cir::SinOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.sin` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.sqrt
(cir::SqrtOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.sqrt` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.stack_restore
(cir::StackRestoreOp)Restores the state of the function stack
Syntax:
operation ::= `cir.stack_restore` $ptr attr-dict `:` qualified(type($ptr))
Restore the state of the function stack to the state it was in when the corresponding cir.stack_save executed. Useful for implementing language features like variable length arrays.
%0 = cir.alloca !cir.ptr<!u8i>, cir.ptr <!cir.ptr<!u8i>>, ["saved_stack"] {alignment = 8 : i64}
%1 = cir.stack_save : <!u8i>
cir.store %1, %0 : !cir.ptr<!u8i>, cir.ptr <!cir.ptr<!u8i>>
%2 = cir.load %0 : cir.ptr <!cir.ptr<!u8i>>, !cir.ptr<!u8i>
cir.stack_restore %2 : !cir.ptr<!u8i>
Operand | Description |
---|---|
ptr | CIR pointer type |
cir.stack_save
(cir::StackSaveOp)Remembers the current state of the function stack
Syntax:
operation ::= `cir.stack_save` attr-dict `:` qualified(type($result))
Remembers the current state of the function stack. Returns a pointer that later can be passed into cir.stack_restore. Useful for implementing language features like variable length arrays.
%0 = cir.stack_save : <!u8i>
Result | Description |
---|---|
result | CIR pointer type |
cir.std.find
(cir::StdFindOp)Std:find()
Syntax:
operation ::= `cir.std.find` `(`
$original_fn
`,` $first `:` type($first)
`,` $last `:` type($last)
`,` $pattern `:` type($pattern)
`)` `->` type($result) attr-dict
Search for pattern
in data range from first
to last
. This currently maps to only one form of std::find
. The original_fn
operand tracks the mangled named that can be used when lowering to a cir.call
.
Example:
...
%result = cir.std.find(@original_fn,
%first : !T, %last : !T, %pattern : !P) -> !T
Traits: SameFirstSecondOperandAndResultType
Attribute | MLIR Type | Description |
---|---|---|
original_fn | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operand | Description |
---|---|
first | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
last | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
pattern | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.store
(cir::StoreOp)Store value to memory address
Syntax:
operation ::= `cir.store` (`volatile` $is_volatile^)?
$value `,` $addr attr-dict `:` type($value) `,` `cir.ptr` type($addr)
cir.store
stores a value (first operand) to the memory address specified in the second operand. A unit attribute volatile
can be used to indicate a volatile store.
Example:
// Store a function argument to local storage, address in %0.
cir.store %arg0, %0 : i32, !cir.ptr<i32>
// Perform a volatile store into memory location at the address in %0.
cir.store volatile %arg0, %0 : i32, !cir.ptr<i32>
Attribute | MLIR Type | Description |
---|---|---|
is_volatile | ::mlir::UnitAttr | unit attribute |
Operand | Description |
---|---|
value | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
addr | CIR pointer type |
cir.switch
(cir::SwitchOp)Switch operation
Syntax:
operation ::= `cir.switch` custom<SwitchOp>(
$regions, $cases, $condition, type($condition)
)
attr-dict
The cir.switch
operation represents C/C++ switch functionality for conditionally executing multiple regions of code. The operand to an switch is an integral condition value.
A variadic list of "case" attribute operands and regions track the possible control flow within cir.switch
. A case
must be in one of the following forms:
equal, <constant>
: equality of the second case operand against the condition.anyof, [constant-list]
: equals to any of the values in a subsequent following list.default
: any other value.Each case region must be explicitly terminated.
Examples:
cir.switch (%b : i32) [
case (equal, 20) {
...
cir.yield break
},
case (anyof, [1, 2, 3] : i32) {
...
cir.return ...
}
case (default) {
...
cir.yield fallthrough
}
]
Traits: AutomaticAllocationScope
, NoRegionArguments
, RecursivelySpeculatableImplTrait
, SameVariadicOperandSize
Interfaces: ConditionallySpeculatable
, RegionBranchOpInterface
Attribute | MLIR Type | Description |
---|---|---|
cases | ::mlir::ArrayAttr | cir.switch case array attribute |
Operand | Description |
---|---|
condition | Integer type with arbitrary precision up to a fixed limit |
cir.ternary
(cir::TernaryOp)The cond ? a : b
C/C++ ternary operation
Syntax:
operation ::= `cir.ternary` `(` $cond `,`
`true` $trueRegion `,`
`false` $falseRegion
`)` `:` functional-type(operands, results) attr-dict
The cir.ternary
operation represents C/C++ ternary, much like a select
operation. First argument is a cir.bool
condition to evaluate, followed by two regions to execute (true or false). This is different from cir.if
since each region is one block sized and the cir.yield
closing the block scope should have one argument.
Example:
// x = cond ? a : b;
%x = cir.ternary (%cond, true_region {
...
cir.yield %a : i32
}, false_region {
...
cir.yield %b : i32
}) -> i32
Traits: AutomaticAllocationScope
, NoRegionArguments
, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, RegionBranchOpInterface
Operand | Description |
---|---|
cond | CIR bool type |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.throw
(cir::ThrowOp)(Re)Throws an exception
Syntax:
operation ::= `cir.throw` `(`
($exception_ptr^ `:` type($exception_ptr))?
(`,` $type_info^)?
(`,` $dtor^)?
`)` attr-dict
Very similar to __cxa_throw:
void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
void (*dest) (void *));
The absense of arguments for cir.throw
means it rethrows.
For the no-rethrow version, it must have at least two operands, the RTTI information, a pointer to the exception object (likely allocated via cir.cxa.allocate_exception
) and finally an optional dtor, which might run as part of this operation.
// if (b == 0)
// throw "Division by zero condition!";
cir.if %10 {
%11 = cir.alloc_exception(!cir.ptr<!u8i>) -> <!cir.ptr<!u8i>>
...
cir.store %13, %11 : // Store string addr for "Division by zero condition!"
cir.throw(%11 : !cir.ptr<!cir.ptr<!u8i>>, @"typeinfo for char const*")
Traits: HasParent<FuncOp, ScopeOp, IfOp, SwitchOp, DoWhileOp, WhileOp, ForOp>
, Terminator
Attribute | MLIR Type | Description |
---|---|---|
type_info | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
dtor | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
Operand | Description |
---|---|
exception_ptr | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.trunc
(cir::TruncOp)Libc builtin equivalent ignoring floating point exceptions and errno
Syntax:
operation ::= `cir.trunc` $src `:` type($src) attr-dict
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
src | floating-point |
Result | Description |
---|---|
result | floating-point |
cir.try_call
(cir::TryCallOp)Try call operation
Similar to cir.call
, direct and indirect properties are the same. The difference relies in an exception object address operand. It's encoded as the first operands or second (for indirect calls).
Similarly to cir.call
, avoid using mlir::Operation
methods to walk the operands for this operation, instead use the methods provided by CIRCallOpInterface
.
Example:
cir.try {
%0 = cir.alloca !cir.ptr<!cir.eh.info>, cir.ptr <!cir.ptr<!cir.eh.info>>
...
%r = cir.try_call %exception(%0) @division(%1, %2)
} ...
Interfaces: CIRCallOpInterface
, CallOpInterface
, SymbolUserOpInterface
Attribute | MLIR Type | Description |
---|---|---|
callee | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
ast | ::mlir::cir::ASTCallExprInterface | ASTCallExprInterface instance |
Operand | Description |
---|---|
exceptionInfo | !cir.eh_info** |
callOps | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
«unnamed» | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.try
(cir::TryOp)Syntax:
operation ::= `cir.try` $body `:` functional-type(operands, results) attr-dict
TBD
Note that variables declared inside a try {}
in C++ will have their allocas places in the surrounding (parent) scope.
Traits: AutomaticAllocationScope
, NoRegionArguments
, RecursivelySpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, RegionBranchOpInterface
Result | Description |
---|---|
result | !cir.eh_info* |
cir.unary
(cir::UnaryOp)Unary operations
Syntax:
operation ::= `cir.unary` `(` $kind `,` $input `)` `:` type($input) `,` type($result) attr-dict
cir.unary
performs the unary operation according to the specified opcode kind: [inc, dec, plus, minus, not].
Note for inc and dec: the operation corresponds only to the addition/subtraction, its input is expect to come from a load and the result to be used by a corresponding store.
It requires one input operand and has one result, both types should be the same.
%7 = cir.unary(inc, %1) : i32 -> i32
%8 = cir.unary(dec, %2) : i32 -> i32
Traits: AlwaysSpeculatableImplTrait
, SameOperandsAndResultType
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::UnaryOpKindAttr | unary operation kind |
Operand | Description |
---|---|
input | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.va.arg
(cir::VAArgOp)Fetches next variadic element as a given type
Syntax:
operation ::= `cir.va.arg` $arg_list attr-dict `:` functional-type(operands, $result)
Operand | Description |
---|---|
arg_list | CIR pointer type |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.va.copy
(cir::VACopyOp)Copies a variable argument list
Syntax:
operation ::= `cir.va.copy` $src_list `to` $dst_list attr-dict `:` type(operands)
Operand | Description |
---|---|
dst_list | CIR pointer type |
src_list | CIR pointer type |
cir.va.end
(cir::VAEndOp)Ends a variable argument list
Syntax:
operation ::= `cir.va.end` $arg_list attr-dict `:` type(operands)
Operand | Description |
---|---|
arg_list | CIR pointer type |
cir.va.start
(cir::VAStartOp)Starts a variable argument list
Syntax:
operation ::= `cir.va.start` $arg_list attr-dict `:` type(operands)
Operand | Description |
---|---|
arg_list | CIR pointer type |
cir.vtable.address_point
(cir::VTableAddrPointOp)Get the vtable (global variable) address point
Syntax:
operation ::= `cir.vtable.address_point` `(`
($name^)?
($sym_addr^ `:` type($sym_addr))?
`,`
`vtable_index` `=` $vtable_index `,`
`address_point_index` `=` $address_point_index
`)`
`:` `cir.ptr` type($addr) attr-dict
The vtable.address_point
operation retrieves the "effective" address (address point) of a C++ virtual table. An object internal __vptr
gets initializated on top of the value returned by this operation.
vtable_index
provides the appropriate vtable within the vtable group (as specified by Itanium ABI), and addr_point_index
the actual address point within that vtable.
The return type is always a !cir.ptr<!cir.ptr<() -> i32>>
.
Example:
cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B, vtable_index = 0, address_point_index = 2) : cir.ptr <!cir.ptr<() -> i32>>
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
, SymbolUserOpInterface
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
name | ::mlir::FlatSymbolRefAttr | flat symbol reference attribute |
vtable_index | ::mlir::IntegerAttr | 32-bit signless integer attribute |
address_point_index | ::mlir::IntegerAttr | 32-bit signless integer attribute |
Operand | Description |
---|---|
sym_addr | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
addr | CIR pointer type |
cir.vec.cmp
(cir::VecCmpOp)Compare two vectors
Syntax:
operation ::= `cir.vec.cmp` `(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,` type($result) attr-dict
The cir.vec.cmp
operation does an element-wise comparison of two vectors of the same type. The result is a vector of the same size as the operands whose element type is the signed integral type that is the same size as the element type of the operands. The values in the result are 0 or -1.
Traits: AlwaysSpeculatableImplTrait
, SameTypeOperands
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Attribute | MLIR Type | Description |
---|---|---|
kind | ::mlir::cir::CmpOpKindAttr | compare operation kind |
Operand | Description |
---|---|
lhs | CIR vector type |
rhs | CIR vector type |
Result | Description |
---|---|
result | CIR vector type |
cir.vec.create
(cir::VecCreateOp)Create a vector value
Syntax:
operation ::= `cir.vec.create` `(` ($elements^ `:` type($elements))? `)` `:` type($result) attr-dict
The cir.vec.create
operation creates a vector value with the given element values. The number of element arguments must match the number of elements in the vector type.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
elements | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
Result | Description |
---|---|
result | CIR vector type |
cir.vec.extract
(cir::VecExtractOp)Extract one element from a vector object
Syntax:
operation ::= `cir.vec.extract` $vec `[` $index `:` type($index) `]` attr-dict `:` type($vec)
The cir.vec.extract
operation extracts the element at the given index from a vector object.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
vec | CIR vector type |
index | Integer type with arbitrary precision up to a fixed limit |
Result | Description |
---|---|
result | Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.vec.insert
(cir::VecInsertOp)Insert one element into a vector object
Syntax:
operation ::= `cir.vec.insert` $value `,` $vec `[` $index `:` type($index) `]` attr-dict `:` type($vec)
The cir.vec.insert
operation replaces the element of the given vector at the given index with the given value. The new vector with the inserted element is returned.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, InferTypeOpInterface
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Operand | Description |
---|---|
vec | CIR vector type |
value | any type |
index | Integer type with arbitrary precision up to a fixed limit |
Result | Description |
---|---|
result | CIR vector type |
cir.while
(cir::WhileOp)C/C++ while loop
Syntax:
operation ::= `cir.while` $cond `do` $body attr-dict
Represents a C/C++ while loop. It consists of two regions:
cond
: single block region with the loop's condition. Should be terminated with a cir.condition
operation.body
: contains the loop body and an arbitrary number of blocks.Example:
cir.while {
cir.break
^bb2:
cir.yield
} do {
cir.condition %cond : cir.bool
}
Traits: NoRegionArguments
Interfaces: LoopLikeOpInterface
, LoopOpInterface
, RegionBranchOpInterface
cir.yield
(cir::YieldOp)Represents the default branching behaviour of a region
Syntax:
operation ::= `cir.yield` ($args^ `:` type($args))? attr-dict
The cir.yield
operation terminates regions on different CIR operations, and it is used to represent the default branching behaviour of a region. Said branching behaviour is determinted by the parent operation. For example, a yield in a switch-case
region implies a fallthrough, while a yield in a cir.if
region implies a branch to the exit block, and so on.
In some cases, it might yield an SSA value and the semantics of how the values are yielded is defined by the parent operation. For example, a cir.ternary
operation yields a value from one of its regions.
As a general rule, cir.yield
must be explicitly used whenever a region has more than one block and no terminator, or within cir.switch
regions not cir.return
terminated.
Examples:
cir.if %4 {
...
cir.yield
}
cir.switch (%5) [
case (equal, 3) {
...
cir.yield
}, ...
]
cir.scope {
...
cir.yield
}
%x = cir.scope {
...
cir.yield %val
}
%y = cir.ternary {
...
cir.yield %val : i32
} : i32
Traits: HasParent<IfOp, ScopeOp, SwitchOp, WhileOp, ForOp, AwaitOp, TernaryOp, GlobalOp, DoWhileOp, CatchOp, TryOp>
, ReturnLike
, Terminator
Interfaces: RegionBranchTerminatorOpInterface
Operand | Description |
---|---|
args | variadic of Integer type with arbitrary precision up to a fixed limit or CIR pointer type or CIR bool type or CIR array type or CIR vector type or CIR function type or CIR void type or CIR struct type or CIR exception info or floating-point |
cir.llvmir.zeroinit
(cir::ZeroInitConstOp)Zero initializes a constant value of a given type
Syntax:
operation ::= `cir.llvmir.zeroinit` attr-dict `:` type($result)
This operation circumvents the lack of a zeroinitializer operation in LLVM Dialect. It can zeroinitialize any LLVM type.
Traits: AlwaysSpeculatableImplTrait
Interfaces: ConditionallySpeculatable
, NoMemoryEffect (MemoryEffectOpInterface)
Effects: MemoryEffects::Effect{}
Result | Description |
---|---|
result | any type |