Operations


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>>, ...

Attributes:

AttributeMLIR TypeDescription
allocType::mlir::TypeAttrany type attribute

Results:

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}
...

Attributes:

AttributeMLIR TypeDescription
allocaType::mlir::TypeAttrany type attribute
name::mlir::StringAttrstring attribute
init::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 0
ast::mlir::cir::ASTVarDeclInterfaceASTVarDeclInterface instance

Operands:

Operand Description
dynAllocSize Integer type with arbitrary precision up to a fixed limit

Results:

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:

  • ready: covers veto power from x.await_ready()
  • suspend: wraps actual x.await_suspend() logic
  • resume: handles x.await_resume()

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

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::AwaitKindAttrawait 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

Operands:

Operand Description
derived_addr CIR pointer type

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::BinOpKindAttrbinary operation (arith and logic) kind

Operands:

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

Results:

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{}

Operands:

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

Successors:

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{}

Operands:

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

Successors:

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:

  • the output variable index referenced by the input operands.
  • the index of early-clobber operand

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

Attributes:

AttributeMLIR TypeDescription
asm_string::mlir::StringAttrstring attribute
constraints::mlir::StringAttrstring attribute
asm_flavor::mlir::cir::AsmFlavorAttrATT or Intel

Results:

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

Attributes:

AttributeMLIR TypeDescription
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute
ast::mlir::cir::ASTCallExprInterfaceASTCallExprInterface instance

Operands:

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

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::CastKindAttrcast kind

Operands:

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

Results:

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

Attributes:

AttributeMLIR TypeDescription
catchers::mlir::ArrayAttrarray attribute

Operands:

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

Operands:

Operand Description
exception_info !cir.eh_info*

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::CmpOpKindAttrcompare operation kind

Operands:

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

Results:

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:

  • When in the cond region of a cir.loop, it continues the loop if true, or exits it if false.
  • When in the 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

Operands:

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{}

Attributes:

AttributeMLIR TypeDescription
value::mlir::TypedAttrTypedAttr instance

Results:

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

Operands:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
function_type::mlir::TypeAttrtype attribute of CIR function type
builtin::mlir::UnitAttrunit attribute
coroutine::mlir::UnitAttrunit attribute
lambda::mlir::UnitAttrunit attribute
no_proto::mlir::UnitAttrunit attribute
linkage::mlir::cir::GlobalLinkageKindAttrLinkage type/kind
extra_attrs::mlir::cir::ExtraFuncAttributesAttrRepresents aggregated attributes for a function
sym_visibility::mlir::StringAttrstring attribute
arg_attrs::mlir::ArrayAttrArray of dictionary attributes
res_attrs::mlir::ArrayAttrArray of dictionary attributes
aliasee::mlir::FlatSymbolRefAttrflat symbol reference attribute
ast::mlir::AttributeAST 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

Attributes:

AttributeMLIR TypeDescription
bitfield_info::mlir::cir::BitfieldInfoAttrRepresents a bit field info
is_volatile::mlir::UnitAttrunit attribute

Operands:

Operand Description
addr CIR pointer type

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute

Results:

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>

Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
index_attr::mlir::IntegerAttrindex attribute

Operands:

Operand Description
addr CIR pointer type

Results:

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

Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
sym_visibility::mlir::StringAttrstring attribute
sym_type::mlir::TypeAttrany type attribute
linkage::mlir::cir::GlobalLinkageKindAttrLinkage type/kind
initial_value::mlir::Attributeany attribute
constant::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute
ast::mlir::cir::ASTVarDeclInterfaceASTVarDeclInterface instance
section::mlir::StringAttrstring 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

Operands:

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

Attributes:

AttributeMLIR TypeDescription
original_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:

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

Results:

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

Attributes:

AttributeMLIR TypeDescription
original_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:

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

Results:

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

Attributes:

AttributeMLIR TypeDescription
isDeref::mlir::UnitAttrunit attribute
is_volatile::mlir::UnitAttrunit attribute

Operands:

Operand Description
addr CIR pointer type

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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

Operands:

Operand Description
src void*
pattern 32-bit signed integer
len 64-bit unsigned integer

Results:

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>

Operands:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::SizeInfoTypeAttrsize info type
dynamic::mlir::UnitAttrunit attribute

Operands:

Operand Description
ptr CIR pointer type

Results:

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{}

Operands:

Operand Description
lhs CIR pointer type
rhs CIR pointer type

Results:

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{}

Operands:

Operand Description
base CIR pointer type
stride Integer type with arbitrary precision up to a fixed limit

Results:

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

Operands:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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

Results:

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

Attributes:

AttributeMLIR TypeDescription
bitfield_info::mlir::cir::BitfieldInfoAttrRepresents a bit field info
is_volatile::mlir::UnitAttrunit attribute

Operands:

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

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
isShiftleft::mlir::UnitAttrunit attribute

Operands:

Operand Description
value Integer type with arbitrary precision up to a fixed limit
amount Integer type with arbitrary precision up to a fixed limit

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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{}

Operands:

Operand Description
src floating-point

Results:

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>

Operands:

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>

Results:

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

Attributes:

AttributeMLIR TypeDescription
original_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:

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

Results:

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>

Attributes:

AttributeMLIR TypeDescription
is_volatile::mlir::UnitAttrunit attribute

Operands:

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

Attributes:

AttributeMLIR TypeDescription
cases::mlir::ArrayAttrcir.switch case array attribute

Operands:

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

Operands:

Operand Description
cond CIR bool type

Results:

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

Attributes:

AttributeMLIR TypeDescription
type_info::mlir::FlatSymbolRefAttrflat symbol reference attribute
dtor::mlir::FlatSymbolRefAttrflat symbol reference attribute

Operands:

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{}

Operands:

Operand Description
src floating-point

Results:

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

Attributes:

AttributeMLIR TypeDescription
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute
ast::mlir::cir::ASTCallExprInterfaceASTCallExprInterface instance

Operands:

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

Results:

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

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::UnaryOpKindAttrunary operation kind

Operands:

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

Results:

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)

Operands:

Operand Description
arg_list CIR pointer type

Results:

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)

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)

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)

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{}

Attributes:

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute
vtable_index::mlir::IntegerAttr32-bit signless integer attribute
address_point_index::mlir::IntegerAttr32-bit signless integer attribute

Operands:

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

Results:

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{}

Attributes:

AttributeMLIR TypeDescription
kind::mlir::cir::CmpOpKindAttrcompare operation kind

Operands:

Operand Description
lhs CIR vector type
rhs CIR vector type

Results:

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{}

Operands:

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

Results:

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{}

Operands:

Operand Description
vec CIR vector type
index Integer type with arbitrary precision up to a fixed limit

Results:

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{}

Operands:

Operand Description
vec CIR vector type
value any type
index Integer type with arbitrary precision up to a fixed limit

Results:

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

Operands:

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{}

Results:

Result Description
result any type