1. ‘cir’ Dialect

A high-level dialect for analyzing and optimizing Clang supported languages

1.1. Operations

1.1.1. cir.abs (::cir::AbsOp)

Computes the absolute value of a signed integer

Syntax:

operation ::= `cir.abs` $src ( `min_is_poison` $min_is_poison^ )? `:` type($src) attr-dict

cir.abs computes the absolute value of a signed integer or vector of signed integers.

The min_is_poison attribute indicates whether the result value is a poison value if the argument is statically or dynamically the minimum value for the type.

Example:

  %0 = cir.const #cir.int<-42> : s32i
  %1 = cir.abs %0 min_is_poison : s32i
  %2 = cir.abs %3 : !cir.vector<!s32i x 4>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.1.1. Attributes:

AttributeMLIR TypeDescription
min_is_poison::mlir::UnitAttrunit attribute

1.1.1.2. Operands:

Operand

Description

src

signed integer or vector of signed integer type

1.1.1.3. Results:

Result

Description

result

signed integer or vector of signed integer type

1.1.2. cir.acos (::cir::ACosOp)

Computes the arcus cosine of the specified value

Syntax:

operation ::= `cir.acos` $src `:` type($src) attr-dict

cir.acoscomputes the arcus cosine of a given value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.2.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.2.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.3. cir.add (::cir::AddOp)

Integer addition

Syntax:

operation ::= `cir.add` (`nsw` $no_signed_wrap^)?
              (`nuw` $no_unsigned_wrap^)?
              (`sat` $saturated^)?
              $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.add operation performs addition on integer operands. Both operands and the result must have the same integer or vector-of-integer type.

The optional nsw (no signed wrap) and nuw (no unsigned wrap) unit attributes indicate that the result is poison if signed or unsigned overflow occurs, respectively. The optional sat (saturated) attribute clamps the result to the type’s representable range instead of wrapping. The nsw/nuw flags and sat are mutually exclusive.

Example:

%0 = cir.add %a, %b : !s32i
%1 = cir.add nsw %a, %b : !s32i
%2 = cir.add nuw %a, %b : !u32i
%3 = cir.add sat %a, %b : !s32i
%4 = cir.add %va, %vb : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.3.1. Operands:

Operand

Description

lhs

integer or vector of integer type

rhs

integer or vector of integer type

1.1.3.2. Results:

Result

Description

result

integer or vector of integer type

1.1.4. cir.add.overflow (::cir::AddOverflowOp)

Integer addition with overflow checking

Syntax:

operation ::= `cir.add.overflow` $lhs `,` $rhs `:` qualified(type($lhs)) `->` qualified(type($result))
              attr-dict

cir.add.overflow performs addition with overflow checking on integral operands. See CIR_BinOpOverflow for semantics.

Example:

%result, %overflow = cir.add.overflow %a, %b : !u32i -> !u32i
%result, %overflow = cir.add.overflow %a, %b : !cir.int<s, 33> -> !s32i
%result, %overflow = cir.add.overflow %a, %b : !s32i -> !cir.bool

Traits: AlwaysSpeculatableImplTrait, Commutative, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.4.1. Operands:

Operand

Description

lhs

Integer type with arbitrary precision up to a fixed limit

rhs

Integer type with arbitrary precision up to a fixed limit

1.1.4.2. Results:

Result

Description

result

integer or boolean type

overflow

CIR bool type

1.1.5. cir.address_of_return_address (::cir::AddrOfReturnAddrOp)

The place stores the return address of the current function

Syntax:

operation ::= `cir.address_of_return_address` attr-dict `:` qualified(type($result))

Represents a call to builtin function _AddressOfReturnAddress in CIR. This builtin function returns a pointer to the place in the stack frame where the return address of the current function is stored.

Examples:

%addr = address_of_return_address() : !cir.ptr<!u8i>

1.1.5.1. Results:

Result

Description

result

CIR pointer type

1.1.6. cir.alloc.exception (::cir::AllocExceptionOp)

Allocates an exception according to Itanium ABI

Syntax:

operation ::= `cir.alloc.exception` $size `->` qualified(type($addr)) attr-dict

Implements a slightly higher level __cxa_allocate_exception:

void *__cxa_allocate_exception(size_t thrown_size);

If the operation fails, the program terminates rather than throw.

Example:

// if (b == 0) {
//   ...
//   throw "...";
cir.if %10 {
    %11 = cir.alloc_exception 8 -> !cir.ptr<!void>
    ... // store exception content into %11
    cir.throw %11 : !cir.ptr<!cir.ptr<!u8i>>, ...

1.1.6.1. Attributes:

AttributeMLIR TypeDescription
size::mlir::IntegerAttr64-bit signless integer attribute

1.1.6.2. Results:

Result

Description

addr

CIR pointer type

1.1.7. cir.alloca (::cir::AllocaOp)

Defines a scope-local variable

Syntax:

operation ::= `cir.alloca` $name
              `align` `(` $alignment `)`
              oilist( `init`              $init
              | `const`             $constant
              | `cleanup_dest_slot` $cleanup_dest_slot)
              (`size` `(` $dynAllocSize^ `)`)? `:` qualified(type($addr))
              ($annotations^)? attr-dict

The cir.alloca operation defines a scope-local variable.

The presence of the const attribute indicates that the local variable is declared with C/C++ const keyword.

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 or the alloca builtin and is omitted when declaring regular local variables.

The cleanup_dest_slot attribute indicates that this was a temporary alloca generated by the compiler to handle cleanup exit dispatching.

The result type is a pointer to the input’s type.

Example:

// int count;
%0 = cir.alloca "count" align(4) : !cir.ptr<i32>

// int *ptr;
%1 = cir.alloca "ptr" align(8) : !cir.ptr<!cir.ptr<i32>>
...

Interfaces: PromotableAllocationOpInterface

1.1.7.1. Attributes:

AttributeMLIR TypeDescription
name::mlir::StringAttrstring attribute
init::mlir::UnitAttrunit attribute
constant::mlir::UnitAttrunit attribute
cleanup_dest_slot::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute whose minimum value is 1
annotations::mlir::ArrayAttrarray of cir.annotation attributes

1.1.7.2. Operands:

Operand

Description

dynAllocSize

64-bit unsigned integer

1.1.7.3. Results:

Result

Description

addr

CIR pointer type

1.1.8. cir.and (::cir::AndOp)

Bitwise AND

Syntax:

operation ::= `cir.and` $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.and operation performs a bitwise AND on integer operands. Both operands and the result must have the same integer type.

Example:

%0 = cir.and %a, %b : !s32i
%1 = cir.and %a, %b : !cir.bool

Traits: Commutative, Idempotent, SameOperandsAndResultType

Interfaces: BinaryOpInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.8.1. Operands:

Operand

Description

lhs

integer, boolean, or vector of integer

rhs

integer, boolean, or vector of integer

1.1.8.2. Results:

Result

Description

result

integer, boolean, or vector of integer

1.1.9. cir.array.ctor (::cir::ArrayCtor)

Initialize array elements with C++ constructors

Syntax:

operation ::= `cir.array.ctor` $addr (`,` $num_elements^)? `:` qualified(type($addr))
              (`,` type($num_elements)^)? $body
              (`partial_dtor` $partial_dtor^)?
              attr-dict

Initialize each array element using the same C++ constructor. This operation has a body region and an optional partial_dtor region. Both regions have a single block whose argument is a pointer to the current array element.

The body region contains the constructor call for one element.

The partial_dtor region, when non-empty, contains the destructor call for one element. During lowering, it is used to build a cleanup that destroys already-constructed elements if a constructor throws. When the element type has a trivial destructor or exceptions are disabled, the partial_dtor region is left empty.

When num_elements is absent, addr must be a pointer to a fixed-size CIR array type and the element count is derived from that array type.

When num_elements is present, addr is a pointer to the first element and num_elements provides the runtime element count (for example new T[n]).

Examples:

// Fixed size without partial destructor:
cir.array.ctor(%0 : !cir.ptr<!cir.array<!rec_S x 42>>) {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Variable size without partial destructor:
cir.array.ctor(%ptr, %n : !cir.ptr<!rec_S>, !u64i) {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Fixed size with partial destructor:
cir.array.ctor(%0 : !cir.ptr<!cir.array<!rec_S x 42>>) {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
} partial_dtor {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @some_dtor(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

Traits: SingleBlockImplicitTerminator<cir::YieldOp>, SingleBlock

1.1.9.1. Operands:

Operand

Description

addr

pointer type

num_elements

integer type

1.1.10. cir.array.dtor (::cir::ArrayDtor)

Destroy array elements with C++ destructors

Syntax:

operation ::= `cir.array.dtor` $addr (`,` $num_elements^)? `:` qualified(type($addr))
              (`,` type($num_elements)^)? (`dtor_may_throw` $dtor_may_throw^)? $body
              attr-dict

Destroy each array element using the same C++ destructor. This operation has one region with one block whose argument is a pointer to the current array element.

When num_elements is absent, addr must be a pointer to a fixed-size CIR array type and the element count is derived from that array type.

When num_elements is present, addr is a pointer to the first element and num_elements provides the runtime element count (e.g. from an array cookie for delete[]).

When dtor_may_throw is present, the element destructor call may throw an exception.

Elements are destroyed in reverse order.

Examples:

// Fixed-size (stack array, global):
cir.array.dtor %0 : !cir.ptr<!cir.array<!rec_S x 42>> {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @_ZN1SD1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Dynamic count (delete[] with destructor):
cir.array.dtor %ptr, %n : !cir.ptr<!rec_S>, !u64i {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @_ZN1SD1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

// Dynamic count (delete[] with throwing destructor):
cir.array.dtor %ptr, %n : !cir.ptr<!rec_S>, !u64i dtor_may_throw {
  ^bb0(%arg0: !cir.ptr<!rec_S>):
    cir.call @_ZN1SD1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
}

Traits: SingleBlockImplicitTerminator<cir::YieldOp>, SingleBlock

1.1.10.1. Operands:

Operand

Description

addr

pointer type

num_elements

integer type

1.1.11. cir.asin (::cir::ASinOp)

Computes the arcus sine of the specified value

Syntax:

operation ::= `cir.asin` $src `:` type($src) attr-dict

cir.asincomputes the arcus sine of a given value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.11.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.11.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.12. cir.asm (::cir::InlineAsmOp)

The cir.asm operation represents C/C++ asm inline.

CIR constraints strings follow 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

Operand attributes are a storage, where each element corresponds to the operand with the same index. The first index relates to the operation result (if any). The operands themselves are stored as VariadicOfVariadic in the following order: output, input and then in/out operands. When several output operands are present, the result type may be represented as an anonymous record type.

Example:

__asm__("foo" : : : );
__asm__("bar $42 %[val]" : [val] "=r" (x), "+&r"(x));
__asm__("baz $42 %[val]" : [val] "=r" (x), "+&r"(x) : "[val]"(y));
!rec_22anon2E022 = !cir.record<struct "anon.0" {!cir.int<s, 32>, !cir.int<s, 32>}>
!rec_22anon2E122 = !cir.record<struct "anon.1" {!cir.int<s, 32>, !cir.int<s, 32>}>
...
%0 = cir.alloca "x" align(4) init : !cir.ptr<!s32i>
%1 = cir.alloca "y" align(4) init : !cir.ptr<!s32i>
...
%2 = cir.load %0 : !cir.ptr<!s32i>, !s32i
%3 = cir.load %1 : !cir.ptr<!s32i>, !s32i

cir.asm(x86_att,
  out = [],
  in = [],
  in_out = [],
  {"foo" "~{dirflag},~{fpsr},~{flags}"}) side_effects

cir.asm(x86_att,
  out = [],
  in = [],
  in_out = [%2 : !s32i],
  {"bar $$42 $0" "=r,=&r,1,~{dirflag},~{fpsr},~{flags}"}) -> !rec_22anon2E022

cir.asm(x86_att,
  out = [],
  in = [%3 : !s32i],
  in_out = [%2 : !s32i],
  {"baz $$42 $0" "=r,=&r,0,1,~{dirflag},~{fpsr},~{flags}"}) -> !rec_22anon2E122

Traits: RecursiveMemoryEffects

1.1.12.1. Attributes:

AttributeMLIR TypeDescription
asm_string::mlir::StringAttrstring attribute
constraints::mlir::StringAttrstring attribute
side_effects::mlir::UnitAttrunit attribute
asm_flavor::cir::AsmFlavorAttrATT or Intel
operand_attrs::mlir::ArrayAttrarray attribute
operands_segments::mlir::DenseI32ArrayAttri32 dense array attribute

1.1.12.2. Operands:

Operand

Description

asm_operands

variadic of any non-token type

1.1.12.3. Results:

Result

Description

res

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.13. cir.assume (::cir::AssumeOp)

Tell the optimizer that a boolean value is true

Syntax:

operation ::= `cir.assume` $predicate custom<AssumeBundle>($bundle_kind, $bundle_args,
              type($bundle_args))
              `:` type($predicate) attr-dict

The cir.assume operation takes a single boolean predicate as its first argument and does not have any results. The operation tells the optimizer that the predicate is always true.

An optional operand bundle carries additional assumption metadata, mirroring MLIR LLVM dialect’s llvm.assume operand bundles (mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td). The bundle kind is a AssumeBundleKind enum; bundle operands follow the kind keyword in the assembly form. For example, __builtin_assume_dereferenceable(p, n) lowers to cir.assume %true dereferenceable(%p, %n : !cir.ptr<!void>, !u64i) : !cir.bool, which in turn lowers to call void @llvm.assume(i1 true) [ "dereferenceable"(ptr, i64) ].

This operation corresponds to the __assume / __builtin_assume builtins (no bundle), as well as __builtin_assume_aligned (align bundle), __builtin_assume_separate_storage (separate_storage bundle), and __builtin_assume_dereferenceable (dereferenceable bundle).

1.1.13.1. Attributes:

AttributeMLIR TypeDescription
bundle_kind::cir::AssumeBundleKindAttrkind of cir.assume operand bundle

1.1.13.2. Operands:

Operand

Description

predicate

CIR bool type

bundle_args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.14. cir.atan (::cir::ATanOp)

Computes the floating-point arcus tangent value

Syntax:

operation ::= `cir.atan` $src `:` type($src) attr-dict

cir.atan computes the arcus tangent of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.14.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.14.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.15. cir.atan2 (::cir::ATan2Op)

Computes the arc tangent of y/x

Syntax:

operation ::= `cir.atan2` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict

cir.atan2 computes the arc tangent of the first operand divided by the second operand, using the signs of both to determine the quadrant.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.15.1. Operands:

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

1.1.15.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.16. cir.atomic.clear (::cir::AtomicClearOp)

Atomic clear

Syntax:

operation ::= `cir.atomic.clear` $mem_order $ptr
              (`volatile` $is_volatile^)?
              `:` qualified(type($ptr)) attr-dict

C/C++ atomic clear operation. Implements the builtin function __atomic_clear.

The operation takes as its only operand a pointer to an 8-bit signed integer. The operation atomically sets the integer to zero.

Example:

  cir.atomic.clear seq_cst %ptr : !cir.ptr<!s8i>

1.1.16.1. Attributes:

AttributeMLIR TypeDescription
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

1.1.16.2. Operands:

Operand

Description

ptr

pointer to 8-bit signed integer

1.1.17. cir.atomic.cmpxchg (::cir::AtomicCmpXchgOp)

Atomic compare and exchange

Syntax:

operation ::= `cir.atomic.cmpxchg` (`weak` $weak^)?
              `success` `(` $succ_order `)` `failure` `(` $fail_order `)`
              `syncscope` `(` $sync_scope `)`
              $ptr `,` $expected `,` $desired
              (`align` `(` $alignment^ `)`)?
              (`volatile` $is_volatile^)?
              `:` functional-type(operands, results) attr-dict

C/C++ atomic compare and exchange operation. Implements builtins like __atomic_compare_exchange_n and __atomic_compare_exchange.

This operation takes three arguments: a pointer ptr and two values expected and desired. This operation compares the value of the object pointed-to by ptr with expected, and if they are equal, it sets the value of the object to desired.

The succ_order attribute gives the memory order of this atomic operation when the exchange takes place. The fail_order attribute gives the memory order of this atomic operation when the exchange does not take place.

The sync_scope attribute specifies the synchronization scope for this atomic operation.

The weak attribute is a boolean flag that indicates whether this is a “weak” compare-and-exchange operation. A weak compare-and-exchange operation allows “spurious failures”, meaning that be treated as if the comparison failed and not exchange values even if *ptr and expected indeed compare equal.

The type of expected and desired must be the same. The pointee type of ptr must be the same as the type of expected and desired.

This operation has two results. The first result old gives the old value of the object pointed-to by ptr, regardless of whether the exchange actually took place. The second result success is a boolean flag indicating whether the exchange actually took place.

Example:

%old, %success = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire)
    syncscope(system) %ptr, %expected, %desired
    : (!cir.ptr<!u64i>, !u64i, !u64i) -> (!u64i, !cir.bool)

Interfaces: InferTypeOpInterface

1.1.17.1. Attributes:

AttributeMLIR TypeDescription
succ_order::cir::MemOrderAttrMemory order according to C++11 memory model
fail_order::cir::MemOrderAttrMemory order according to C++11 memory model
sync_scope::cir::SyncScopeKindAttrsync scope kind
alignment::mlir::IntegerAttr64-bit signless integer attribute
weak::mlir::UnitAttrunit attribute
is_volatile::mlir::UnitAttrunit attribute

1.1.17.2. Operands:

Operand

Description

ptr

CIR pointer type

expected

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

desired

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.17.3. Results:

Result

Description

old

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

success

CIR bool type

1.1.18. cir.atomic.fence (::cir::AtomicFenceOp)

Atomic thread fence

Syntax:

operation ::= `cir.atomic.fence` (`syncscope` `(` $syncscope^ `)`)? $ordering attr-dict

C/C++ Atomic thread fence synchronization primitive. Implements the builtin __atomic_thread_fence which enforces memory ordering constraints across threads within the specified synchronization scope.

This handles all variations including:

  • __atomic_thread_fence

  • __atomic_signal_fence

  • __c11_atomic_thread_fence

  • __c11_atomic_signal_fence

Example:

  cir.atomic.fence syncscope(system) seq_cst
  cir.atomic.fence syncscope(single_thread) seq_cst

1.1.18.1. Attributes:

AttributeMLIR TypeDescription
ordering::cir::MemOrderAttrMemory order according to C++11 memory model
syncscope::cir::SyncScopeKindAttrsync scope kind

1.1.19. cir.atomic.fetch (::cir::AtomicFetchOp)

Atomic fetch-and-update operation

Syntax:

operation ::= `cir.atomic.fetch` $binop $mem_order
              `syncscope` `(` $sync_scope `)`
              (`fetch_first` $fetch_first^)?
              $ptr `,` $val
              (`volatile` $is_volatile^)?
              `:` `(` qualified(type($ptr)) `,` qualified(type($val)) `)`
              `->` type($result) attr-dict

C/C++ atomic fetch-and-update operation. This operation implements the C/C++ builtin functions __atomic_<binop>_fetch, __atomic_fetch_<binop>, and __c11_atomic_fetch_<binop>, where <binop> is one of the following binary opcodes: add, sub, and, xor, or, nand, max, min, uinc_wrap, and udec_wrap.

This operation takes 2 arguments: a pointer ptr and a value val. The type of val must match the pointee type of ptr. If the binary operation is add, sub, max, or min, the type of val may either be an integer type or a floating-point type. Otherwise, val must be an integer.

This operation atomically loads the value from ptr, performs the binary operation as indicated by binop on the loaded value and val, and stores the result back to ptr. If the fetch_first flag is present, the result of this operation is the old value loaded from ptr before the binary operation. Otherwise, the result of this operation is the result of the binary operation.

Example:

: (!cir.ptr<!s32i>, !s32i) -> !s32i

Interfaces: InferTypeOpInterface

1.1.19.1. Attributes:

AttributeMLIR TypeDescription
binop::cir::AtomicFetchKindAttrBinary opcode for atomic fetch-and-update operations
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
sync_scope::cir::SyncScopeKindAttrsync scope kind
is_volatile::mlir::UnitAttrunit attribute
fetch_first::mlir::UnitAttrunit attribute

1.1.19.2. Operands:

Operand

Description

ptr

pointer to integer or floating point type

val

integer or floating point type

1.1.19.3. Results:

Result

Description

result

integer or floating point type

1.1.20. cir.atomic.test_and_set (::cir::AtomicTestAndSetOp)

Atomic test and set

Syntax:

operation ::= `cir.atomic.test_and_set` $mem_order $ptr
              (`volatile` $is_volatile^)?
              `:` qualified(type($ptr)) `->` qualified(type($result)) attr-dict

C/C++ atomic test and set operation. Implements the builtin function __atomic_test_and_set.

The operation takes as its only operand a pointer to an 8-bit signed integer. The operation atomically set the integer to an implementation- defined non-zero “set” value. The result of the operation is a boolean value indicating whether the previous value of the integer was the “set” value.

Example:

  %res = cir.atomic.test_and_set seq_cst %ptr : !cir.ptr<!s8i> -> !cir.bool

Interfaces: InferTypeOpInterface

1.1.20.1. Attributes:

AttributeMLIR TypeDescription
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

1.1.20.2. Operands:

Operand

Description

ptr

pointer to 8-bit signed integer

1.1.20.3. Results:

Result

Description

result

CIR bool type

1.1.21. cir.atomic.xchg (::cir::AtomicXchgOp)

Atomic exchange

Syntax:

operation ::= `cir.atomic.xchg` $mem_order
              `syncscope` `(` $sync_scope `)`
              (`volatile` $is_volatile^)?
              $ptr `,` $val
              `:` functional-type(operands, results) attr-dict

C/C++ atomic exchange operation. This operation implements the C/C++ builtin function __atomic_exchange, __atomic_exchange_n, and __c11_atomic_exchange.

This operation takes two arguments: a pointer ptr and a value val. The operation atomically replaces the value of the object pointed-to by ptr with val, and returns the original value of the object.

Example:

%res = cir.atomic.xchg seq_cst %ptr, %val : !cir.ptr<!u64i> -> !u64i

Interfaces: InferTypeOpInterface

1.1.21.1. Attributes:

AttributeMLIR TypeDescription
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
sync_scope::cir::SyncScopeKindAttrsync scope kind
is_volatile::mlir::UnitAttrunit attribute

1.1.21.2. Operands:

Operand

Description

ptr

CIR pointer type

val

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.21.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.22. 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 allows 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 4 flavors of cir.await available:

  • init: compiler generated initial suspend via implicit co_await.

  • user: also known as normal, representing a user written co_await.

  • yield: user written co_yield expressions.

  • final: compiler generated final suspend via implicit co_await.

  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

1.1.22.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::AwaitKindAttrawait kind

1.1.23. cir.base_class_addr (::cir::BaseClassAddrOp)

Get the base class address for a class/struct

Syntax:

operation ::= `cir.base_class_addr` $derived_addr `:` qualified(type($derived_addr))
              (`nonnull` $assume_not_null^)?
              ` ` `[` $offset `]` `->` qualified(type($base_addr)) attr-dict

The cir.base_class_addr operaration gets the address of a particular non-virtual base class given a derived class pointer. The offset in bytes of the base class must be passed in, since it is easier for the front end to calculate that than the MLIR passes. The operation contains a flag for whether or not the operand may be nullptr. That depends on the context and cannot be known by the operation, and that information affects how the operation is lowered.

The validity of the relationship of derived and base cannot yet be verified. If the target class is not a valid base class for the object, the behavior is undefined.

Example:

struct Base { };
struct Derived : Base { };
Derived d;
Base& b = d;

will generate

%3 = cir.base_class_addr %1 : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.23.1. Attributes:

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute
assume_not_null::mlir::UnitAttrunit attribute

1.1.23.2. Operands:

Operand

Description

derived_addr

CIR pointer type

1.1.23.3. Results:

Result

Description

base_addr

CIR pointer type

1.1.24. cir.base_data_member (::cir::BaseDataMemberOp)

Cast a derived class data member pointer to a base class data member pointer

Syntax:

operation ::= `cir.base_data_member` $src `[` $offset `]` `:` qualified(type($src)) `->` qualified(type($result)) attr-dict

The cir.base_data_member operation casts a data member pointer of type T Derived::* to a data member pointer of type T Base::*, where Base is an accessible non-ambiguous non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.24.1. Attributes:

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

1.1.24.2. Operands:

Operand

Description

src

CIR type that represents a pointer-to-data-member in C++

1.1.24.3. Results:

Result

Description

result

CIR type that represents a pointer-to-data-member in C++

1.1.25. cir.base_method (::cir::BaseMethodOp)

Cast a derived class pointer-to-member-function to a base class pointer-to-member-function

Syntax:

operation ::= `cir.base_method` $src `[` $offset `]` `:` qualified(type($src))
              `->` qualified(type($result)) attr-dict

The cir.base_method operation casts a pointer-to-member-function of type Ret (Derived::*)(Args) to a pointer-to-member-function of type Ret (Base::*)(Args), where Base is a non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Example:

%1 = cir.base_method %0 [16] : !cir.method<!cir.func<(!s32i)> in !rec_Derived> -> !cir.method<!cir.func<(!s32i)> in !rec_Base>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.25.1. Attributes:

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

1.1.25.2. Operands:

Operand

Description

src

CIR type that represents C++ pointer-to-member-function type

1.1.25.3. Results:

Result

Description

result

CIR type that represents C++ pointer-to-member-function type

1.1.26. cir.begin_catch (::cir::BeginCatchOp)

Begin a catch handler

Syntax:

operation ::= `cir.begin_catch` $eh_token `:` type($eh_token) `->` `(` type($catch_token) `,`
              qualified(type($exn_ptr)) `)` attr-dict

cir.begin_catch marks the beginning of a catch handler. It takes a !cir.eh_token representing the inflight exception and returns a !cir.catch_token along with a pointer to the exception object.

The catch token must be passed to the corresponding cir.end_catch operation. The exception pointer points to the caught exception object and can be used to access the exception value.

For catch(...) (catch all), the exception pointer type is !cir.ptr<!void>.

In the high-level CIR representation, this operation appears as the first operation in a catch handler region of a cir.try operation, taking the region’s !cir.eh_token argument. In the flattened CIR representation, it appears in a catch block, taking the block’s !cir.eh_token argument.

Example:

// High-level form (inside cir.try catch handler region):
} catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) {
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
  cir.cleanup.scope {
    // Handle exception...
    cir.yield
  } cleanup eh {
    cir.end_catch %catch_token : !cir.catch_token
    cir.yield
  }
  cir.yield
}

// Flattened form (inside a catch block):
^catch_int(%eh_token : !cir.eh_token):
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
  // Handle exception...
  cir.end_catch %catch_token : !cir.catch_token
  cir.br ^continue

1.1.26.1. Operands:

Operand

Description

eh_token

CIR exception handling token type

1.1.26.2. Results:

Result

Description

catch_token

CIR catch token type

exn_ptr

CIR pointer type

1.1.27. cir.begin_cleanup (::cir::BeginCleanupOp)

Begin a cleanup block during exception unwinding

Syntax:

operation ::= `cir.begin_cleanup` $eh_token `:` type($eh_token) `->` type($cleanup_token) attr-dict

cir.begin_cleanup marks the beginning of a cleanup handler during exception unwinding. It takes a !cir.eh_token and returns a !cir.cleanup_token that must be passed to the corresponding cir.end_cleanup operation.

The cleanup code between cir.begin_cleanup and cir.end_cleanup will be executed during exception unwinding before control is transferred to the exception dispatcher.

Example:

^cleanup(%eh_token : !cir.eh_token):
  %cleanup_token = cir.begin_cleanup %eh_token : !cir.eh_token
                                               -> !cir.cleanup_token
  cir.call @destructor() : () -> ()
  cir.end_cleanup %cleanup_token : !cir.cleanup_token
  cir.br ^dispatch(%eh_token : !cir.eh_token)

Interfaces: InferTypeOpInterface

1.1.27.1. Operands:

Operand

Description

eh_token

CIR exception handling token type

1.1.27.2. Results:

Result

Description

cleanup_token

CIR cleanup token type

1.1.28. cir.bitreverse (::cir::BitReverseOp)

Reverse the bit pattern of the operand integer

Syntax:

operation ::= `cir.bitreverse` $input `:` type($result) attr-dict

The cir.bitreverse operation reverses the bits of the operand integer. Its only argument must be of unsigned integer types of width 8, 16, 32, or 64.

Example:

%1 = cir.bitreverse %0: !u32i

Traits: AlwaysSpeculatableImplTrait, Involution, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.28.1. Operands:

Operand

Description

input

unsigned integer type of widths 8/16/32/64

1.1.28.2. Results:

Result

Description

result

unsigned integer type of widths 8/16/32/64

1.1.29. cir.block_address (::cir::BlockAddressOp)

Get the address of a cir.label within a function

Syntax:

operation ::= `cir.block_address` $block_addr_info `:` qualified(type($addr)) attr-dict

The cir.blockaddress operation takes a function name and a label and produces a pointer value that represents the address of that cir.label within the specified function.

This operation models GCC’s “labels as values” extension (&&label), which allows taking the address of a local label and using it as a computed jump target (e.g., with goto *addr;).

Example:

%1 = cir.alloca "ptr" align(8) init : !cir.ptr<!cir.ptr<!void>>
%addr = cir.block_address <@c, "label1"> : !cir.ptr<!cir.void>
cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
cir.br ^bb1
^bb1:
cir.label "label"

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.29.1. Attributes:

AttributeMLIR TypeDescription
block_addr_info::cir::BlockAddrInfoAttrBlock address attribute

1.1.29.2. Results:

Result

Description

addr

pointer to void type

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

Note that for source level goto’s crossing scope boundaries, those are usually represented with the “symbolic” cir.goto operation.

Example:

  ...
    cir.br ^bb3
  ^bb3:
    cir.return

Traits: AlwaysSpeculatableImplTrait, Terminator

Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.30.1. Operands:

Operand

Description

destOperands

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.30.2. Successors:

Successor

Description

dest

any successor

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

it branches to ‘bb1’.

Example:

  ...
    cir.brcond %a, ^bb3, ^bb4
  ^bb3:
    cir.return
  ^bb4:
    cir.yield

Traits: AlwaysSpeculatableImplTrait, AttrSizedOperandSegments, Terminator

Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.31.1. Operands:

Operand

Description

cond

CIR bool type

destOperandsTrue

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

destOperandsFalse

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.31.2. Successors:

Successor

Description

destTrue

any successor

destFalse

any successor

1.1.32. cir.break (::cir::BreakOp)

C/C++ break statement equivalent

Syntax:

operation ::= `cir.break` attr-dict

The cir.break operation is used to cease the execution of the current loop or switch operation and transfer control to the parent operation. It is only allowed within a breakable operations (loops and switches).

Traits: HasAncestor<WhileOp, DoWhileOp, ForOp, SwitchOp>, Terminator

1.1.33. cir.builtin_int_cast (::cir::BuiltinIntCastOp)

Cast between a CIR integer and a builtin integer

Syntax:

operation ::= `cir.builtin_int_cast` $src `:` type($src) `->` type($result) attr-dict

Convert between a CIR integer type (!cir.int) and a builtin MLIR integer type (AnyInteger, e.g. i32, si32, ui32) or index, and vice versa.

This allows using operations from e.g. OpenMP or OpenACC dialects that expect the builtin types with CIR operations. Casting can be done in either direction.

Example:

// CIR integer cast to a builtin integer.
%0 = cir.builtin_int_cast %ciri : !cir.int<s, 32> -> i32

// Builtin induction variable / bound cast to CIR type.
%1 = cir.builtin_int_cast %iv : index -> !cir.int<u, 64>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.33.1. Operands:

Operand

Description

src

Integer type with arbitrary precision up to a fixed limit or integer or index

1.1.33.2. Results:

Result

Description

result

Integer type with arbitrary precision up to a fixed limit or integer or index

1.1.34. cir.byte_swap (::cir::ByteSwapOp)

Reverse the bytes in the object representation of the operand

Syntax:

operation ::= `cir.byte_swap` $input `:` type($result) attr-dict

The cir.byte_swap operation takes an integer as operand, reverse the bytes in the object representation of the operand integer, and returns the result.

The operand integer must be an unsigned integer whose width is a multiple of 16 bits (e.g. 16, 32, 64, 128, or a wider _BitInt).

Example:

// %0 = 0x12345678
%0 = cir.const #cir.int<305419896> : !u32i

// %1 should be 0x78563412
%1 = cir.byte_swap %0 : !u32i

Traits: AlwaysSpeculatableImplTrait, Involution, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.34.1. Operands:

Operand

Description

input

unsigned integer type with a width that is a multiple of 16 bits

1.1.34.2. Results:

Result

Description

result

unsigned integer type with a width that is a multiple of 16 bits

1.1.35. cir.call (::cir::CallOp)

Call a function

The cir.call operation represents a function call. It could represent either a direct call or an indirect call.

If the operation represents a direct call, the callee should be defined within the same symbol scope as the call. The callee attribute contains a symbol reference to the callee function. All operands of this operation are arguments to the callee function.

If the operation represents an indirect call, the callee attribute is empty. The first operand of this operation must be a pointer to the callee function. The rest operands are arguments to the callee function.

Example:

%0 = cir.call @foo()

Traits: NoRegionArguments

Interfaces: ArgAndResultAttrsOpInterface, CIRCallOpInterface, CallOpInterface, SymbolUserOpInterface

1.1.35.1. Attributes:

AttributeMLIR TypeDescription
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute
nothrow::mlir::UnitAttrunit attribute
musttail::mlir::UnitAttrunit attribute
side_effect::cir::SideEffectAttrallowed side effects of a function
arg_attrs::mlir::ArrayAttrArray of dictionary attributes
res_attrs::mlir::ArrayAttrArray of dictionary attributes

1.1.35.2. Operands:

Operand

Description

args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.35.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.36. cir.call_llvm_intrinsic (::cir::LLVMIntrinsicCallOp)

Call to llvm intrinsic functions that is not defined in CIR

Syntax:

operation ::= `cir.call_llvm_intrinsic` $intrinsic_name $arg_ops `:` functional-type($arg_ops, $result) attr-dict

cir.call_llvm_intrinsic operation represents a call-like expression which has return type and arguments that maps directly to a llvm intrinsic. It only records intrinsic intrinsic_name.

1.1.36.1. Attributes:

AttributeMLIR TypeDescription
intrinsic_name::mlir::StringAttrstring attribute

1.1.36.2. Operands:

Operand

Description

arg_ops

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.36.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.37. cir.case (::cir::CaseOp)

Case operation

Syntax:

operation ::= `cir.case` `(` $kind `,` $value `)` $caseRegion attr-dict

The cir.case operation represents a case within a C/C++ switch. The cir.case operation must be in a cir.switch operation directly or indirectly.

The cir.case have 4 kinds:

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

  • range, [lower-bound, upper-bound]: the condition is within the closed interval.

  • default: any other value.

Each case region must be explicitly terminated.

Traits: AutomaticAllocationScope, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

1.1.37.1. Attributes:

AttributeMLIR TypeDescription
value::mlir::ArrayAttrarray attribute
kind::cir::CaseOpKindAttrcase kind

1.1.38. cir.cast (::cir::CastOp)

Conversion between values of different types

Syntax:

operation ::= `cir.cast` $kind $src `:` type($src) `->` type($result) attr-dict

Apply the usual C/C++ conversion rules between values. This operation models a subset of conversions as defined in Clang’s OperationKinds.def (llvm-project/clang/include/clang/AST/OperationKinds.def).

Note: not all conversions are implemented using cir.cast. For instance, lvalue-to-rvalue conversion is modeled as a cir.load instead. Currently supported kinds:

  • bitcast

  • array_to_ptrdecay

  • `member_ptr_to_bool

  • int_to_ptr

  • ptr_to_int

  • ptr_to_bool

  • integral

  • int_to_bool

  • int_to_float

  • float_to_int

  • float_to_bool

  • bool_to_int

  • floating

  • float_complex

  • int_complex_to_real

  • int_complex_to_bool

  • int_complex

  • int_complex_to_float_complex

  • address_space

CIR also supports some additional conversions that are not part of the classic Clang codegen:

  • bool_to_float

Example:

%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), PromotableOpInterface

Effects: MemoryEffects::Effect{}

1.1.38.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::CastKindAttrcast kind

1.1.38.2. Operands:

Operand

Description

src

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.38.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.39. cir.catch_param (::cir::CatchParamOp)

Represents the catch clause formal parameter

Syntax:

operation ::= `cir.catch_param` (`:` qualified(type($param))^)?
              attr-dict

The cir.catch_param is used to retrieve the exception object inside the handler regions of cir.try.

This operation is used only before the CFG flatterning pass.

Example:

%exception = cir.catch_param : !cir.ptr<!void>

Traits: HasParent<TryOp>

1.1.39.1. Results:

Result

Description

param

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.40. cir.ceil (::cir::CeilOp)

Computes the ceiling of the specified value

Syntax:

operation ::= `cir.ceil` $src `:` type($src) attr-dict

cir.ceil computes the ceiling of a given value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.40.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.40.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.41. cir.cleanup.scope (::cir::CleanupScopeOp)

Represents a scope with associated cleanup code

Syntax:

operation ::= `cir.cleanup.scope` $bodyRegion `cleanup` $cleanupKind $cleanupRegion attr-dict

cir.cleanup.scope contains a body region and a cleanup region. The body region is executed first, and the cleanup region is executed when the body region is exited, either normally or due to an exception.

The cleanup kind attribute specifies when the cleanup region should be executed:

  • none: No cleanup (cleanup region is empty/unused)

  • normal: Cleanup is executed only on normal exit

  • eh: Cleanup is executed only on exception unwinding

  • all: Cleanup is executed on both normal exit and exception unwinding

Examples:

// Cleanup that runs on both normal and exception paths
cir.cleanup.scope {
  cir.call @mayThrow() : () -> ()
  cir.yield
} cleanup all {
  cir.call @destructor() : () -> ()
  cir.yield
}

// EH-only cleanup (destructor only called on exception)
cir.cleanup.scope {
  cir.call @mayThrow() : () -> ()
  cir.yield
} cleanup eh {
  cir.call @destructor() : () -> ()
  cir.yield
}

Both regions must be terminated. If a region has only one block, the terminator can be left out, and cir.yield will be inserted implicitly.

Traits: AutomaticAllocationScope, NoRegionArguments, RecursiveMemoryEffects, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

1.1.41.1. Attributes:

AttributeMLIR TypeDescription
cleanupKind::cir::CleanupKindAttrCleanup kind attribute

1.1.42. cir.clear_cache (::cir::ClearCacheOp)

Clear the processor’s instruction cache if required.

Syntax:

operation ::= `cir.clear_cache` $begin `,` $end `:` qualified(type($begin))
              attr-dict

The cir.clear_cache operation provides a representation for the __builtin__clear_cache builtin and corresponds to the llvm.clear_cache intrinsic in LLVM IR.

This operation ensures visibility of modifications in the specified range to the execution unit of the processor. On targets with non-unified instruction and data cache, the implementation flushes the instruction cache.

On platforms with coherent instruction and data caches (e.g., x86), this intrinsic is a nop. On platforms with non-coherent instruction and data cache (e.g., ARM, MIPS), the operation will be lowered either to appropriate instructions or a system call, if cache flushing requires special privileges.

The default behavior is to emit a call to __clear_cache from the runtime library.

This operation does not empty the instruction pipeline. Modifications of the current function are outside the scope of the operation.

1.1.42.1. Operands:

Operand

Description

begin

pointer to void type

end

pointer to void type

1.1.43. cir.clrsb (::cir::BitClrsbOp)

Get the number of leading redundant sign bits in the input

Syntax:

operation ::= `cir.clrsb` $input `:` type($result) attr-dict

Compute the number of leading redundant sign bits in the input integer.

The input integer must be a signed integer. The most significant bit of the input integer is the sign bit. The cir.clrsb operation returns the number of consecutive bits following the sign bit that are identical to the sign bit.

The bit width of the input integer must be either 32 or 64.

Examples:

// %0 = 0b1101_1110_1010_1101_1011_1110_1110_1111
%0 = cir.const #cir.int<3735928559> : !s32i
// %1 will be 1 because there is 1 bit following the most significant bit
// that is identical to it.
%1 = cir.clrsb %0 : !s32i

// %2 = 1, 0b0000_0000_0000_0000_0000_0000_0000_0001
%2 = cir.const #cir.int<1> : !s32i
// %3 will be 30 because there are 30 consecutive bits following the sign
// bit that are identical to the sign bit.
%3 = cir.clrsb %2 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.43.1. Operands:

Operand

Description

input

signed integer type of widths 32/64

1.1.43.2. Results:

Result

Description

result

signed integer type of widths 32/64

1.1.44. cir.clz (::cir::BitClzOp)

Get the number of leading 0-bits in the input

Syntax:

operation ::= `cir.clz` $input (`poison_zero` $poison_zero^)?
              `:` type($result) attr-dict

Compute the number of leading 0-bits in the input.

The input integer must be an unsigned integer. The cir.clz operation returns the number of consecutive 0-bits at the most significant bit position in the input.

If the poison_zero attribute is present, this operation will have undefined behavior if the input value is 0.

Example:

// %0 = 0b0000_0000_0000_0000_0000_0000_0000_1000
%0 = cir.const #cir.int<8> : !u32i
// %1 will be 28
%1 = cir.clz %0 poison_zero : !u32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.44.1. Attributes:

AttributeMLIR TypeDescription
poison_zero::mlir::UnitAttrunit attribute

1.1.44.2. Operands:

Operand

Description

input

unsigned integer type of widths 8/16/32/64/128

1.1.44.3. Results:

Result

Description

result

unsigned integer type of widths 8/16/32/64/128

1.1.45. cir.cmp (::cir::CmpOp)

Compare two values and produce a boolean result

Syntax:

operation ::= `cir.cmp` $kind $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.cmp operation compares two operands of the same type and produces a !cir.bool result. It supports integral, floating-point, and pointer types.

The following comparison predicates are available:

  • lt: less than

  • le: less than or equal

  • gt: greater than

  • ge: greater than or equal

  • eq: equal

  • ne: not equal

  • one: ordered and not equal (floating-point only)

  • uno: unordered (floating-point only, true if either operand is NaN)

For floating-point comparisons, the predicate follows C semantics (e.g. NaN comparisons return false for all predicates except ne). The one and uno predicates are floating-point specific: one is ordered not-equal (false for NaN), uno tests if either operand is NaN.

%0 = cir.cmp gt %1, %2 : !s32i
%1 = cir.cmp eq %a, %b : !cir.ptr<!u8i>

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.45.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::CmpOpKindAttrcompare operation kind

1.1.45.2. Operands:

Operand

Description

lhs

comparable type

rhs

comparable type

1.1.45.3. Results:

Result

Description

result

CIR bool type

1.1.46. cir.cmp3way (::cir::CmpThreeWayOp)

Compare two values with C++ three-way comparison semantics

Syntax:

operation ::= `cir.cmp3way` qualified($info) $lhs `,` $rhs `:` qualified(type($lhs))
              `->` qualified(type($result)) attr-dict

The cir.cmp3way operation models the builtin <=> operator in C++20. It takes two operands with the same type and produces a result indicating the ordering between the two input operands.

The result of the operation is a signed integer that indicates the ordering between the two input operands.

There are three kinds of ordering: strong, weak and partial ordering. Comparing different types of values yields different kinds of orderings. The info parameter gives the ordering kind and other necessary information about the comparison.

Example:

!s32i = !cir.int<s, 32>

#cmpinfo_partial_ltn1eq0gt1unn127 =
  #cir.cmp3way_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>
#cmpinfo_strong_ltn1eq0gt1 =
  #cir.cmp3way_info<strong, lt = -1, eq = 0, gt = 1>

%0 = cir.const #cir.int<0> : !s32i
%1 = cir.const #cir.int<1> : !s32i
%2 = cir.cmp3way #cmpinfo_strong_ltn1eq0gt1 %0, %1 : !s32i -> !s8i

%3 = cir.const #cir.fp<0.0> : !cir.float
%4 = cir.const #cir.fp<1.0> : !cir.float
%5 = cir.cmp3way #cmpinfo_partial_ltn1eq0gt1unn127 %3, %4 : !cir.float -> !s8i

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.46.1. Attributes:

AttributeMLIR TypeDescription
info::cir::CmpThreeWayInfoAttrHolds information about a three-way comparison operation

1.1.46.2. Operands:

Operand

Description

lhs

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

rhs

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.46.3. Results:

Result

Description

result

signed integer type

1.1.47. cir.co_return (::cir::CoReturnOp)

Coroutine return operation

Syntax:

operation ::= `cir.co_return` attr-dict

The cir.co_return operation models a coroutine return point inside a cir.coro.body region. This operation is expected to appear only within a cir.coro.body region, but it may be nested within other operations or regions inside that body.

Traits: AlwaysSpeculatableImplTrait, HasAncestor<CoroBodyOp>, ReturnLike, Terminator

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), RegionBranchTerminatorOpInterface

Effects: MemoryEffects::Effect{}

1.1.48. cir.complex.add (::cir::ComplexAddOp)

Complex addition

Syntax:

operation ::= `cir.complex.add` $lhs `,` $rhs `:` qualified(type($result)) attr-dict

The cir.complex.add operation takes two complex numbers and returns their sum.

Example:

%2 = cir.complex.add %0, %1 : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.48.1. Operands:

Operand

Description

lhs

CIR complex type

rhs

CIR complex type

1.1.48.2. Results:

Result

Description

result

CIR complex type

1.1.49. cir.complex.conj (::cir::ComplexConjOp)

Complex conjugate

Syntax:

operation ::= `cir.complex.conj` $operand `:` qualified(type($operand)) attr-dict

The cir.complex.conj operation takes a complex number and returns its complex conjugate, which is formed by negating the imaginary part.

Example:

%1 = cir.complex.conj %0 : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.49.1. Operands:

Operand

Description

operand

CIR complex type

1.1.49.2. Results:

Result

Description

result

CIR complex type

1.1.50. cir.complex.create (::cir::ComplexCreateOp)

Create a complex value from its real and imaginary parts

Syntax:

operation ::= `cir.complex.create` $real `,` $imag
              `:` qualified(type($real)) `->` qualified(type($result)) attr-dict

The cir.complex.create operation takes two operands that represent the real and imaginary part of a complex number, and yields the complex number.

%0 = cir.const #cir.fp<1.000000e+00> : !cir.double
%1 = cir.const #cir.fp<2.000000e+00> : !cir.double
%2 = cir.complex.create %0, %1 : !cir.double -> !cir.complex<!cir.double>

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.50.1. Operands:

Operand

Description

real

integer or floating point type

imag

integer or floating point type

1.1.50.2. Results:

Result

Description

result

CIR complex type

1.1.51. cir.complex.div (::cir::ComplexDivOp)

Complex division

Syntax:

operation ::= `cir.complex.div` $lhs `,` $rhs `range` `(` $range `)` `:` qualified(type($result)) attr-dict

The cir.complex.div operation takes two complex numbers and returns their quotient.

For complex types with floating-point components, the range attribute specifies the algorithm to be used when the operation is lowered to the LLVM dialect. For division, ‘improved’ produces Smith’s algorithms for Complex division with no additional handling for NaN values. If ‘promoted’ is used, the values are promoted to a higher precision type, if possible, and the calculation is performed using the algebraic formula, with no additional handling for NaN values. We fall back on Smith’s algorithm when the target doesn’t support a higher precision type. If ‘full’ is used, a runtime-library function is called if one of the intermediate calculations produced a NaN value. and for ‘basic’ algebraic formula with no additional handling for the NaN value will be used. For integers types range attribute will be ignored.

Example:

%2 = cir.complex.div %0, %1 range(basic) : !cir.complex<!cir.float>
%2 = cir.complex.div %0, %1 range(full) : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.51.1. Attributes:

AttributeMLIR TypeDescription
range::cir::ComplexRangeKindAttrcomplex multiplication and division implementation

1.1.51.2. Operands:

Operand

Description

lhs

CIR complex type

rhs

CIR complex type

1.1.51.3. Results:

Result

Description

result

CIR complex type

1.1.52. cir.complex.imag (::cir::ComplexImagOp)

Extract the imaginary part of a complex value

Syntax:

operation ::= `cir.complex.imag` $operand `:` qualified(type($operand)) `->` qualified(type($result))
              attr-dict

cir.complex.imag operation takes an operand of !cir.complex, !cir.int !cir.bool or !cir.float. If the operand is !cir.complex, the imag part of it will be returned, otherwise a zero value will be returned.

Example:

%imag = cir.complex.imag %complex : !cir.complex<!cir.float> -> !cir.float
%imag = cir.complex.imag %scalar : !cir.float -> !cir.float

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.52.1. Operands:

Operand

Description

operand

complex, integer, boolean or floating point type

1.1.52.2. Results:

Result

Description

result

integer, boolean or floating point type

1.1.53. cir.complex.imag_ptr (::cir::ComplexImagPtrOp)

Derive a pointer to the imaginary part of a complex value

Syntax:

operation ::= `cir.complex.imag_ptr` $operand `:`
              qualified(type($operand)) `->` qualified(type($result)) attr-dict

cir.complex.imag_ptr operation takes a pointer operand that points to a complex value of type !cir.complex and yields a pointer to the imaginary part of the operand.

Example:

%1 = cir.complex.imag_ptr %0 : !cir.ptr<!cir.complex<!cir.double>>
  -> !cir.ptr<!cir.double>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.53.1. Operands:

Operand

Description

operand

pointer to complex type

1.1.53.2. Results:

Result

Description

result

pointer to integer or floating point type

1.1.54. cir.complex.mul (::cir::ComplexMulOp)

Complex multiplication

Syntax:

operation ::= `cir.complex.mul` $lhs `,` $rhs `range` `(` $range `)` `:` qualified(type($result)) attr-dict

The cir.complex.mul operation takes two complex numbers and returns their product.

For complex types with floating-point components, the range attribute specifies the algorithm to be used when the operation is lowered to the LLVM dialect. For multiplication, ‘improved’, ‘promoted’, and ‘basic’ are all handled equivalently, producing the algebraic formula with no special handling for NaN value. If ‘full’ is used, a runtime-library function is called if one of the intermediate calculations produced a NaN value.

Example:

%2 = cir.complex.mul %0, %1 range(basic) : !cir.complex<!cir.float>
%2 = cir.complex.mul %0, %1 range(full) : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.54.1. Attributes:

AttributeMLIR TypeDescription
range::cir::ComplexRangeKindAttrcomplex multiplication and division implementation

1.1.54.2. Operands:

Operand

Description

lhs

CIR complex type

rhs

CIR complex type

1.1.54.3. Results:

Result

Description

result

CIR complex type

1.1.55. cir.complex.real (::cir::ComplexRealOp)

Extract the real part of a complex value

Syntax:

operation ::= `cir.complex.real` $operand `:` qualified(type($operand)) `->` qualified(type($result))
              attr-dict

cir.complex.real operation takes an operand of !cir.complex, cir.int, !cir.bool or !cir.float. If the operand is !cir.complex, the real part of it will be returned, otherwise the value returned unmodified.

Example:

%real = cir.complex.real %complex : !cir.complex<!cir.float> -> !cir.float
%real = cir.complex.real %scalar : !cir.float -> !cir.float

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.55.1. Operands:

Operand

Description

operand

complex, integer, boolean or floating point type

1.1.55.2. Results:

Result

Description

result

integer, boolean or floating point type

1.1.56. cir.complex.real_ptr (::cir::ComplexRealPtrOp)

Derive a pointer to the real part of a complex value

Syntax:

operation ::= `cir.complex.real_ptr` $operand `:`
              qualified(type($operand)) `->` qualified(type($result)) attr-dict

cir.complex.real_ptr operation takes a pointer operand that points to a complex value of type !cir.complex and yields a pointer to the real part of the operand.

Example:

%1 = cir.complex.real_ptr %0 : !cir.ptr<!cir.complex<!cir.double>>
  -> !cir.ptr<!cir.double>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.56.1. Operands:

Operand

Description

operand

pointer to complex type

1.1.56.2. Results:

Result

Description

result

pointer to integer or floating point type

1.1.57. cir.complex.sub (::cir::ComplexSubOp)

Complex subtraction

Syntax:

operation ::= `cir.complex.sub` $lhs `,` $rhs `:` qualified(type($result)) attr-dict

The cir.complex.sub operation takes two complex numbers and returns their difference.

Example:

%2 = cir.complex.sub %0, %1 : !cir.complex<!cir.float>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.57.1. Operands:

Operand

Description

lhs

CIR complex type

rhs

CIR complex type

1.1.57.2. Results:

Result

Description

result

CIR complex type

1.1.58. 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 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.for cond {
  cir.condition(%val) // Branches to `step` region or exits.
} body {
  cir.yield
} step {
  cir.yield
}

cir.await(user, ready : {
  cir.condition(%arg0) // Branches to `resume` or `suspend` region.
}, suspend : {
  [...]
}, resume : {
  [...]
},)

Traits: Terminator

Interfaces: RegionBranchTerminatorOpInterface

1.1.58.1. Operands:

Operand

Description

condition

CIR bool type

1.1.59. cir.const (::cir::ConstantOp)

Create a CIR constant from a literal attribute

Syntax:

operation ::= `cir.const` $value attr-dict

The cir.const operation turns a literal into an SSA value. The data is attached to the operation as an attribute.

  %0 = cir.const #cir.int<4> : !u32i
  %1 = cir.const #cir.fp<1.500000e+00> : !cir.float
  %2 = cir.const #cir.ptr<null> : !cir.ptr<!void>

Traits: AlwaysSpeculatableImplTrait, ConstantLike

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.59.1. Attributes:

AttributeMLIR TypeDescription
value::mlir::TypedAttrTypedAttr instance

1.1.59.2. Results:

Result

Description

res

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.60. cir.construct_catch_param (::cir::ConstructCatchParamOp)

Construct a catch parameter from the in-flight exception

Syntax:

operation ::= `cir.construct_catch_param` $kind $eh_token `to` $param_addr `using` ($copy_fn^)? `:`
              qualified(type($param_addr)) attr-dict

cir.construct_catch_param abstractly represents the target-specific work that must be performed before cir.begin_catch to bind the in-flight exception object to the local alloca used for the catch parameter.

For example: for non-pointer, non-reference catch parameters whose type has a non-trivial copy constructor, the Itanium C++ ABI requires calling __cxa_get_exception_ptr to obtain the adjusted exception pointer and then invoking the catch parameter’s copy constructor to create a local copy of the object before __cxa_begin_catch is invoked.

This operation takes a !cir.eh_token that represents the in-flight exception and the alloca value that is used for the local copy of the exception object. The copy_fn attribute is a flat symbol reference to a cir.func thunk that copies the exception object to a local alloca value.

This operation is replaced with a target-specific representation during the EHABI lowering pass. For some targets, such as the Microsoft ABI, this operation is a no-op and is simply erased during lowering.

Example:

cir.construct_catch_param non_trivial_copy %eh_token to %param_addr
  using @__clang_cir_catch_init_T : !cir.ptr<!rec_T>

Interfaces: SymbolUserOpInterface

1.1.60.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::InitCatchKindAttrallowed 32-bit signless integer cases: 0, 1, 2, 3, 4, 5
copy_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute

1.1.60.2. Operands:

Operand

Description

eh_token

CIR exception handling token type

param_addr

CIR pointer type

1.1.61. cir.continue (::cir::ContinueOp)

C/C++ continue statement equivalent

Syntax:

operation ::= `cir.continue` attr-dict

The cir.continue operation is used to end execution of the current iteration of a loop and resume execution beginning at the next iteration. It is only allowed within loop regions.

Traits: HasAncestor<WhileOp, DoWhileOp, ForOp>, Terminator

1.1.62. cir.copy (::cir::CopyOp)

Copies contents from a CIR pointer to another

Syntax:

operation ::= `cir.copy` $src `to` $dst (`volatile` $is_volatile^)?
              (`skip_tail_padding` $skip_tail_padding^)?
              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 number of bytes copied is inferred from the pointee type. The pointee type of src and dst must match and both must implement the DataLayoutTypeInterface.

The volatile keyword indicates that the operation is volatile.

The skip_tail_padding keyword indicates that only the data bytes should be copied, excluding any tail padding. This is used when copying potentially-overlapping subobjects where the tail padding might be occupied by other objects (e.g. fields marked with [[no_unique_address]]). This is only valid when the pointee type is a record type.

Examples:

  // Copying contents from one record to another:
  cir.copy %0 to %1 : !cir.ptr<!record_ty>

  // Copying without tail padding (for overlapping subobjects):
  cir.copy %0 to %1 skip_tail_padding : !cir.ptr<!record_ty>

Traits: SameTypeOperands

Interfaces: PromotableMemOpInterface

1.1.62.1. Attributes:

AttributeMLIR TypeDescription
is_volatile::mlir::UnitAttrunit attribute
skip_tail_padding::mlir::UnitAttrunit attribute

1.1.62.2. Operands:

Operand

Description

dst

CIR pointer type

src

CIR pointer type

1.1.63. cir.copysign (::cir::CopysignOp)

Copies the sign of a floating-point value

Syntax:

operation ::= `cir.copysign` $lhs `,` $rhs `:` qualified(type($lhs)) attr-dict

cir.copysign returns a value with the magnitude of the first operand and the sign of the second operand.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.63.1. Operands:

Operand

Description

lhs

floating point or vector of floating point type

rhs

floating point or vector of floating point type

1.1.63.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.64. cir.coro.body (::cir::CoroBodyOp)

Region containing the user-authored coroutine body

Syntax:

operation ::= `cir.coro.body` $body attr-dict

The cir.coro.body operation models the region where the user-authored coroutine code is emitted.

This operation serves as a structural boundary separating the coroutine setup and teardown logic (e.g. initial suspend, final suspend, and cleanup) from the user-provided statements inside the coroutine.

The body region contains the code corresponding to the original function body, including co_await and co_return expressions. In particular, cir.co_return operations inside this region mark coroutine exit points and introduce structured control flow that transfers execution to the final suspend point of the coroutine.

Traits: AutomaticAllocationScope, NoRegionArguments, RecursiveMemoryEffects, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

1.1.65. cir.cos (::cir::CosOp)

Computes the floating-point cosine value

Syntax:

operation ::= `cir.cos` $src `:` type($src) attr-dict

cir.cos computes the cosine of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.65.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.65.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.66. cir.cpuid (::cir::CpuIdOp)

Get information about the CPU

Syntax:

operation ::= `cir.cpuid` $cpu_info`,` $function_id`,` $sub_function_id `:`
              qualified(type($cpu_info)) `,`
              type($function_id) `,`
              type($sub_function_id) attr-dict

The cir.cpuid operation retrieves different types of CPU information and stores it in an array of 4 integers.

This operation takes 3 arguments: cpu_info, a pointer to an array of 4 integers; function_id, an integer determining what type of information to be retrieved (for instance, basic information, processor information and features, or cache/TLB information); and sub_function_id, an integer that adds more detail about what information is requested.

As a result, the array of 4 integers is filled with the requested information.

Example:

cir.cpuid %cpui_info, %function_id, %sub_function_id : (!cir.ptr<!s32i>,
    !s32i, !s32i)

1.1.66.1. Operands:

Operand

Description

cpu_info

pointer to 32-bit signed integer

function_id

32-bit signed integer

sub_function_id

32-bit signed integer

1.1.67. cir.ctz (::cir::BitCtzOp)

Get the number of trailing 0-bits in the input

Syntax:

operation ::= `cir.ctz` $input (`poison_zero` $poison_zero^)?
              `:` type($result) attr-dict

Compute the number of trailing 0-bits in the input.

The input integer must be an unsigned integer. The cir.ctz operation counts the number of consecutive 0-bits starting from the least significant bit.

If the poison_zero attribute is present, this operation will have undefined behavior if the input value is 0.

Example:

// %0 = 0b1000
%0 = cir.const #cir.int<8> : !u32i
// %1 will be 3
%1 = cir.ctz %0 poison_zero : !u32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.67.1. Attributes:

AttributeMLIR TypeDescription
poison_zero::mlir::UnitAttrunit attribute

1.1.67.2. Operands:

Operand

Description

input

unsigned integer type of widths 8/16/32/64/128

1.1.67.3. Results:

Result

Description

result

unsigned integer type of widths 8/16/32/64/128

1.1.68. cir.dec (::cir::DecOp)

Decrement an integer by one

Syntax:

operation ::= `cir.dec` (`nsw` $no_signed_wrap^)?
              $input `:` type($input) attr-dict

The cir.dec operation decrements the operand by one. The operand and result must have the same type.

The optional nsw (no signed wrap) attribute indicates that the result is poison if signed overflow occurs.

Example:

%1 = cir.dec %0 : !s32i
%3 = cir.dec nsw %2 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface), UnaryOpInterface

Effects: MemoryEffects::Effect{}

1.1.68.1. Operands:

Operand

Description

input

integer or vector of integer type

1.1.68.2. Results:

Result

Description

result

integer or vector of integer type

1.1.69. cir.delete_array (::cir::DeleteArrayOp)

Delete address representing an array

Syntax:

operation ::= `cir.delete_array` $address `:` qualified(type($address)) (`dtor_may_throw` $dtor_may_throw^)?
              attr-dict

cir.delete_array operation deletes an array. For example, delete[] ptr; will be translated to cir.delete_array %ptr.

The delete_fn attribute specifies the operator delete function to call. The delete_params attribute describes the parameters needed by the operator delete call.

The element_dtor attribute, when present, specifies the destructor to call on each array element before deallocation.

The dtor_may_throw unit property, when present, indicates that the element destructor may throw exceptions.

1.1.69.1. Attributes:

AttributeMLIR TypeDescription
delete_fn::mlir::FlatSymbolRefAttrflat symbol reference attribute
delete_params::cir::UsualDeleteParamsAttrParameters describing the usual operator delete signature
element_dtor::mlir::FlatSymbolRefAttrflat symbol reference attribute

1.1.69.2. Operands:

Operand

Description

address

CIR pointer type

1.1.70. cir.derived_class_addr (::cir::DerivedClassAddrOp)

Get the derived class address for a class/struct

Syntax:

operation ::= `cir.derived_class_addr` $base_addr `:` qualified(type($base_addr))
              (`nonnull` $assume_not_null^)?
              ` ` `[` $offset `]` `->` qualified(type($derived_addr)) attr-dict

The cir.derived_class_addr operaration gets the address of a particular derived class given a non-virtual base class pointer. The offset in bytes of the base class must be passed in, similar to cir.base_class_addr, but going into the other direction. This means lowering to a negative offset.

The operation contains a flag for whether or not the operand may be nullptr. That depends on the context and cannot be known by the operation, and that information affects how the operation is lowered.

The validity of the relationship of derived and base cannot yet be verified. If the target class is not a valid derived class for the object, the behavior is undefined.

Example:

class A {};
class B : public A {};

B *getAsB(A *a) {
  return static_cast<B*>(a);
}

leads to

  %2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
  %3 = cir.base_class_addr %2 : !cir.ptr<!rec_B> [0] -> !cir.ptr<!rec_A>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.70.1. Attributes:

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute
assume_not_null::mlir::UnitAttrunit attribute

1.1.70.2. Operands:

Operand

Description

base_addr

CIR pointer type

1.1.70.3. Results:

Result

Description

derived_addr

CIR pointer type

1.1.71. cir.derived_data_member (::cir::DerivedDataMemberOp)

Cast a base class data member pointer to a derived class data member pointer

Syntax:

operation ::= `cir.derived_data_member` $src `[` $offset `]` `:` qualified(type($src)) `->` qualified(type($result)) attr-dict

The cir.derived_data_member operation casts a data member pointer of type T Base::* to a data member pointer of type T Derived::*, where Base is an accessible non-ambiguous non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.71.1. Attributes:

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

1.1.71.2. Operands:

Operand

Description

src

CIR type that represents a pointer-to-data-member in C++

1.1.71.3. Results:

Result

Description

result

CIR type that represents a pointer-to-data-member in C++

1.1.72. cir.derived_method (::cir::DerivedMethodOp)

Cast a base class pointer-to-member-function to a derived class pointer-to-member-function

Syntax:

operation ::= `cir.derived_method` $src `[` $offset `]` `:` qualified(type($src))
              `->` qualified(type($result)) attr-dict

The cir.derived_method operation casts a pointer-to-member-function of type Ret (Base::*)(Args) to a pointer-to-member-function of type Ret (Derived::*)(Args), where Base is a non-virtual base class of Derived.

The offset parameter gives the offset in bytes of the Base base class subobject within a Derived object.

Example:

%1 = cir.derived_method %0 [16] : !cir.method<!cir.func<(!s32i)> in !rec_Base> -> !cir.method<!cir.func<(!s32i)> in !rec_Derived>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.72.1. Attributes:

AttributeMLIR TypeDescription
offset::mlir::IntegerAttrindex attribute

1.1.72.2. Operands:

Operand

Description

src

CIR type that represents C++ pointer-to-member-function type

1.1.72.3. Results:

Result

Description

result

CIR type that represents C++ pointer-to-member-function type

1.1.73. cir.div (::cir::DivOp)

Integer division

Syntax:

operation ::= `cir.div` $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.div operation performs division on integer operands. Both operands and the result must have the same integer or vector-of-integer type.

Example:

%0 = cir.div %a, %b : !s32i
%1 = cir.div %a, %b : !u32i
%2 = cir.div %va, %vb : !cir.vector<4 x !s32i>

Traits: SameOperandsAndResultType

Interfaces: BinaryOpInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.73.1. Operands:

Operand

Description

lhs

integer or vector of integer type

rhs

integer or vector of integer type

1.1.73.2. Results:

Result

Description

result

integer or vector of integer type

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

1.1.75. cir.dyn_cast (::cir::DynamicCastOp)

Perform dynamic cast on record pointers

Syntax:

operation ::= `cir.dyn_cast` $kind (`relative_layout` $relative_layout^)? $src
              `:` qualified(type($src)) `->` qualified(type($result))
              (qualified($info)^)? attr-dict

The cir.dyn_cast operation models part of the semantics of the dynamic_cast operator in C++. It can be used to perform 3 kinds of casts on record pointers:

  • Down-cast, which casts a base class pointer to a derived class pointer;

  • Side-cast, which casts a class pointer to a sibling class pointer;

  • Cast-to-complete, which casts a class pointer to a void pointer.

The input of the operation must be a record pointer. The result of the operation is either a record pointer or a void pointer.

The parameter kind specifies the semantics of this operation. If its value is ptr, then the operation models dynamic casts on pointers. Otherwise, if its value is ref, the operation models dynamic casts on references. Specifically:

  • When the input pointer is a null pointer value:

    • If kind is ref, the operation will invoke undefined behavior. A sanitizer check will be emitted if sanitizer is on.

    • Otherwise, the operation will return a null pointer value as its result.

  • When the runtime type check fails:

    • If kind is ref, the operation will throw a bad_cast exception.

    • Otherwise, the operation will return a null pointer value as its result.

The info argument gives detailed information about the requested dynamic cast operation. It is an optional #cir.dyn_cast_info attribute that is only present when the operation models a down-cast or a side-cast.

The relative_layout argument specifies whether the Itanium C++ ABI vtable uses relative layout. It is only meaningful when the operation models a cast-to-complete operation.

Examples:

%0 = cir.dyn_cast ptr %p : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
%1 = cir.dyn_cast ptr relative_layout %p : !cir.ptr<!rec_Base>
          -> !cir.ptr<!rec_Derived>
%2 = cir.dyn_cast ref %r : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived>
          #cir.dyn_cast_info<
            srcRtti = #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>,
            destRtti = #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>,
            runtimeFunc = @__dynamic_cast,
            badCastFunc = @__cxa_bad_cast,
            offsetHint = #cir.int<0> : !s64i
          >

1.1.75.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::DynamicCastKindAttrdynamic cast kind
info::cir::DynamicCastInfoAttrABI specific information about a dynamic cast
relative_layout::mlir::UnitAttrunit attribute

1.1.75.2. Operands:

Operand

Description

src

pointer to record type

1.1.75.3. Results:

Result

Description

result

pointer to any of CIR void type, CIR struct/class type, CIR union type

1.1.76. cir.eh.dispatch (::cir::EhDispatchOp)

Dispatch to exception handlers based on exception type

Syntax:

operation ::= `cir.eh.dispatch` $eh_token `:` type($eh_token)
              custom<EhDispatchDestinations>($catch_types, $catch_destinations,
              $default_destination, $default_is_catch_all)
              attr-dict

cir.eh.dispatch is a terminator operation that dispatches control flow based on the type of the in-flight exception. It takes an !cir.eh_token as input and branches to an eh handler block based on the exception type.

The operation contains a list of handlers specified as type-block pairs, plus either a catch_all handler or an unwind handler, which continues unwinding if no catch handler matches. Exactly one of catch_all or unwind must be present.

When the type of the in-flight exception matches a type handler, control is transfered to the corresponding block with the eh_token as an argument. The catch_all handler, if present, catches any exception not matched by another type handler. The unwind handler is used when no handler is matched.

Example:

cir.eh.dispatch %eh_token : !cir.eh_token [
  catch (#cir.global_view<@_ZTIi> : !cir.ptr<!u8i>) : ^catch_int,
  catch (#cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>) : ^catch_str,
  catch_all : ^catch_all
]

cir.eh.dispatch %eh_token : !cir.eh_token [
  catch (#cir.global_view<type @_ZTIi> : !cir.ptr<!u8i>) : ^catch_int,
  unwind : ^continue_unwind
]

Traits: Terminator

1.1.76.1. Attributes:

AttributeMLIR TypeDescription
catch_types::mlir::ArrayAttrarray attribute
default_is_catch_all::mlir::UnitAttrunit attribute

1.1.76.2. Operands:

Operand

Description

eh_token

CIR exception handling token type

1.1.76.3. Successors:

Successor

Description

default_destination

any successor

catch_destinations

any successor

1.1.77. cir.eh.inflight_exception (::cir::EhInflightOp)

Materialize the catch clause formal parameter

Syntax:

operation ::= `cir.eh.inflight_exception` (`cleanup` $cleanup^)?
              (`catch_all` $catch_all^)?
              ($catch_type_list^)?
              attr-dict

cir.eh.inflight_exception returns two values:

  • exception_ptr: The exception pointer for the inflight exception

  • type_id: the type info index for the exception type This operation is expected to be the first operation in the unwind destination basic blocks of a cir.try_call operation.

The cleanup attribute indicates that clean up code must be run before the values produced by this operation are used to dispatch the exception. This cleanup code must be executed even if the exception is not caught. This helps CIR to pass down more accurate information for LLVM lowering to landingpads.

The catch_all attribute indicates that a catch-all handler exists for the exception being dispatched. When lowered to LLVM IR, this results in a catch ptr null clause on the landing pad. When catch_all is present alongside typed catches, the landing pad will contain both the typed catch clauses and a trailing catch ptr null.

Example:

%exception_ptr, %type_id = cir.eh.inflight_exception
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
%exception_ptr, %type_id = cir.eh.inflight_exception cleanup
%exception_ptr, %type_id = cir.eh.inflight_exception catch_all [@_ZTIi]
``

Interfaces: `InferTypeOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>cleanup</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>catch_all</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>catch_type_list</code></td><td>::mlir::ArrayAttr</td><td>flat symbol ref array attribute</td></tr>
</table>

#### Results:

| Result | Description |
| :----: | ----------- |
| `exception_ptr` | pointer to void type |
| `type_id` | 32-bit unsigned integer |



### `cir.eh.initiate` (::cir::EhInitiateOp)

_Initiate exception handling in flattened CIR_

Syntax:

operation ::= cir.eh.initiate (cleanup $cleanup^)? : type($eh_token) attr-dict


`cir.eh.initiate` is the first operation in the unwind destination of a
`cir.try_call` operation after CFG flattening. It returns an opaque
`!cir.eh_token` that represents the in-flight exception.

The `cleanup` attribute indicates that cleanup code must be executed before
the exception is dispatched to any handlers. When present, the operation
will be followed by cleanup code before branching to a `cir.eh.dispatch`
operation.

The returned token is passed to `cir.begin_cleanup`, `cir.begin_catch`,
or `cir.eh.dispatch` operations.

Example:

^unwind:

cir.br ^dispatch(%eh_token : !cir.eh_token)

^unwind_with_cleanup:

cir.br ^cleanup(%eh_token : !cir.eh_token)


Interfaces: `InferTypeOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>cleanup</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Results:

| Result | Description |
| :----: | ----------- |
| `eh_token` | CIR exception handling token type |



### `cir.eh.longjmp` (::cir::EhLongjmpOp)

_CIR longjmp operation_

Syntax:

operation ::= cir.eh.longjmp $env : qualified(type($env)) attr-dict


Restore the environment (e.g., stack pointer, instruction pointer,
signal mask, and other registers) at the time of setjmp() call, by using
the information saved in `env` by setjmp().

Examples:

cir.eh.longjmp %arg0 : !cir.ptr<!cir.void>


#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `env` | CIR pointer type |



### `cir.eh.setjmp` (::cir::EhSetjmpOp)

_CIR setjmp operation_

Syntax:

operation ::= cir.eh.setjmp $env : functional-type($env, results) attr-dict


Saves call-site information (e.g., stack pointer, instruction pointer, 
signal mask, and other registers) in memory at `env` for use by longjmp(). 
In this case, setjmp() returns 0. Following a successful longjmp(),
execution proceeds from cir.eh.setjmp with the operation yielding a 
non-zero value.

Examples:

Interfaces: `InferTypeOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `env` | CIR pointer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `res` | 32-bit signed integer |



### `cir.eh.terminate` (::cir::EhTerminateOp)

_Terminate due to exception thrown during cleanup_

Syntax:

operation ::= cir.eh.terminate $eh_token : type($eh_token) attr-dict


`cir.eh.terminate` terminates program execution when an exception is thrown
while executing cleanup code during exception unwinding. The C++ standard
requires that `std::terminate()` be called in this scenario.

This operation takes an `!cir.eh_token` from a `cir.eh.initiate` operation
and acts as a terminator. It is produced during CFG flattening when throwing
calls are found in EH cleanup regions.

During EH ABI lowering, this is replaced with target-specific termination
code. For the Itanium ABI, the `cir.eh.initiate` is lowered to
`cir.eh.inflight_exception` (producing an exception pointer), and the
`cir.eh.terminate` becomes a call to `__clang_call_terminate` with that
pointer, followed by an unreachable operation.

Example:

^terminate_unwind:

cir.eh.terminate %eh_token : !cir.eh_token


Traits: `Terminator`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `eh_token` | CIR exception handling token type |



### `cir.eh.typeid` (::cir::EhTypeIdOp)

_Compute exception type id from its global type symbol_

Syntax:

operation ::= cir.eh.typeid $type_sym attr-dict


Returns the exception type id for a given global symbol representing
a type.

Example:

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`, `SymbolUserOpInterface`

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>type_sym</code></td><td>::mlir::FlatSymbolRefAttr</td><td>flat symbol reference attribute</td></tr>
</table>

#### Results:

| Result | Description |
| :----: | ----------- |
| `type_id` | 32-bit unsigned integer |



### `cir.end_catch` (::cir::EndCatchOp)

_End a catch handler_

Syntax:

operation ::= cir.end_catch $catch_token : type($catch_token) attr-dict


`cir.end_catch` marks the end of a catch handler. It takes the
`!cir.catch_token` returned by the corresponding `cir.begin_catch`
operation.

In the high-level CIR representation, this operation appears inside
the cleanup region of the `cir.cleanup.scope` that follows
`cir.begin_catch` in a catch handler region. In the flattened CIR
representation, it appears at the end of a path that exits the catch
handler.

Example:

// High-level form (inside cir.try catch handler region): } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) {

: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)

cir.cleanup.scope { // Handle exception… cir.yield } cleanup eh { cir.end_catch %catch_token : !cir.catch_token cir.yield } }

// Flattened form: ^catch_int(%eh_token : !cir.eh_token):

: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)

// Handle exception… cir.end_catch %catch_token : !cir.catch_token cir.br ^continue


#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `catch_token` | CIR catch token type |



### `cir.end_cleanup` (::cir::EndCleanupOp)

_End a cleanup block during exception unwinding_

Syntax:

operation ::= cir.end_cleanup $cleanup_token : type($cleanup_token) attr-dict


`cir.end_cleanup` marks the end of a cleanup block during exception
unwinding. It takes the `!cir.cleanup_token` returned by the corresponding
`cir.begin_cleanup` operation.

After the cleanup is complete, control typically transfers to either a
catch dispatch block or continues unwinding via `cir.resume`.

Example:

^cleanup(%eh_token : !cir.eh_token):

                                           -> !cir.cleanup_token

cir.call @destructor() : () -> () cir.end_cleanup %cleanup_token : !cir.cleanup_token cir.br ^dispatch(%eh_token : !cir.eh_token)


#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `cleanup_token` | CIR cleanup token type |



### `cir.exp` (::cir::ExpOp)

_Computes the floating-point base-e exponential value_

Syntax:

operation ::= cir.exp $src : type($src) attr-dict


`cir.exp` computes the exponential of a floating-point operand and returns
a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.exp2` (::cir::Exp2Op)

_Computes the floating-point base-2 exponential value_

Syntax:

operation ::= cir.exp2 $src : type($src) attr-dict


`cir.exp2` computes the base-2 exponential of a floating-point operand and
 returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.expect` (::cir::ExpectOp)

_Tell the optimizer that two values are likely to be equal._

Syntax:

operation ::= cir.expect ( $val, $expected (, $prob^)? ) : type($val) attr-dict


The `cir.expect` operation may take 2 or 3 arguments.

When the argument `prob` is missing, this operation effectively models the
`__builtin_expect` builtin function. It tells the optimizer that `val` and
`expected` are likely to be equal.

When the argument `prob` is present, this operation effectively models the
`__builtin_expect_with_probability` builtin function. It tells the
optimizer that `val` and `expected` are equal to each other with a certain
probability.

`val` and `expected` must be integers and their types must match.

The result of this operation is always equal to `val`.

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>prob</code></td><td>::mlir::FloatAttr</td><td>64-bit float attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `val` | fundamental integer type |
| `expected` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | fundamental integer type |



### `cir.extract_member` (::cir::ExtractMemberOp)

_Extract the value of a member of a record value_

Syntax:

operation ::= cir.extract_member $record [ $index ] attr-dict : qualified(type($record)) -> qualified(type($result))


The `cir.extract_member` operation extracts the value of a particular member
from the input record. Unlike `cir.get_member` which derives pointers, this
operation operates on values. It takes a value of record type and extracts
the value of the specified record member from the input record value.

Currently `cir.extract_member` does not work on unions.

Example:

// Suppose we have a record with multiple members. !s32i = !cir.int<s, 32> !s8i = !cir.int<s, 32> !record_ty = !cir.record<”struct.Bar” {!s32i, !s8i}>

// And suppose we have a value of the record type.

                          #cir.int<2> : !s8i}> : !record_ty

// Extract the value of the second member of the record.


Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>index</code></td><td>::mlir::IntegerAttr</td><td>64-bit signless integer attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `record` | CIR record type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.fabs` (::cir::FAbsOp)

_Computes the floating-point absolute value_

Syntax:

operation ::= cir.fabs $src : type($src) attr-dict


`cir.fabs` computes the absolute value of a floating-point operand
and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fadd` (::cir::FAddOp)

_Floating-point addition_

Syntax:

operation ::= cir.fadd $lhs , $rhs : type($lhs) attr-dict


The `cir.fadd` operation performs floating-point addition on its operands.
Both operands and the result must have the same floating-point scalar or
vector-of-float type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fdiv` (::cir::FDivOp)

_Floating-point division_

Syntax:

operation ::= cir.fdiv $lhs , $rhs : type($lhs) attr-dict


The `cir.fdiv` operation performs floating-point division on its operands.
Both operands and the result must have the same floating-point scalar or
vector-of-float type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.ffs` (::cir::BitFfsOp)

_Get the position of the least significant 1-bit in input_

Syntax:

operation ::= cir.ffs $input : type($result) attr-dict


Compute the 1-based position of the least significant 1-bit of the input.

The input integer must be a signed integer. The `cir.ffs` operation returns
one plus the index of the least significant 1-bit of the input signed
integer. If the input integer is 0, `cir.ffs` yields 0.

Example:

!s32i = !cir.int<s, 32>

// %0 = 0x0010_1000

// #1 will be 4 since the 4th least significant bit is 1.


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | signed integer type of widths 32/64 |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | signed integer type of widths 32/64 |



### `cir.floor` (::cir::FloorOp)

_Computes the floating-point floor value_

Syntax:

operation ::= cir.floor $src : type($src) attr-dict


`cir.floor` computes the floor of a floating-point operand and returns
a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Example:

// $x : !cir.double


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fmaximum` (::cir::FMaximumOp)

_Returns the larger of two floating-point values (IEEE 754-2019)_

Syntax:

operation ::= cir.fmaximum $lhs , $rhs : qualified(type($lhs)) attr-dict


`cir.fmaximum` returns the larger of its two operands according to
IEEE 754-2019 semantics. If either operand is NaN, NaN is returned.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fmaxnum` (::cir::FMaxNumOp)

_Returns the larger of two floating-point values_

Syntax:

operation ::= cir.fmaxnum $lhs , $rhs : qualified(type($lhs)) attr-dict


`cir.fmaxnum` returns the larger of its two operands. If one operand is
NaN, the other operand is returned.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fminimum` (::cir::FMinimumOp)

_Returns the smaller of two floating-point values (IEEE 754-2019)_

Syntax:

operation ::= cir.fminimum $lhs , $rhs : qualified(type($lhs)) attr-dict


`cir.fminimum` returns the smaller of its two operands according to
IEEE 754-2019 semantics. If either operand is NaN, NaN is returned.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fminnum` (::cir::FMinNumOp)

_Returns the smaller of two floating-point values_

Syntax:

operation ::= cir.fminnum $lhs , $rhs : qualified(type($lhs)) attr-dict


`cir.fminnum` returns the smaller of its two operands. If one operand is
NaN, the other operand is returned.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fmod` (::cir::FModOp)

_Computes the floating-point remainder_

Syntax:

operation ::= cir.fmod $lhs , $rhs : qualified(type($lhs)) attr-dict


`cir.fmod` computes the floating-point remainder of dividing the first
operand by the second operand.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fmul` (::cir::FMulOp)

_Floating-point multiplication_

Syntax:

operation ::= cir.fmul $lhs , $rhs : type($lhs) attr-dict


The `cir.fmul` operation performs floating-point multiplication on its
operands. Both operands and the result must have the same floating-point
scalar or vector-of-float type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.fneg` (::cir::FNegOp)

_Floating-point negation_

Syntax:

operation ::= cir.fneg $input : type($input) attr-dict


The `cir.fneg` operation negates the operand. The operand and result must
have the same type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`, `UnaryOpInterface`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `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.frame_address` (::cir::FrameAddrOp)

_The frame address of the current function, or of one of its callers_

Syntax:

operation ::= cir.frame_address ( $level ) attr-dict : qualified(type($result))


Represents a call to builtin function ` __builtin_frame_address` in CIR.
This builtin function returns the frame address of the current function,
or of one of its callers. The frame is the area on the stack that holds
local variables and saved registers. The frame address is normally the
address of the first word pushed on to the stack by the function.
However, the exact definition depends upon the processor and the calling
convention. If the processor has a dedicated frame pointer register, and
the function has a frame, then __builtin_frame_address returns the value of
the frame pointer register.

The `level` argument is number of frames to scan up the call stack.
For instance, value of 0 yields the frame address of the current function,
value of 1 yields the frame address of the caller of the current function,
and so forth.

Examples:


#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `level` | 32-bit unsigned integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR pointer type |



### `cir.frem` (::cir::FRemOp)

_Floating-point remainder_

Syntax:

operation ::= cir.frem $lhs , $rhs : type($lhs) attr-dict


The `cir.frem` operation computes the floating-point remainder of its
operands. Both operands and the result must have the same floating-point
scalar or vector-of-float type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.frexp` (::cir::FrexpOp)

_Decomposes a floating-point value into significand and exponent_

Syntax:

operation ::= cir.frexp $src : type($src) -> type($result) , type($exp) attr-dict


`cir.frexp` splits a floating-point value into a normalized significand
(in the range [0.5, 1.0)) and an integral power-of-two exponent, such
that `src = significand * 2^exp`.  Returns both as separate results.

Lowers to `llvm.frexp`.

Example:
  %sig, %exp = cir.frexp %x : !cir.float -> !cir.float, !s32i

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |
| `exp` | integer type |



### `cir.fsub` (::cir::FSubOp)

_Floating-point subtraction_

Syntax:

operation ::= cir.fsub $lhs , $rhs : type($lhs) attr-dict


The `cir.fsub` operation performs floating-point subtraction on its
operands. Both operands and the result must have the same floating-point
scalar or vector-of-float type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.func` (::cir::FuncOp)

_Declare or define a function_

The `cir.func` operation defines a function, similar to the `mlir::FuncOp`
built-in.

The function linkage information is specified by `linkage`, as defined by
`GlobalLinkageKind` attribute.

The `calling_conv` attribute specifies the calling convention of the function.
By default calling convention is `CallingConv::C`. When printed, C calling
convention is omitted. Other calling conventions are printed as `cc(<mnemonic>)`,
e.g. `cc(amdgpu_kernel)`.

A compiler builtin function must be marked as `builtin` for further
processing when lowering from CIR.

The `coroutine` keyword is used to mark a 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 `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 `global_ctor` keyword indicates whether a function should execute before
`main()` function, as specified by `__attribute__((constructor))`. An
execution priority can also be specified `global_ctor(<priority>)`.
Similarly, for global destructors both `global_dtor` and
`global_dtor(<priority>)` are available.

The `no_inline` attribute marks a function that should not be inlined.
The `always_inline` attribute marks a function that should always be inlined.
The `inline_hint` attribute suggests that the function should be inlined.

The `personality` attribute specifies the personality function to use for
exception handling. This is a symbol reference to the personality function
(e.g., `@__gxx_personality_v0` for C++ exceptions).

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(…)

// Calling convention information cir.func @func1(…) cc(amdgpu_kernel)

// Inline information cir.func no_inline @some_method(…)

// Builtin function cir.func builtin @__builtin_coro_end(!cir.ptr, !cir.bool) -> !cir.bool // Coroutine cir.func coroutine @_Z10silly_taskv() -> !CoroTask { … cir.await(…) … }


Traits: `AutomaticAllocationScope`, `IsolatedFromAbove`

Interfaces: `ArgAndResultAttrsOpInterface`, `CIRGlobalValueInterface`, `CallableOpInterface`, `FunctionOpInterface`, `Symbol`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>sym_name</code></td><td>::mlir::StringAttr</td><td>string attribute</td></tr>
<tr><td><code>function_type</code></td><td>::mlir::TypeAttr</td><td>type attribute of CIR function type</td></tr>
<tr><td><code>builtin</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>coroutine</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>inline_kind</code></td><td>::cir::InlineKindAttr</td><td>inlineKind</td></tr>
<tr><td><code>lambda</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>no_proto</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>dso_local</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>linkage</code></td><td>::cir::GlobalLinkageKindAttr</td><td>linkage kind</td></tr>
<tr><td><code>calling_conv</code></td><td>::cir::CallingConvAttr</td><td>calling convention</td></tr>
<tr><td><code>sym_visibility</code></td><td>::mlir::StringAttr</td><td>string attribute</td></tr>
<tr><td><code>comdat</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>arg_attrs</code></td><td>::mlir::ArrayAttr</td><td>Array of dictionary attributes</td></tr>
<tr><td><code>res_attrs</code></td><td>::mlir::ArrayAttr</td><td>Array of dictionary attributes</td></tr>
<tr><td><code>aliasee</code></td><td>::mlir::FlatSymbolRefAttr</td><td>flat symbol reference attribute</td></tr>
<tr><td><code>side_effect</code></td><td>::cir::SideEffectAttr</td><td>allowed side effects of a function</td></tr>
<tr><td><code>personality</code></td><td>::mlir::FlatSymbolRefAttr</td><td>flat symbol reference attribute</td></tr>
<tr><td><code>global_ctor_priority</code></td><td>::mlir::IntegerAttr</td><td>32-bit signless integer attribute whose minimum value is 101 whose maximum value is 65535</td></tr>
<tr><td><code>global_dtor_priority</code></td><td>::mlir::IntegerAttr</td><td>32-bit signless integer attribute whose minimum value is 101 whose maximum value is 65535</td></tr>
<tr><td><code>cxx_special_member</code></td><td>::mlir::Attribute</td><td>Marks a function as a C++ constructor or Marks a function as a CXX destructor or Marks a function as a CXX assignment operator</td></tr>
<tr><td><code>annotations</code></td><td>::mlir::ArrayAttr</td><td>array of cir.annotation attributes</td></tr>
</table>



### `cir.get_bitfield` (::cir::GetBitfieldOp)

_Get the information for a bitfield member_

Syntax:

operation ::= cir.get_bitfield (align ( $alignment^ ))? ($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.

cir.get_bitfield(#bfi, %0 {is_volatile} : !cir.ptr<!u64i>) -> !s32i


Example:
Suppose we have a struct with multiple bitfields stored in
different members. The `cir.get_bitfield` operation gets the value
of the bitfield.
```C++
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.e;
}
// 'e' is in the storage with the index 1
!cir.record<struct "S" packed padded {!u64i, !u16i, !cir.array<!u8i x 2>}>
#bfi_e = #cir.bitfield_info<name = "e", storage_type = !u16i, size = 15,
                            offset = 0, is_signed = true>

%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
%3 = cir.get_member %2[1] {name = "e"} : !cir.ptr<!record_type>
                                                         -> !cir.ptr<!u16i>
%4 = cir.get_bitfield align(4) (#bfi_e, %3 : !cir.ptr<!u16i>) -> !s32i

1.1.77.1. Attributes:

AttributeMLIR TypeDescription
bitfield_info::cir::BitfieldInfoAttrRepresents info for a bit-field member
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

1.1.77.2. Operands:

Operand

Description

addr

CIR pointer type

1.1.77.3. Results:

Result

Description

result

integer or boolean type

1.1.78. cir.get_element (::cir::GetElementOp)

Get the address of an array element

Syntax:

operation ::= `cir.get_element` $base`[` $index `:` type($index) `]` attr-dict
              `:` qualified(type($base)) `->` qualified(type($result))

The cir.get_element operation gets the address of a particular element from the base array.

It expects a pointer to the base array and the index of the element. The result pointer preserves the address space of the base pointer.

Example:

// Suppose we have a array.
!s32i = !cir.int<s, 32>
!arr_ty = !cir.array<!s32i x 4>

// Get the address of the element at index 1.
%elem_1 = cir.get_element %0[1 : !s32i] : !cir.ptr<!array_ty> -> !cir.ptr<!s32i>

// Get the address of the element at index %i.
%i = ...
%elem_i = cir.get_element %0[%i : !s32i] : !cir.ptr<!array_ty> -> !cir.ptr<!s32i>

// With address space (e.g., GPU private memory):
%elem_gpu = cir.get_element %gpu_arr[%i : !s32i] :
  !cir.ptr<!cir.array<!s32i x 10>, target_address_space(5)> ->
  !cir.ptr<!s32i, target_address_space(5)>

Interfaces: InferTypeOpInterface

1.1.78.1. Operands:

Operand

Description

base

pointer to array type

index

fundamental integer type

1.1.78.2. Results:

Result

Description

result

CIR pointer type

1.1.79. cir.get_global (::cir::GetGlobalOp)

Get the address of a global variable

Syntax:

operation ::= `cir.get_global` (`thread_local` $tls^)?
              (`static_local` $static_local^)?
              $name `:` qualified(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. The resulting type must always be a !cir.ptr<...> type with the same address space as the global variable.

Addresses of thread local globals can only be retrieved if this operation is marked thread_local, which indicates the address isn’t constant.

The static_local attribute indicates that this global is a function-local static variable that requires guarded initialization (e.g., C++ static local variables with non-constant initializers).

Example:

%x = cir.get_global @gv : !cir.ptr<i32>
...
%y = cir.get_global thread_local @tls_gv : !cir.ptr<i32>
...
%w = cir.get_global static_local @func_static : !cir.ptr<i32>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface

Effects: MemoryEffects::Effect{}

1.1.79.1. Attributes:

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute
tls::mlir::UnitAttrunit attribute
static_local::mlir::UnitAttrunit attribute

1.1.79.2. Results:

Result

Description

addr

CIR pointer type

1.1.80. cir.get_member (::cir::GetMemberOp)

Get the address of a member of a record

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 record with multiple members.
!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 8>
!ty_B = !cir.record<"struct.B" {!s32i, !s8i}>

// Get the address of the member at index 1.
%1 = cir.get_member %0[1] {name = "i"} : (!cir.ptr<!ty_B>) -> !cir.ptr<!s8i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.80.1. Attributes:

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

1.1.80.2. Operands:

Operand

Description

addr

CIR pointer type

1.1.80.3. Results:

Result

Description

result

CIR pointer type

1.1.81. cir.get_method (::cir::GetMethodOp)

Resolve a method to a function pointer as callee

Syntax:

operation ::= `cir.get_method` $method `,` $object
              `:` `(` qualified(type($method)) `,` qualified(type($object)) `)`
              `->` `(` qualified(type($callee)) `,` qualified(type($adjusted_this)) `)`
              attr-dict

The cir.get_method operation takes a pointer to method (!cir.method) and a pointer to a class object (!cir.ptr<!cir.record>>) as input, and yields a function pointer that points to the actual function corresponding to the input method. The operation also applies any necessary adjustments to the input object pointer for calling the method and yields the adjusted pointer.

This operation is generated when calling a method through a pointer-to- member-function in C++:

// Foo *object;
// int arg;
// void (Foo::*method)(int);

(object->*method)(arg);

The code above will generate CIR similar to:

%callee, %this = cir.get_method %method, %object
cir.call %callee(%this, %arg)

The method type must match the callee type. That is:

  • The return type of the method must match the return type of the callee.

  • The first parameter of the callee must have type !cir.ptr<!cir.void>.

  • Types of other parameters of the callee must match the method’s parameters after the implicit this pointer.

1.1.81.1. Operands:

Operand

Description

method

CIR type that represents C++ pointer-to-member-function type

object

pointer to record type

1.1.81.2. Results:

Result

Description

callee

pointer to function type

adjusted_this

pointer to void type

1.1.82. cir.get_runtime_member (::cir::GetRuntimeMemberOp)

Get the address of a member of a record

Syntax:

operation ::= `cir.get_runtime_member` $addr `[` $member `:` qualified(type($member)) `]` attr-dict
              `:` qualified(type($addr)) `->` qualified(type($result))

The cir.get_runtime_member operation gets the address of a member from the input record. The target member is given by a value of type !cir.data_member (i.e. a pointer-to-data-member value).

This operation differs from cir.get_member in when the target member can be determined. For the cir.get_member operation, the target member is specified as a constant index so the member it returns access to is known when the operation is constructed. For the cir.get_runtime_member operation, the target member is given through a pointer-to-data-member value which is unknown until the program being compiled is executed. In other words, cir.get_member represents a normal member access through the . operator in C/C++:

struct Foo { int x; };
Foo f;
(void)f.x;  // cir.get_member

And cir.get_runtime_member represents a member access through the .* or the ->* operator in C++:

struct Foo { int x; }
Foo f;
Foo *p;
int Foo::*member;

(void)f.*member;   // cir.get_runtime_member
(void)p->*member;  // cir.get_runtime_member

This operation expects a pointer to the base record as well as the pointer to the target member.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.82.1. Operands:

Operand

Description

addr

pointer to record type

member

CIR type that represents a pointer-to-data-member in C++

1.1.82.2. Results:

Result

Description

result

CIR pointer type

1.1.83. cir.global (::cir::GlobalOp)

Declare or define a global variable

Syntax:

operation ::= `cir.global` ($sym_visibility^)?
              ($global_visibility^)?
              (`constant` $constant^)?
              $linkage
              (`comdat` $comdat^)?
              ($tls_model^)?
              (`dyn_tls_refs` `=` $dyn_tls_refs^)?
              (`dso_local` $dso_local^)?
              (`static_local_guard` `` $static_local_guard^)?
              (` ` custom<GlobalAddressSpaceValue>($addr_space)^ )?
              $sym_name
              (`alias` `(` $aliasee^ `)`)?
              custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value,
              $ctorRegion, $dtorRegion)
              ($annotations^)?
              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 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.

The static_local_guard attribute indicates that this global represents a function-local static variable that requires guarded initialization (e.g., C++ static local variables with non-constant initializers). It contains the mangled name of the guard variable.

Traits: NoRegionArguments

Interfaces: CIRGlobalValueInterface, RegionBranchOpInterface, Symbol

1.1.83.1. Attributes:

AttributeMLIR TypeDescription
sym_name::mlir::StringAttrstring attribute
sym_visibility::mlir::StringAttrstring attribute
sym_type::mlir::TypeAttrany type attribute
linkage::cir::GlobalLinkageKindAttrlinkage kind
addr_space::mlir::ptr::MemorySpaceAttrInterfaceMemorySpaceAttrInterface instance
tls_model::cir::TLS_ModelAttrTLS model
dyn_tls_refs::cir::ThreadLocalGlobalWrapperInitAttrWrapper and Init function names for thread local variables
initial_value::mlir::Attributeany attribute
static_local_guard::cir::StaticLocalGuardAttrGuard variable name for static local variables
alignment::mlir::IntegerAttr64-bit signless integer attribute
ast::cir::ASTVarDeclInterfaceASTVarDeclInterface instance
section::mlir::StringAttrstring attribute
annotations::mlir::ArrayAttrarray of cir.annotation attributes
aliasee::mlir::FlatSymbolRefAttrflat symbol reference attribute

1.1.84. cir.goto (::cir::GotoOp)

Syntax:

operation ::= `cir.goto` $label attr-dict

Transfers control to the specified label. This requires a corresponding cir.label to exist and is used by to represent source level gotos that jump across region boundaries. Alternatively, cir.br is used to construct goto’s that don’t violate such boundaries.

cir.goto is completely symbolic (i.e. it “jumps” on a label that isn’t yet materialized) and should be taken into account by passes and analysis when deciding if it’s safe to make some assumptions about a given region or basic block.

Example:

  int test(int x) {
    if (x)
      goto label;
    {
      x = 10;
  label:
      return x;
    }
  }
  cir.scope {  // REGION #1
    %2 = cir.load %0 : !cir.ptr<!s32i>, !s32i
    %3 = cir.cast int_to_bool %2 : !s32i -> !cir.bool
    cir.if %3 {
      cir.goto "label"
    }
    }
    cir.scope {  // REGION #2
      %2 = cir.const #cir.int<10> : !s32i
      cir.store %2, %0 : !s32i, !cir.ptr<!s32i>
      cir.br ^bb1
    ^bb1:  // pred: ^bb0
      cir.label "label"
      %3 = cir.load %0 : !cir.ptr<!s32i>, !s32i
      cir.store %3, %1 : !s32i, !cir.ptr<!s32i>
      %4 = cir.load %1 : !cir.ptr<!s32i>, !s32i
      cir.return %4 : !s32i
    }
    cir.unreachable

Traits: Terminator

1.1.84.1. Attributes:

AttributeMLIR TypeDescription
label::mlir::StringAttrstring attribute

1.1.85. 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 %cond  {
  ...
} else {
  ...
}

cir.if %cond  {
  ...
}

cir.if %cond  {
  ...
  cir.br ^a
^a:
  cir.yield
}

cir.if defines no values and the ‘else’ can be omitted. The if/else regions must be terminated. If the region has only one block, the terminator can be left out, and cir.yield terminator will be inserted implictly. Otherwise, the region must be explicitly terminated.

Traits: AutomaticAllocationScope, NoRegionArguments, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

1.1.85.1. Operands:

Operand

Description

condition

CIR bool type

1.1.86. cir.inc (::cir::IncOp)

Increment an integer by one

Syntax:

operation ::= `cir.inc` (`nsw` $no_signed_wrap^)?
              $input `:` type($input) attr-dict

The cir.inc operation increments the operand by one. The operand and result must have the same type.

The optional nsw (no signed wrap) attribute indicates that the result is poison if signed overflow occurs.

Example:

%1 = cir.inc %0 : !s32i
%3 = cir.inc nsw %2 : !s32i

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface), UnaryOpInterface

Effects: MemoryEffects::Effect{}

1.1.86.1. Operands:

Operand

Description

input

integer or vector of integer type

1.1.86.2. Results:

Result

Description

result

integer or vector of integer type

1.1.87. cir.indirect_br (::cir::IndirectBrOp)

Indirect branch

Syntax:

operation ::= `cir.indirect_br` $addr ( `poison` $poison^ )? `:` qualified(type($addr)) `,`
              custom<IndirectBrOpSucessors>(ref(type($addr)),
              $successors,
              $succ_operands,
              type($succ_operands))
              attr-dict

The cir.indirectbr operation represents an indirect branch to one of several possible successor blocks. The target block is computed from the value of the given address operand.

This operation is typically generated when handling constructs like the GCC extension &&label combined with an indirect goto *ptr;.

The poison attribute is used to mark an indirectbr that was created but is known to be invalid, for instance when a label address was taken but no indirect branch was ever emitted.

Example:

  %0 = cir.block_address <@A, "A"> : !cir.ptr<!void>
  cir.indirectbr %0 poison : <!void>, [
  ^bb1
  ]

Traits: AlwaysSpeculatableImplTrait, SameVariadicOperandSize, Terminator

Interfaces: BranchOpInterface, ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.87.1. Attributes:

AttributeMLIR TypeDescription
poison::mlir::UnitAttrunit attribute
operand_segments::mlir::DenseI32ArrayAttri32 dense array attribute

1.1.87.2. Operands:

Operand

Description

addr

pointer to void type

succ_operands

variadic of any non-token type

1.1.87.3. Successors:

Successor

Description

successors

any successor

1.1.88. cir.init_catch_param (::cir::InitCatchParamOp)

Initialize a catch parameter from the exception pointer

Syntax:

operation ::= `cir.init_catch_param` $kind $exn_ptr `to` $param_addr `:`
              qualified(type($exn_ptr)) `,` qualified(type($param_addr)) attr-dict

cir.init_catch_param represents copying or otherwise materializing the caught exception object into the local catch parameter variable. It takes the exception pointer returned by cir.begin_catch and the address of the alloca created for the catch parameter, and has no result.

This operation is target-independent. It is replaced during EHABI lowering with the appropriate target/ABI-specific sequence (for example, the Itanium C++ ABI may emit a load and store for scalar/pointer catch types, an aggregate copy for record types, or a call to a copy constructor when one is required).

Example:

%catch_token, %exn_ptr = cir.begin_catch %eh_token
  : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
%param_addr = cir.alloca "e" align(4) init : !cir.ptr<!s32i>
cir.init_catch_param %exn_ptr to %param_addr
  : !cir.ptr<!void>, !cir.ptr<!s32i>

1.1.88.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::InitCatchKindAttrallowed 32-bit signless integer cases: 0, 1, 2, 3, 4, 5

1.1.88.2. Operands:

Operand

Description

exn_ptr

CIR pointer type

param_addr

CIR pointer type

1.1.89. cir.insert_member (::cir::InsertMemberOp)

Overwrite the value of a member of a record value

Syntax:

operation ::= `cir.insert_member` $record `[` $index `]` `,` $value attr-dict
              `:` qualified(type($record)) `,` qualified(type($value))

The cir.insert_member operation overwrites the value of a particular member in the input record, and returns the modified record. The result of this operation is equal to the input record, except for the member specified by index_attr whose value is equal to the given value.

This operation is named after the LLVM instruction insertvalue.

Currently cir.insert_member does not work on unions.

Example:

// Suppose we have a record with multiple members.
!s32i = !cir.int<s, 32>
!s8i = !cir.int<s, 32>
!record_ty = !cir.record<"struct.Bar" {!s32i, !s8i}>

// And suppose we have a value of the record type.
%0 = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s8i}> : !record_ty
// %0 is {1, 2}

// Overwrite the second member of the record value.
%1 = cir.const #cir.int<3> : !s8i
%2 = cir.insert_member %0[1], %1 : !record_ty, !s8i
// %2 is {1, 3}

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.89.1. Attributes:

AttributeMLIR TypeDescription
index::mlir::IntegerAttr64-bit signless integer attribute

1.1.89.2. Operands:

Operand

Description

record

CIR record type

value

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.89.3. Results:

Result

Description

result

CIR record type

1.1.90. cir.is_constant (::cir::IsConstantOp)

Test for manifest compile-time constant

Syntax:

operation ::= `cir.is_constant` $val `:` qualified(type($val)) `->` qualified(type($result)) attr-dict

Returns true if the argument is known to be a manifest compile-time constant otherwise returns false. If the argument is a constant expression which refers to a global (the address of which is a constant, but not manifest during the compile), then the intrinsic evaluates to false.

This is used to represent __builtin_constant_p in cases where the argument isn’t known to be constant during initial translation of the source code but might be proven to be constant after later optimizations.

Example:

%1 = cir.is_constant %2 : !s32i -> !cir.bool

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.90.1. Operands:

Operand

Description

val

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.90.2. Results:

Result

Description

result

CIR bool type

1.1.91. cir.is_fp_class (::cir::IsFPClassOp)

Corresponding to the __builtin_fpclassify builtin function in clang

Syntax:

operation ::= `cir.is_fp_class` $src `,` $flags `:` functional-type($src, $result) attr-dict

The cir.is_fp_class operation takes a floating-point value as its first argument and a bitfield of flags as its second argument. The operation returns a boolean value indicating whether the floating-point value satisfies the given flags.

The flags must be a compile time constant and the values are:

Bit #

floating-point class

0

Signaling NaN

1

Quiet NaN

2

Negative infinity

3

Negative normal

4

Negative subnormal

5

Negative zero

6

Positive zero

7

Positive subnormal

8

Positive normal

9

Positive infinity

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.91.1. Attributes:

AttributeMLIR TypeDescription
flags::cir::FPClassTestAttrfloating-point class test flags

1.1.91.2. Operands:

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

1.1.91.3. Results:

Result

Description

result

CIR bool type

1.1.92. cir.label (::cir::LabelOp)

Syntax:

operation ::= `cir.label` $label attr-dict

An identifier which may be referred by cir.goto operation

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable

1.1.92.1. Attributes:

AttributeMLIR TypeDescription
label::mlir::StringAttrstring attribute

1.1.93. cir.launder (::cir::LaunderOp)

Launder operation

Syntax:

operation ::= `cir.launder` $arg `:` qualified(type($result)) attr-dict

This operation represents a call to ‘launder’ in C++, which acts as an optimization boundary that breaks type invariance.

Example:

  %0 = cir.alloca "" align(8) : !cir.ptr<!cir.ptr<!rec_S>>
  %1 = cir.load align(8) %1 : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
  %2 = cir.launder(%1) : !cir.ptr<!rec_S>

Traits: SameOperandsAndResultType

Interfaces: InferTypeOpInterface

1.1.93.1. Operands:

Operand

Description

arg

CIR pointer type

1.1.93.2. Results:

Result

Description

result

CIR pointer type

1.1.94. 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. 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)

Interfaces: InferTypeOpInterface

1.1.94.1. Operands:

Operand

Description

src

pointer to void type

pattern

32-bit signed integer

len

64-bit unsigned integer

1.1.94.2. Results:

Result

Description

result

pointer to void type

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

As is the case for memcpy in the C standard library, this operation exhibits undefined behavior (UB) if any of the following conditions hold:

  • src and/or dst are null pointers; or

  • the memory regions referenced by src and dst overlap.

Examples:

  // Copying 2 bytes from one array to a record:
  %2 = cir.const #cir.int<2> : !u32i
  cir.libc.memcpy %2 bytes from %arr to %record : !cir.ptr<!arr> -> !cir.ptr<!record>

1.1.95.1. Operands:

Operand

Description

dst

pointer to void type

src

pointer to void type

len

fundamental unsigned integer type

1.1.96. cir.libc.memmove (::cir::MemMoveOp)

Equivalent to libc’s memmove

Syntax:

operation ::= `cir.libc.memmove` $len `bytes` `from` $src `to` $dst attr-dict
              `:` qualified(type($dst)) `,` type($len)

Given two CIR pointers, src and dst, cir.libc.memmove will copy len bytes from the memory pointed by src to the memory pointed by dst.

similiar to cir.libc.memcpy but accounts for overlapping memory.

Examples:

  // Copying 2 bytes from one array to a record:
  %2 = cir.const #cir.int<2> : !u32i
  cir.libc.memmove %2 bytes from %arr to %record : !cir.ptr<!void>, !u64i

1.1.96.1. Operands:

Operand

Description

dst

pointer to void type

src

pointer to void type

len

fundamental unsigned integer type

1.1.97. cir.libc.memset (::cir::MemSetOp)

Equivalent to libc’s memset

Syntax:

operation ::= `cir.libc.memset` $len `bytes` `at` $dst (`align` `(` $alignment^ `)`)? `to` $val attr-dict
              `:` qualified(type($dst)) `,` type($val) `,` type($len)

Given the CIR pointer, dst, cir.libc.memset will set the first len bytes of the memory pointed by dst to the specified val.

Examples:

  // Set 2 bytes in a record to 0:
  %len = cir.const #cir.int<2> : !u32i
  %zero = cir.const #cir.int<0> : !u8i
  cir.libc.memset %len bytes at %record to %zero : !cir.ptr<!void>,
                                                   !s32i, !u64i

1.1.97.1. Attributes:

AttributeMLIR TypeDescription
alignment::mlir::IntegerAttr64-bit signless integer attribute

1.1.97.2. Operands:

Operand

Description

dst

pointer to void type

val

8-bit unsigned integer

len

fundamental unsigned integer type

1.1.98. cir.lifetime.end (::cir::LifetimeEndOp)

Marks the end of the lifetime of a variable produced by a cir.alloca operation

Syntax:

operation ::= `cir.lifetime.end` $ptr attr-dict `:` qualified(type($ptr))

The cir.lifetime.end operation marks the end of the lifetime of the storage pointed to by $ptr. After this operation the underlying storage is considered dead, and the optimizer is free to reuse the storage for other purposes, until a subsequent cir.lifetime.start on the same pointer revives it.

The cir.scope is the operation that models the block scope of the C/C++ source. Once ClangIR is no longer structured, cir.scope can no longer express the lifetime of a local variable. This happens, for example, after FlattenCFG, where cir.scope regions are dissolved into plain basic blocks, or after HoistAllocas, where an alloca is moved to the function entry so that its position no longer reflects the scope it was declared in. In that form, these lifetime markers are what delimit the beginning and end of a variable’s lifetime.

The verifier requires $ptr to be produced by a cir.alloca. cir.lifetime.end should be preceded by a matching cir.lifetime.start on the same pointer on every control-flow path that reaches it.

This operation corresponds to the LLVM intrinsic llvm.lifetime.end.

Example:

cir.lifetime.end %ptr : !cir.ptr<!s32i>

1.1.98.1. Operands:

Operand

Description

ptr

CIR pointer type

1.1.99. cir.lifetime.start (::cir::LifetimeStartOp)

Marks the start of the lifetime of a variable produced by a cir.alloca operation

Syntax:

operation ::= `cir.lifetime.start` $ptr attr-dict `:` qualified(type($ptr))

The cir.lifetime.start operation marks the beginning of the lifetime of the storage pointed to by $ptr. Between this operation and a matching cir.lifetime.end on the same pointer, the underlying storage is considered live; outside that range it is considered dead, and the optimizer is free to reuse the storage for other purposes.

The cir.scope is the operation that models the block scope of the C/C++ source. Once ClangIR is no longer structured, cir.scope can no longer express the lifetime of a local variable. This happens, for example, after FlattenCFG, where cir.scope regions are dissolved into plain basic blocks, or after HoistAllocas, where an alloca is moved to the function entry so that its position no longer reflects the scope it was declared in. In that form, these lifetime markers are what delimit the beginning and end of a variable’s lifetime.

The verifier requires $ptr to be produced by a cir.alloca. For the lifetime to be meaningful, a matching cir.lifetime.end on the same pointer should follow on every control-flow path. This is different from LLVM, where an llvm.lifetime.start may appear without a matching llvm.lifetime.end – there the storage is also implicitly marked dead when the function returns (see the LLVM LangRef).

This operation corresponds to the LLVM intrinsic llvm.lifetime.start.

Example:

cir.lifetime.start %ptr : !cir.ptr<!s32i>

1.1.99.1. Operands:

Operand

Description

ptr

CIR pointer type

1.1.100. cir.llrint (::cir::LlrintOp)

Rounds floating-point to long long integer using current rounding mode

Syntax:

operation ::= `cir.llrint` $src `:` type($src) `->` type($result) attr-dict

cir.llrint rounds a floating-point value to the nearest integer value using the current rounding mode and returns the result as a long long.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.100.1. Operands:

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

1.1.100.2. Results:

Result

Description

result

Integer type with arbitrary precision up to a fixed limit

1.1.101. cir.llround (::cir::LlroundOp)

Rounds floating-point to long long integer

Syntax:

operation ::= `cir.llround` $src `:` type($src) `->` type($result) attr-dict

cir.llround rounds a floating-point value to the nearest integer value, rounding halfway cases away from zero, and returns the result as a long long.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.101.1. Operands:

Operand

Description

src

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

1.1.101.2. Results:

Result

Description

result

Integer type with arbitrary precision up to a fixed limit

1.1.102. cir.load (::cir::LoadOp)

Load value from memory adddress

Syntax:

operation ::= `cir.load` (`deref` $isDeref^)?
              (`volatile` $is_volatile^)?
              (`nontemporal` $is_nontemporal^)?
              (`invariant` $invariant^)?
              (`align` `(` $alignment^ `)`)?
              (`syncscope` `(` $sync_scope^ `)`)?
              (`atomic` `(` $mem_order^ `)`)?
              $addr `:` qualified(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. Load can be marked atomic by using atomic(<mem_order>).

alignment can be used to specify an alignment that’s different from the default, which is computed from result’s type ABI data layout.

A unit attribute invariant can be used to indicate that the loaded memory never changes, mapping to LLVM IR’s !invariant.load metadata.

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

// Perform an invariant load from address in %0.
%5 = cir.load invariant %0 : !cir.ptr<i32>, i32

// Others
%x = cir.load align(16) atomic(seq_cst) %0 : !cir.ptr<i32>, i32

Interfaces: InferTypeOpInterface, PromotableMemOpInterface

1.1.102.1. Attributes:

AttributeMLIR TypeDescription
isDeref::mlir::UnitAttrunit attribute
is_volatile::mlir::UnitAttrunit attribute
is_nontemporal::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute
sync_scope::cir::SyncScopeKindAttrsync scope kind
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model
invariant::mlir::UnitAttrunit attribute

1.1.102.2. Operands:

Operand

Description

addr

CIR pointer type

1.1.102.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.103. cir.local_init (::cir::LocalInitOp)

Initialize a static or thread local object

Syntax:

operation ::= `cir.local_init` (`thread_local` $tls^) : (`static_local`)?
              $globalName attr-dict
              (`ctor` $ctorRegion^)?
              (`dtor` $dtorRegion^)?

The ‘cir.local_init’ operation has no result, but is responsible for containing the regions to initialize and destroy the static local variable. This will be handled during lowering-prepare to include the guard variables correctly for the variable.

This operation may also represent a static local thread local variable, which would be indicated by the ‘tls’ flag.

Example:

// Note: despite this always being static_local, we print it anyway to be
// visually consistent with get_global, and as a 'counter' to 'tls'.
cir.local_init static_local @GlobalName ctor {
  %4 = cir.get_global static_local @GlobalName : !cir.ptr<!rec_CtorDtor>
  %5 = cir.call @_Z5get_iv() : () -> !s32i
  cir.call @_ZN8CtorDtorC1Ei(%4, %5) : !cir.ptr<!rec_CtorDtor>
  cir.yield
}, dtor {
  %4 = cir.get_global static_local @_ZZ3foovE8localCD2 :
                                              !cir.ptr<!rec_CtorDtor>
  cir.call @_ZN8CtorDtorD1Ev(%4) : (!cir.ptr<!rec_CtorDtor>) -> ()
  cir.yield
}

Traits: `HasAncestor<FuncOp>`, `NoRegionArguments`

Interfaces: `SymbolUserOpInterface`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>globalName</code></td><td>::mlir::FlatSymbolRefAttr</td><td>flat symbol reference attribute</td></tr>
</table>



### `cir.log` (::cir::LogOp)

_Computes the floating-point natural logarithm_

Syntax:

operation ::= cir.log $src : type($src) attr-dict


`cir.log` computes the natural logarithm of a floating-point operand and
returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.log10` (::cir::Log10Op)

_Computes the floating-point base-10 logarithm_

Syntax:

operation ::= cir.log10 $src : type($src) attr-dict


`cir.log10` computes the base-10 logarithm of a floating-point operand and
returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.log2` (::cir::Log2Op)

_Computes the floating-point base-2 logarithm_

Syntax:

operation ::= cir.log2 $src : type($src) attr-dict


`cir.log2` computes the base-2 logarithm of a floating-point operand and
returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.lrint` (::cir::LrintOp)

_Rounds floating-point to long integer using current rounding mode_

Syntax:

operation ::= cir.lrint $src : type($src) -> type($result) attr-dict


`cir.lrint` rounds a floating-point value to the nearest integer value
using the current rounding mode and returns the result as a `long`.

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | Integer type with arbitrary precision up to a fixed limit |



### `cir.lround` (::cir::LroundOp)

_Rounds floating-point to long integer_

Syntax:

operation ::= cir.lround $src : type($src) -> type($result) attr-dict


`cir.lround` rounds a floating-point value to the nearest integer value,
rounding halfway cases away from zero, and returns the result as a `long`.

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | Integer type with arbitrary precision up to a fixed limit |



### `cir.max` (::cir::MaxOp)

_Integer maximum_

Syntax:

operation ::= cir.max $lhs , $rhs : type($lhs) attr-dict


The `cir.max` operation computes the maximum of two integer operands.
Both operands and the result must have the same integer type or vector of
integer type.

Example:


Traits: `Commutative`, `Idempotent`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.min` (::cir::MinOp)

_Integer minimum_

Syntax:

operation ::= cir.min $lhs , $rhs : type($lhs) attr-dict


The `cir.min` operation computes the minimum of two integer operands.
Both operands and the result must have the same integer type or vector of
integer type.

Example:


Traits: `Commutative`, `Idempotent`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.minus` (::cir::MinusOp)

_Integer unary minus (negation)_

Syntax:

operation ::= cir.minus (nsw $no_signed_wrap^)? $input : type($input) attr-dict


The `cir.minus` operation negates the operand. The operand and result
must have the same type.

The optional `nsw` (no signed wrap) attribute indicates that the result
is poison if signed overflow occurs (e.g. negating the minimum signed
integer).

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`, `UnaryOpInterface`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.modf` (::cir::ModfOp)

_Decomposes a floating-point value into fractional and integral parts_

Syntax:

operation ::= cir.modf $src : type($src) -> type($fractional) , type($integral) attr-dict


`cir.modf` splits a floating-point value into its fractional and integral
parts.  Both parts have the same sign as the input.

Lowers to `llvm.modf`.

Example:
  %frac, %intpart = cir.modf %x : !cir.float -> !cir.float, !cir.float

Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `fractional` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |
| `integral` | single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type |



### `cir.mul` (::cir::MulOp)

_Integer multiplication_

Syntax:

operation ::= cir.mul (nsw $no_signed_wrap^)? (nuw $no_unsigned_wrap^)? $lhs , $rhs : type($lhs) attr-dict


The `cir.mul` operation performs multiplication on integer operands. Both
operands and the result must have the same integer or vector-of-integer
type.

The optional `nsw` (no signed wrap) and `nuw` (no unsigned wrap) unit
attributes indicate that the result is poison if signed or unsigned
overflow occurs, respectively.

Example:


Traits: `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.mul.overflow` (::cir::MulOverflowOp)

_Integer multiplication with overflow checking_

Syntax:

operation ::= cir.mul.overflow $lhs , $rhs : qualified(type($lhs)) -> qualified(type($result)) attr-dict


`cir.mul.overflow` performs multiplication with overflow checking on
integral operands. See `CIR_BinOpOverflow` for semantics.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `Commutative`, `SameTypeOperands`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | Integer type with arbitrary precision up to a fixed limit |
| `rhs` | Integer type with arbitrary precision up to a fixed limit |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or boolean type |
| `overflow` | CIR bool type |



### `cir.nearbyint` (::cir::NearbyintOp)

_Rounds floating-point value to nearest integer_

Syntax:

operation ::= cir.nearbyint $src : type($src) attr-dict


`cir.nearbyint` rounds a floating-point operand to the nearest integer value
and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.not` (::cir::NotOp)

_Bitwise NOT / logical NOT_

Syntax:

operation ::= cir.not $input : type($input) attr-dict


The `cir.not` operation performs a bitwise NOT on integer types or a
logical NOT on boolean types. The operand and result must have the same
type.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `Involution`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`, `UnaryOpInterface`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | integer, boolean, or vector of integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer, boolean, or vector of integer |



### `cir.objsize` (::cir::ObjSizeOp)

_Implements the llvm.objsize builtin_

Syntax:

operation ::= cir.objsize (min $min^) : (max)? (nullunknown $nullunknown^)? (dynamic $dynamic^)? $ptr : qualified(type($ptr)) -> qualified(type($result)) attr-dict


The `cir.objsize` operation is designed to provide information to the
optimizer to determine whether a) an operation (like memcpy) will
overflow a buffer that corresponds to an object, or b) that a runtime
check for overflow isn’t necessary. An object in this context means an
allocation of a specific class, structure, array, or other object.

When the `min` attribute is present, the operation returns the minimum
guaranteed accessible size. When absent (max mode), it returns the maximum
possible object size. Corresponds to `llvm.objectsize`'s `min` argument.

The `dynamic` attribute determines if the value should be evaluated at
runtime. Corresponds to `llvm.objectsize`'s `dynamic` argument.

The `nullunknown` attribute controls how null pointers are handled. When
present, null pointers are treated as having unknown size. When absent,
null pointers are treated as having 0 size (in min mode) or -1 size
(in max mode). Corresponds to `llvm.objectsize`'s `nullunknown` argument.

Example:


Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>min</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>nullunknown</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
<tr><td><code>dynamic</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `ptr` | CIR pointer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | fundamental integer type |



### `cir.or` (::cir::OrOp)

_Bitwise OR_

Syntax:

operation ::= cir.or $lhs , $rhs : type($lhs) attr-dict


The `cir.or` operation performs a bitwise OR on integer operands.
Both operands and the result must have the same integer type.

Example:


Traits: `Commutative`, `Idempotent`, `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer, boolean, or vector of integer |
| `rhs` | integer, boolean, or vector of integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer, boolean, or vector of integer |



### `cir.parity` (::cir::BitParityOp)

_Get the parity of input_

Syntax:

operation ::= cir.parity $input : type($result) attr-dict


Compute the parity of the input. The parity of an integer is the number of
1-bits in it modulo 2.

The input must be an unsigned integer.

Example:

// %0 = 0x0110_1000

// %1 will be 1 since there are three 1-bits in %0


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | unsigned integer type of widths 32/64 |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | unsigned integer type of widths 32/64 |



### `cir.popcount` (::cir::BitPopcountOp)

_Get the number of 1-bits in input_

Syntax:

operation ::= cir.popcount $input : type($result) attr-dict


Compute the number of 1-bits in the input.

The input must be an unsigned integer.

Example:

// %0 = 0x0110_1000

// %1 will be 3 since there are 3 1-bits in %0


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | unsigned integer type of widths 8/16/32/64/128 |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | unsigned integer type of widths 8/16/32/64/128 |



### `cir.pow` (::cir::PowOp)

_Computes the power of a floating-point value_

Syntax:

operation ::= cir.pow $lhs , $rhs : qualified(type($lhs)) attr-dict


`cir.pow` computes the first operand raised to the power of the second
operand.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | floating point or vector of floating point type |
| `rhs` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.prefetch` (::cir::PrefetchOp)

_Prefetch operation_

Syntax:

operation ::= cir.prefetch (write $isWrite^) : (read)? locality ( $locality ) $addr : qualified(type($addr)) attr-dict


The `cir.prefetch` operation is a hint to the code generator to insert a
prefetch instruction if supported; otherwise, it is a noop. Prefetches
have no effect on the behavior of the program but can change its
performance characteristics.

cir.prefetch(%0 : !cir.ptr<!void>) locality(1) write


$locality is a temporal locality specifier ranging from (0) - no locality,
to (3) - extremely local, keep in cache. If $locality is not present, the
default value is 3.

$isWrite specifies whether the prefetch is for a 'read' or 'write'. If
$isWrite is not specified, it means that prefetch is prepared for 'read'.

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>locality</code></td><td>::mlir::IntegerAttr</td><td>32-bit signless integer attribute whose minimum value is 0 whose maximum value is 3</td></tr>
<tr><td><code>isWrite</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `addr` | pointer to void type |



### `cir.ptr_diff` (::cir::PtrDiffOp)

_Pointer subtraction arithmetic_

Syntax:

operation ::= cir.ptr_diff $lhs , $rhs : qualified(type($lhs)) -> qualified(type($result)) attr-dict


The cir.ptr_diff operation computes the difference between two pointers that
have the same element type.

The result reflects the ABI-defined size of the pointed-to type. For example,
subtracting two !cir.ptr<!u64i> values may yield 1, representing an 8-byte
difference. In contrast, for pointers to void or function types, a result of
8 corresponds to an 8-byte difference.

For pointers to types whose size are not aligned with the target data
layout, the size is generally rounded to the next power of 2 bits. For
example, subtracting two !cir.ptr<!s24i> values for the _BitInt(24) type may
yield 1, representing a 4-byte difference (as opposed to a 3-byte
difference).

Example:


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` | fundamental integer type |



### `cir.ptr_stride` (::cir::PtrStrideOp)

_Pointer access with stride_

Syntax:

operation ::= cir.ptr_stride $base, $stride : functional-type(operands, results) attr-dict


The `cir.ptr_stride` operation computes a new pointer from a base pointer
and an integer stride, similar to a single-index `getelementptr` in LLVM IR.
It moves the pointer by `stride * sizeof(element_type)` bytes.


Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `base` | CIR pointer type |
| `stride` | fundamental integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR pointer type |



### `cir.rem` (::cir::RemOp)

_Integer remainder_

Syntax:

operation ::= cir.rem $lhs , $rhs : type($lhs) attr-dict


The `cir.rem` operation computes the remainder of division on integer
operands. Both operands and the result must have the same integer or
vector-of-integer type.

Example:


Traits: `SameOperandsAndResultType`

Interfaces: `BinaryOpInterface`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `lhs` | integer or vector of integer type |
| `rhs` | integer or vector of integer type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | integer or vector of integer type |



### `cir.resume` (::cir::ResumeOp)

_Resumes execution after not catching exceptions_

Syntax:

operation ::= cir.resume $eh_token : type($eh_token) attr-dict


The `cir.resume` operation handles an uncaught exception scenario.

Before CFG flattening, this operation is used as the terminator of a
`CatchUnwind` region of `cir.try`, where it receives an `!cir.eh_token`
argument representing the in-flight exception.

During CFG flattening, this operation may temporarily appear inside any
structured CIR operation (scope, loop, switch, etc.) when an inner cleanup
scope is flattened before the enclosing structured op. When the enclosing
op is subsequently flattened, the resume will end up in a `cir.try`
operation or at function level.

After CFG flattening, this operation appears at the function level (inside
`cir.func`) to indicate that the exception should be re-thrown to the
caller after cleanup code has been executed.

Examples:

// Before CFG flattening (in try unwind region) cir.try { cir.yield } unwind (%eh_token : !cir.eh_token) { cir.resume %eh_token : !cir.eh_token }

// After CFG flattening (at function level, after cleanup) ^eh_cleanup(%eh_token : !cir.eh_token):

cir.call @destructor() : () -> () cir.end_cleanup %ct : !cir.cleanup_token cir.resume %eh_token : !cir.eh_token


Traits: `Terminator`

Interfaces: `RegionBranchTerminatorOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `eh_token` | CIR exception handling token type |



### `cir.resume.flat` (::cir::ResumeFlatOp)

_A flattened version of `cir.resume`_

Syntax:

operation ::= cir.resume.flat $exception_ptr , $type_id attr-dict


The `cir.resume.flat` operation is a region-less and simplified
version of the `cir.resume`.

Its representation is closer to LLVM IR dialect
than the C/C++ language feature.

This operation is used only after the CFG flatterning pass.

Examples:

cir.resume.flat %exception_ptr, %type_id


Traits: `ReturnLike`, `Terminator`

Interfaces: `RegionBranchTerminatorOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `exception_ptr` | pointer to void type |
| `type_id` | 32-bit unsigned integer |



### `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, CaseOp, CleanupScopeOp, DoWhileOp, WhileOp, ForOp, TryOp>`, `Terminator`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.return_address` (::cir::ReturnAddrOp)

_The return address of the current function, or of one of its callers_

Syntax:

operation ::= cir.return_address ( $level ) attr-dict


Represents a call to builtin function ` __builtin_return_address` in CIR.
This builtin function returns the return address of the current function,
or of one of its callers.

The `level` argument is number of frames to scan up the call stack.
For instance, value of 0 yields the return address of the current function,
value of 1 yields the return address of the caller of the current function,
and so forth.

Examples:


Interfaces: `InferTypeOpInterface`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `level` | 32-bit unsigned integer |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | pointer to void type |



### `cir.rint` (::cir::RintOp)

_Rounds floating-point value to nearest integer_

Syntax:

operation ::= cir.rint $src : type($src) attr-dict


`cir.rint` rounds a floating-point operand to the nearest integer value
and returns a result of the same type.

This operation does not set `errno`. Unlike `cir.nearbyint`, this operation
may raise the `FE_INEXACT` exception if the input value is not an exact
integer, but this is not guaranteed to happen.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.rotate` (::cir::RotateOp)

_Rotate the bits in the operand integer_

Syntax:

operation ::= cir.rotate (left $rotateLeft^) : (right)? $input , $amount : type($result) attr-dict


The `cir.rotate` rotates the bits in `input` by the given amount `amount`.
The rotate direction is specified by the `left` and `right` keyword.

`input` must be an unsigned integer and its width must be either 8, 16, 32,
or 64. The types of `input`, `amount`, and the result must all match.

Example:


Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Attributes:

<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>rotateLeft</code></td><td>::mlir::UnitAttr</td><td>unit attribute</td></tr>
</table>

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `input` | unsigned integer type of widths 8/16/32/64 |
| `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.round` (::cir::RoundOp)

_Rounds floating-point value to nearest integer_

Syntax:

operation ::= cir.round $src : type($src) attr-dict


`cir.round` rounds a floating-point operand to the nearest integer value
and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.roundeven` (::cir::RoundEvenOp)

_Rounds floating-point value to nearest integer, ties to even_

Syntax:

operation ::= cir.roundeven $src : type($src) attr-dict


`cir.roundeven` rounds a floating-point operand to the nearest integer
value, with ties rounding to even (banker's rounding).

Floating-point exceptions are ignored, and it does not set `errno`.

Traits: `AlwaysSpeculatableImplTrait`, `SameOperandsAndResultType`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `src` | floating point or vector of floating point type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | floating point or vector of floating point type |



### `cir.scope` (::cir::ScopeOp)

_Represents a C/C++ scope_

Syntax:

operation ::= cir.scope custom($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`:


… cir.yield %value }


The blocks can be terminated by `cir.yield`, `cir.return` or `cir.throw`.
If `cir.scope` yields no value, the `cir.yield` can be left out, and
will be inserted implicitly.

Traits: `AutomaticAllocationScope`, `NoRegionArguments`, `RecursiveMemoryEffects`, `RecursivelySpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `RegionBranchOpInterface`

#### Results:

| Result | Description |
| :----: | ----------- |
| `results` | CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.select` (::cir::SelectOp)

_Yield one of two values based on a boolean value_

Syntax:

operation ::= cir.select if $condition then $true_value else $false_value : ( qualified(type($condition)) , qualified(type($true_value)) , qualified(type($false_value)) ) -> qualified(type($result)) attr-dict


The `cir.select` operation takes three operands. The first operand
`condition` is either a boolean value of type `!cir.bool` or a boolean
vector of type `!cir.bool`.  The second and the third operand can be of
any CIR types, but their types must be the same. If the first operand 
is `true`, the operation yields its second operand. Otherwise, the
operation yields its third operand.

In the case where the first operand is a boolean vector, then the second 
and third operand needs to also be of some vectors of the same type to
each other and that the number of elements of all three operands needs to 
be the same as well.

Example:


Traits: `AlwaysSpeculatableImplTrait`

Interfaces: `ConditionallySpeculatable`, `InferTypeOpInterface`, `NoMemoryEffect (MemoryEffectOpInterface)`

Effects: `MemoryEffects::Effect{}`

#### Operands:

| Operand | Description |
| :-----: | ----------- |
| `condition` | CIR bool type or vector of CIR bool type |
| `true_value` | CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |
| `false_value` | CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |

#### Results:

| Result | Description |
| :----: | ----------- |
| `result` | CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type |



### `cir.set_bitfield` (::cir::SetBitfieldOp)

_Set the value of a bitfield member_

Syntax:

operation ::= cir.set_bitfield (align ( $alignment^ ))? ($bitfield_info, $addr:qualified(type($addr)), $src:type($src) ) attr-dict -> type($result)


The `cir.set_bitfield` operation provides a store-like access to
a bit field of a record.

A bitfield info attribute must be provided to describe the location of
the bitfield within the memory referenced by the $addr argument.
The $src argument is inserted at the appropriate place in the memory and
the value that was stored. Returns the value being stored.

A unit attribute `volatile` can be used to indicate a volatile store of the
bitfield.
cir.set_bitfield(#bfi, %0 : !cir.ptr<!u32i>, %1 : !s32i) {is_volatile}
                                                               -> !s32i

Example.
Suppose we have a struct with multiple bitfields stored in
different storages. The `cir.set_bitfield` operation sets the value
of the bitfield.
```C++
typedef struct {
int a : 4;
int b : 27;
int c : 17;
int d : 2;
int e : 15;
} S;

void store_bitfield(S& s) {
s.e = 3;
}
// 'e' is in the storage with the index 1
!record_type = !cir.record<struct "S" packed padded {!u64i, !u16i,
                           !cir.array<!u8i x 2>} #cir.record.decl.ast>
#bfi_e = #cir.bitfield_info<name = "e", storage_type = !u16i, size = 15,
                            offset = 0, is_signed = true>

%1 = cir.const #cir.int<3> : !s32i
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
%3 = cir.get_member %2[1] {name = "e"} : !cir.ptr<!record_type>
                                                         -> !cir.ptr<!u16i>
%4 = cir.set_bitfield align(4) (#bfi_e, %3 : !cir.ptr<!u16i>, %1 : !s32i)
                                                                   -> !s32i

1.1.103.1. Attributes:

AttributeMLIR TypeDescription
bitfield_info::cir::BitfieldInfoAttrRepresents info for a bit-field member
alignment::mlir::IntegerAttr64-bit signless integer attribute
is_volatile::mlir::UnitAttrunit attribute

1.1.103.2. Operands:

Operand

Description

addr

CIR pointer type

src

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.103.3. Results:

Result

Description

result

integer or boolean type

1.1.104. cir.shift (::cir::ShiftOp)

Shift

Syntax:

operation ::= `cir.shift` `(`
              (`left` $isShiftleft^) : (```right`)?
              `,` $value `:` type($value)
              `,` $amount `:` type($amount)
              `)` `->` type($result) attr-dict

The cir.shift operation performs a bitwise shift, either to the left or to the right, based on the first operand. The second operand specifies the value to be shifted, and the third operand determines the number of positions by which the shift is applied, They must be either all vector of integer type, or all integer type. If they are vectors, each vector element of the shift target is shifted by the corresponding shift amount in the shift amount vector.

%res = cir.shift(left, %lhs : !u64i, %amount : !s32i) -> !u64i
%new_vec = cir.shift(left, %lhs : !cir.vector<2 x !s32i>, %rhs :
    !cir.vector<2 x !s32i>) -> !cir.vector<2 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.104.1. Attributes:

AttributeMLIR TypeDescription
isShiftleft::mlir::UnitAttrunit attribute

1.1.104.2. Operands:

Operand

Description

value

integer or vector of integer type

amount

integer or vector of integer type

1.1.104.3. Results:

Result

Description

result

integer or vector of integer type

1.1.105. cir.signbit (::cir::SignBitOp)

Checks the sign of a floating-point number

Syntax:

operation ::= `cir.signbit` $input attr-dict `:` type($input) `->` qualified(type($res))

It returns whether the sign bit (i.e. the highest bit) of the input operand is set.

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.105.1. Operands:

Operand

Description

input

single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type

1.1.105.2. Results:

Result

Description

res

CIR bool type

1.1.106. cir.sin (::cir::SinOp)

Computes the floating-point sine

Syntax:

operation ::= `cir.sin` $src `:` type($src) attr-dict

cir.sin computes the sine of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.106.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.106.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.107. cir.sqrt (::cir::SqrtOp)

Floating-point square root operation

Syntax:

operation ::= `cir.sqrt` $src `:` type($src) attr-dict

Computes the square root of a floating-point value or vector.

The input must be either: • a floating-point scalar type, or • a vector whose element type is floating-point.

The result type must match the input type exactly.

Examples: // scalar

// vector

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.107.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.107.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.108. cir.stackrestore (::cir::StackRestoreOp)

Restores the state of the function stack

Syntax:

operation ::= `cir.stackrestore` $ptr attr-dict `:` qualified(type($ptr))

Restore the state of the function stack to the state it was in when the corresponding cir.stacksave executed. This is used during the lowering of variable length array allocas.

This operation corresponds to LLVM intrinsic stackrestore.

%0 = cir.alloca "saved_stack" align(8) : !cir.ptr<!cir.ptr<!u8i>>
%1 = cir.stacksave : <!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.stackrestore %2 : !cir.ptr<!u8i>

1.1.108.1. Operands:

Operand

Description

ptr

CIR pointer type

1.1.109. cir.stacksave (::cir::StackSaveOp)

Remembers the current state of the function stack

Syntax:

operation ::= `cir.stacksave` attr-dict `:` qualified(type($result))

Saves current state of the function stack. Returns a pointer to an opaque object that later can be passed into cir.stackrestore. This is used during the lowering of variable length array allocas.

This operation corresponds to LLVM intrinsic stacksave.

%0 = cir.stacksave : <!u8i>

1.1.109.1. Results:

Result

Description

result

CIR pointer type

1.1.110. cir.store (::cir::StoreOp)

Store value to memory address

Syntax:

operation ::= `cir.store` (`volatile` $is_volatile^)?
              (`nontemporal` $is_nontemporal^)?
              (`align` `(` $alignment^ `)`)?
              (`syncscope` `(` $sync_scope^ `)`)?
              (`atomic` `(` $mem_order^ `)`)?
              $value `,` $addr attr-dict `:` type($value) `,` qualified(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. Store’s can be marked atomic by using atomic(<mem_order>).

alignment can be used to specify an alignment that’s different from the default, which is computed from result’s type ABI data layout.

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>

// Others
cir.store align(16) atomic(seq_cst) %x, %addr : i32, !cir.ptr<i32>

Interfaces: PromotableMemOpInterface

1.1.110.1. Attributes:

AttributeMLIR TypeDescription
is_volatile::mlir::UnitAttrunit attribute
is_nontemporal::mlir::UnitAttrunit attribute
alignment::mlir::IntegerAttr64-bit signless integer attribute
sync_scope::cir::SyncScopeKindAttrsync scope kind
mem_order::cir::MemOrderAttrMemory order according to C++11 memory model

1.1.110.2. Operands:

Operand

Description

value

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

addr

CIR pointer type

1.1.111. cir.sub (::cir::SubOp)

Integer subtraction

Syntax:

operation ::= `cir.sub` (`nsw` $no_signed_wrap^)?
              (`nuw` $no_unsigned_wrap^)?
              (`sat` $saturated^)?
              $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.sub operation performs subtraction on integer operands. Both operands and the result must have the same integer or vector-of-integer type.

The optional nsw (no signed wrap) and nuw (no unsigned wrap) unit attributes indicate that the result is poison if signed or unsigned overflow occurs, respectively. The optional sat (saturated) attribute clamps the result to the type’s representable range. The nsw/nuw flags and sat are mutually exclusive.

Example:

%0 = cir.sub %a, %b : !s32i
%1 = cir.sub nsw %a, %b : !s32i
%2 = cir.sub sat %a, %b : !s32i
%3 = cir.sub %va, %vb : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: BinaryOpInterface, ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.111.1. Operands:

Operand

Description

lhs

integer or vector of integer type

rhs

integer or vector of integer type

1.1.111.2. Results:

Result

Description

result

integer or vector of integer type

1.1.112. cir.sub.overflow (::cir::SubOverflowOp)

Integer subtraction with overflow checking

Syntax:

operation ::= `cir.sub.overflow` $lhs `,` $rhs `:` qualified(type($lhs)) `->` qualified(type($result))
              attr-dict

cir.sub.overflow performs subtraction with overflow checking on integral operands. See CIR_BinOpOverflow for semantics.

Example:

%result, %overflow = cir.sub.overflow %a, %b : !u32i -> !u32i

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.112.1. Operands:

Operand

Description

lhs

Integer type with arbitrary precision up to a fixed limit

rhs

Integer type with arbitrary precision up to a fixed limit

1.1.112.2. Results:

Result

Description

result

integer or boolean type

overflow

CIR bool type

1.1.113. cir.switch (::cir::SwitchOp)

Switch operation

Syntax:

operation ::= `cir.switch` `(` $condition `:` qualified(type($condition)) `)`
              (`all_enum_cases_covered` $all_enum_cases_covered^)?
              $body
              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.

Besides taking an integer condition and CIR regions, it also accepts an all_enum_cases_covered attribute indicating whether all enum cases are handled by the operation. Note that the presence of a default CaseOp does not imply all_enum_cases_covered. The original AST switch must explicitly list every enum case.

The set of cir.case operations and their enclosing cir.switch represent the semantics of a C/C++ switch statement. Users can use collectCases(llvm::SmallVector<CaseOp> &cases) to collect the cir.case operation in the cir.switch operation easily.

The cir.case operations don’t have to be in the region of cir.switch directly. However, when all the cir.case operations live in the region of cir.switch directly and there are no other operations except the ending cir.yield operation in the region of cir.switch directly, we say the cir.switch operation is in a simple form. Users can use bool isSimpleForm(llvm::SmallVector<CaseOp> &cases) member function to detect if the cir.switch operation is in a simple form. The simple form makes it easier for analyses to handle the cir.switch operation and makes the boundary to give up clear.

To make the simple form as common as possible, CIR code generation attaches operations corresponding to the statements that lives between top level cases into the closest cir.case operation.

For example,

switch(int cond) {
  case 4:
    a++;
    b++;
  case 5:
    c++;

  ...
}

The statement b++ is not a sub-statement of the case statement case 4. But to make the generated cir.switch a simple form, we will attach the statement b++ into the closest cir.case operation. So that the generated code will be like:

cir.switch(int cond) {
  cir.case(equal, 4) {
    a++;
    b++;
    cir.yield
  }
  cir.case(equal, 5) {
    c++;
    cir.yield
  }
  ...
}

For the same reason, we will hoist the case statement as the substatement of another case statement so that they will be in the same level. For example,

switch(int cond) {
  case 4:
  default;
  case 5:
    a++;
  ...
}

will be generated as

cir.switch(int cond) {
  cir.case(equal, 4) {
    cir.yield
  }
  cir.case(default) {
    cir.yield
  }
  cir.case(equal, 5) {
    a++;
    cir.yield
  }
  ...
}

The cir.switch is not be considered “simple” if any of the following is true:

  • There are case statements of the switch statement that are scope other than the top level compound statement scope. Note that a case statement itself doesn’t form a scope.

  • The sub-statement of the switch statement is not a compound statement.

  • There is any code before the first case statement. For example,

switch(int cond) {
  l:
    b++;

  case 4:
    a++;
    break;

  case 5:
    goto l;
  ...
}

the generated CIR for this non-simple switch would be:

cir.switch(int cond) {
  cir.label "l"
  b++;
  cir.case(4) {
    a++;
    cir.break
  }
  cir.case(5) {
    goto "l"
  }
  cir.yield
}

Traits: AutomaticAllocationScope, NoRegionArguments, RecursiveMemoryEffects, RecursivelySpeculatableImplTrait, SameVariadicOperandSize

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

1.1.113.1. Attributes:

AttributeMLIR TypeDescription
all_enum_cases_covered::mlir::UnitAttrunit attribute

1.1.113.2. Operands:

Operand

Description

condition

Integer type with arbitrary precision up to a fixed limit

1.1.114. cir.switch.flat (::cir::SwitchFlatOp)

A flattened version of cir.switch

Syntax:

operation ::= `cir.switch.flat` $condition `:` type($condition) `,`
              $defaultDestination (`(` $defaultOperands^ `:` type($defaultOperands) `)`)?
              custom<SwitchFlatOpCases>(ref(type($condition)), $caseValues,
              $caseDestinations, $caseOperands,
              type($caseOperands))
              attr-dict

The cir.switch.flat operation is a region-less and simplified version of the cir.switch. Its representation is closer to LLVM IR dialect than the C/C++ language feature.

Traits: AttrSizedOperandSegments, Terminator

1.1.114.1. Attributes:

AttributeMLIR TypeDescription
caseValues::mlir::ArrayAttrarray attribute
case_operand_segments::mlir::DenseI32ArrayAttri32 dense array attribute

1.1.114.2. Operands:

Operand

Description

condition

Integer type with arbitrary precision up to a fixed limit

defaultOperands

variadic of any non-token type

caseOperands

variadic of any non-token type

1.1.114.3. Successors:

Successor

Description

defaultDestination

any successor

caseDestinations

any successor

1.1.115. cir.tan (::cir::TanOp)

Computes the floating-point tangent

Syntax:

operation ::= `cir.tan` $src `:` type($src) attr-dict

cir.tan computes the tangent of a floating-point operand and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.115.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.115.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.116. 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. The 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.

cir.ternary also represents the GNU binary conditional operator ?: which reuses the parent operation for both the condition and the true branch to evaluate it only once.

Example:

// 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

1.1.116.1. Operands:

Operand

Description

cond

CIR bool type

1.1.116.2. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.117. cir.throw (::cir::ThrowOp)

(Re)Throws an exception

Syntax:

operation ::= `cir.throw` ($exception_ptr^ `:` type($exception_ptr))?
              (`,` $type_info^)?
              (`,` $dtor^)?
              attr-dict

This operation is equivalent to either __cxa_throw or __cxa_rethrow, depending on the arguments.

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.alloc_exception) and finally an optional dtor, which might run as part of this operation.

Example:

// re-throw;
cir.throw

// if (b == 0)
//   throw "Division by zero condition!";

// Type info for char const*
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>
cir.if %cond {
  %exception_addr = cir.alloc_exception 8 -> !cir.ptr<!void>
  ...
  // Store string addr for "Division by zero condition!"
  cir.store %string_addr, %exception_addr : !cir.ptr<!s8i>,
    !cir.ptr<!cir.ptr<!s8i>>
  cir.throw %exception_addr : !cir.ptr<!cir.ptr<!u8i>>,
    @_ZTIPKc

1.1.117.1. Attributes:

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

1.1.117.2. Operands:

Operand

Description

exception_ptr

CIR pointer type

1.1.118. cir.trap (::cir::TrapOp)

Exit the program abnormally

Syntax:

operation ::= `cir.trap` attr-dict

The cir.trap operation causes the program to exit abnormally. The implementations may implement this operation with different mechanisms. For example, an implementation may implement this operation by calling abort, while another implementation may implement this operation by executing an illegal instruction.

Traits: Terminator

1.1.119. cir.trunc (::cir::TruncOp)

Truncates floating-point value to integer

Syntax:

operation ::= `cir.trunc` $src `:` type($src) attr-dict

cir.trunc truncates a floating-point operand to an integer value and returns a result of the same type.

Floating-point exceptions are ignored, and it does not set errno.

Traits: AlwaysSpeculatableImplTrait, SameOperandsAndResultType

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.119.1. Operands:

Operand

Description

src

floating point or vector of floating point type

1.1.119.2. Results:

Result

Description

result

floating point or vector of floating point type

1.1.120. cir.try (::cir::TryOp)

C++ try block

Syntax:

operation ::= `cir.try` (`cleanup` $cleanup^)?
              $try_region
              custom<TryHandlerRegions>($handler_regions, $handler_types)
              attr-dict

Holds the lexical scope of try {}. Note that resources used on catch clauses are usually allocated in the same parent as cir.try.

cleanup: indicates that there are cleanups that must be performed when exiting the try region via exception, even if the exception is not caught.

Each catch handler region and unwind region receives a !cir.eh_token argument representing the inflight exception. The first operation in a catch handler region must be a cir.begin_catch operation. This must be followed by a cir.cleanup.scope operation, with the cir.end_catch operation in its cleanup region. The catch handling code will be emitted into the body of the cleanup scope. This ensures that all paths out of the catch handler will execute the end_catch operation.

Example:

cir.try {
  cir.call exception @function() : () -> ()
  cir.yield
} catch [type #cir.global_view<@_ZTIPf> : !cir.ptr<!u8i>] (%eh_token : !cir.eh_token) {
  %catch_token, %exn_ptr = cir.begin_catch %eh_token
    : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.float>)
  cir.cleanup.scope {
    ...
    cir.yield
  } cleanup eh {
    cir.end_catch %catch_token : !cir.catch_token
    cir.yield
  }
  cir.yield
} unwind (%eh_token : !cir.eh_token) {
  cir.resume %eh_token : !cir.eh_token
}

Traits: AutomaticAllocationScope, RecursivelySpeculatableImplTrait

Interfaces: ConditionallySpeculatable, RegionBranchOpInterface

1.1.120.1. Attributes:

AttributeMLIR TypeDescription
cleanup::mlir::UnitAttrunit attribute
handler_types::mlir::ArrayAttrcatch all or unwind or global view array attribute

1.1.121. cir.try_call (::cir::TryCallOp)

Try_call operation

Similar to cir.call but requires two destination blocks, one which is used if the call returns without throwing an exception (the “normal” destination) and another which is used if an exception is thrown (the “unwind” destination).

This operation is used only after the CFG flatterning pass.

Example:

// Before CFG flattening
cir.try {
  %call = cir.call @division(%a, %b) : () -> !s32i
  cir.yield
} catch all {
  cir.yield
}

// After CFG flattening
%call = cir.try_call @division(%a, %b) ^normalDest, ^unwindDest
  : (f32, f32) -> f32
^normalDest:
  cir.br ^afterTryBlock
^unwindDest:
  %exception_ptr, %type_id = cir.eh.inflight_exception
  cir.br ^catchHandlerBlock(%exception_ptr : !cir.ptr<!void>)
^catchHandlerBlock:
  ...

Traits: Terminator

Interfaces: ArgAndResultAttrsOpInterface, CIRCallOpInterface, CallOpInterface, SymbolUserOpInterface

1.1.121.1. Attributes:

AttributeMLIR TypeDescription
callee::mlir::FlatSymbolRefAttrflat symbol reference attribute
nothrow::mlir::UnitAttrunit attribute
musttail::mlir::UnitAttrunit attribute
side_effect::cir::SideEffectAttrallowed side effects of a function
arg_attrs::mlir::ArrayAttrArray of dictionary attributes
res_attrs::mlir::ArrayAttrArray of dictionary attributes

1.1.121.2. Operands:

Operand

Description

args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.121.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.121.4. Successors:

Successor

Description

normalDest

any successor

unwindDest

any successor

1.1.122. cir.try_throw (::cir::TryThrowOp)

Throw an exception with an unwind destination

Syntax:

operation ::= `cir.try_throw` ($exception_ptr^ `:` type($exception_ptr))?
              (`,` $type_info^)?
              (`,` $dtor^)?
              $normalDest `,` $unwindDest
              attr-dict

Similar to cir.throw but acts as a terminator with two destination blocks: a normalDest that should contain a cir.unreachable operation (since a throw never returns) and an unwindDest that receives control when the throw needs to unwind through an enclosing cleanup or catch handler. This is the EH counterpart of cir.throw, analogous to how cir.try_call is the EH counterpart of cir.call.

Like cir.throw, the absence of operands means rethrow. With operands, it carries the same exception pointer, type info, and optional destructor as cir.throw.

This operation is produced by the FlattenCFG pass for cir.throw operations that appear inside a cleanup scope or try region. It is later lowered by the EHABI lowering pass to a cir.try_call of __cxa_throw (or __cxa_rethrow).

Example:

cir.try_throw %exception_addr : !cir.ptr<!s32i>, @_ZTIi
    ^normalDest, ^unwindDest
^normalDest:
  cir.unreachable
^unwindDest:
  ...

Traits: Terminator

1.1.122.1. Attributes:

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

1.1.122.2. Operands:

Operand

Description

exception_ptr

CIR pointer type

1.1.122.3. Successors:

Successor

Description

normalDest

any successor

unwindDest

any successor

1.1.123. cir.unreachable (::cir::UnreachableOp)

Invoke immediate undefined behavior

Syntax:

operation ::= `cir.unreachable` attr-dict

If the program control flow reaches a cir.unreachable operation, the program exhibits undefined behavior immediately. This operation is useful in cases where the unreachability of a program point needs to be explicitly marked.

Traits: Terminator

1.1.124. 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)

The cir.va_arg operation models the C/C++ va_arg macro by reading the next argument from an active variable argument list and producing it as a value of a specified result type.

The operand must be a pointer to the target’s va_list representation. The operation advances the va_list state as a side effect and returns the fetched value as the result, whose type is chosen by the user of the operation.

A cir.va_arg must only be used on a va_list that has been initialized with cir.va.start and not yet finalized by cir.va.end. The semantics (including alignment and promotion rules) follow the platform ABI; the frontend is responsible for providing a va_list pointer that matches the target representation.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
        : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
        -> !cir.ptr<!rec___va_list_tag>
cir.va.start %p : !cir.ptr<!rec___va_list_tag>

// Fetch an `int` from the vararg list.
%v = cir.va_arg %p : (!cir.ptr<!rec___va_list_tag>) -> !s32i

cir.va.end %p : !cir.ptr<!rec___va_list_tag>

1.1.124.1. Operands:

Operand

Description

arg_list

CIR pointer type

1.1.124.2. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.125. cir.va_copy (::cir::VACopyOp)

Copied a variable argument list

Syntax:

operation ::= `cir.va_copy` $src_list `to` $dst_list attr-dict `:` type(operands)

The cir.copy operation models the C/C++ va_copy macro. The variable argument list passed as the $src_list is copied to an unitialized va_list in the destination operand. The next argument that can be extracted from the copied list is the same as the next argument in the source list. The copied list must be destroyed with va_end.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
      : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
      -> !cir.ptr<!rec___va_list_tag>
cir.va_copy %p to %dst
      : (!cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>)

1.1.125.1. Operands:

Operand

Description

dst_list

CIR pointer type

src_list

CIR pointer type

1.1.126. cir.va_end (::cir::VAEndOp)

Ends a variable argument list

Syntax:

operation ::= `cir.va_end` $arg_list attr-dict `:` type(operands)

The cir.va_end operation models the C/C++ va_end macro by finalizing and cleaning up a variable argument list previously initialized with cir.va_start.

The operand must be a pointer to the target’s va_list representation. This operation has no results and produces its effect by mutating the storage referenced by the pointer operand.

cir.va_end must only be called after a matching cir.va_start on the same va_list along all control-flow paths. After cir.va_end, the va_list is invalid and must not be accessed unless reinitialized.

Lowering typically maps this to the LLVM intrinsic llvm.va_end, passing the appropriately decayed pointer to the underlying va_list storage.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
      : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
      -> !cir.ptr<!rec___va_list_tag>
cir.va_end %p : !cir.ptr<!rec___va_list_tag>

1.1.126.1. Operands:

Operand

Description

arg_list

CIR pointer type

1.1.127. cir.va_start (::cir::VAStartOp)

Starts a variable argument list

Syntax:

operation ::= `cir.va_start` $arg_list attr-dict `:` type(operands)

The cir.va_start operation models the C/C++ va_start macro by initializing a variable argument list at the given va_list storage location.

The operand must be a pointer to the target’s va_list representation. This operation has no results and produces its effect by mutating the storage referenced by the pointer operand.

Each cir.va_start must be paired with a corresponding cir.va_end on the same logical va_list object along all control-flow paths. After cir.va_end, the va_list must not be accessed unless reinitialized with another cir.va_start.

Lowering maps this to the LLVM intrinsic llvm.va_start, passing the appropriately decayed pointer to the underlying va_list storage.

Example:

// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
      : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>)
      -> !cir.ptr<!rec___va_list_tag>
cir.va_start %p : !cir.ptr<!rec___va_list_tag>

1.1.127.1. Operands:

Operand

Description

arg_list

CIR pointer type

1.1.128. cir.vec.cmp (::cir::VecCmpOp)

Compare two vectors

Syntax:

operation ::= `cir.vec.cmp` `(` $kind `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
              qualified(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.

%eq = cir.vec.cmp(eq, %vec_a, %vec_b) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>
%lt = cir.vec.cmp(lt, %vec_a, %vec_b) : !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait, SameTypeOperands

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.128.1. Attributes:

AttributeMLIR TypeDescription
kind::cir::CmpOpKindAttrcompare operation kind

1.1.128.2. Operands:

Operand

Description

lhs

CIR vector type

rhs

CIR vector type

1.1.128.3. Results:

Result

Description

result

CIR vector type

1.1.129. cir.vec.create (::cir::VecCreateOp)

Create a vector value

Syntax:

operation ::= `cir.vec.create` `(` ($elements^ `:` type($elements))? `)` `:` qualified(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{}

1.1.129.1. Operands:

Operand

Description

elements

variadic of any cir boolean, integer, floating point or pointer type

1.1.129.2. Results:

Result

Description

result

CIR vector type

1.1.130. cir.vec.extract (::cir::VecExtractOp)

Extract one element from a vector object

Syntax:

operation ::= `cir.vec.extract` $vec `[` $index `:` type($index) `]` attr-dict `:` qualified(type($vec))

The cir.vec.extract operation extracts the element at the given index from a vector object.

%tmp = cir.load %vec : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
%idx = cir.const #cir.int<1> : !s32i
%element = cir.vec.extract %tmp[%idx : !s32i] : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.130.1. Operands:

Operand

Description

vec

CIR vector type

index

fundamental integer type

1.1.130.2. Results:

Result

Description

result

any cir boolean, integer, floating point or pointer type

1.1.131. cir.vec.insert (::cir::VecInsertOp)

Insert one element into a vector object

Syntax:

operation ::= `cir.vec.insert` $value `,` $vec `[` $index `:` type($index) `]` attr-dict `:`
              qualified(type($vec))

The cir.vec.insert operation produces a new vector by replacing the element of the input vector at index with value.

%value = cir.const #cir.int<5> : !s32i
%index = cir.const #cir.int<2> : !s32i
%vec_tmp = cir.load %0 : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
%new_vec = cir.vec.insert %value, %vec_tmp[%index : !s32i] : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.131.1. Operands:

Operand

Description

vec

CIR vector type

value

any cir boolean, integer, floating point or pointer type

index

fundamental integer type

1.1.131.2. Results:

Result

Description

result

CIR vector type

1.1.132. cir.vec.masked_load (::cir::VecMaskedLoadOp)

Masked vector load from memory

Syntax:

operation ::= `cir.vec.masked_load` (`align` `(` $alignment^ `)`)?
              $addr `,` $mask `,` $pass_thru
              `:` qualified(type($addr)) `,` type($mask) `,` type($pass_thru)
              `->` type($result)
              attr-dict

cir.masked_load conditionally loads elements from memory based on a mask. Elements for which the mask is false are taken from pass_thru.

This operation corresponds to LLVM’s masked load op (llvm.intr.maskedload) and lower directly to it.

alignment can be provided to override the default alignment derived from the pointee/element type data layout.

Example:

%v = cir.masked_load align(16) %ptr, %mask, %passthru
     : !cir.ptr<i32>, <4xi1>, <4xi32> -> <4xi32>

Interfaces: InferTypeOpInterface

1.1.132.1. Attributes:

AttributeMLIR TypeDescription
alignment::mlir::IntegerAttr64-bit signless integer attribute whose value is positive and whose value is a power of two > 0

1.1.132.2. Operands:

Operand

Description

addr

CIR pointer type

mask

CIR vector type

pass_thru

CIR vector type

1.1.132.3. Results:

Result

Description

result

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.133. cir.vec.shuffle (::cir::VecShuffleOp)

Combine two vectors using indices passed as constant integers

Syntax:

operation ::= `cir.vec.shuffle` `(` $vec1 `,` $vec2 `:` qualified(type($vec1)) `)` $indices `:`
              qualified(type($result)) attr-dict

The cir.vec.shuffle operation implements the documented form of Clang’s __builtin_shufflevector, where the indices of the shuffled result are integer constants.

The two input vectors, which must have the same type, are concatenated. Each of the integer constant arguments is interpreted as an index into that concatenated vector, with a value of -1 meaning that the result value doesn’t matter. The result vector, which must have the same element type as the input vectors and the same number of elements as the list of integer constant indices, is constructed by taking the elements at the given indices from the concatenated vector. The size of the result vector does not have to match the size of the individual input vectors or of the concatenated vector.

%new_vec = cir.vec.shuffle(%vec_1, %vec_2 : !cir.vector<2 x !s32i>)
    [#cir.int<3> : !s64i, #cir.int<1> : !s64i] : !cir.vector<2 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.133.1. Attributes:

AttributeMLIR TypeDescription
indices::mlir::ArrayAttrinteger array attribute

1.1.133.2. Operands:

Operand

Description

vec1

CIR vector type

vec2

CIR vector type

1.1.133.3. Results:

Result

Description

result

CIR vector type

1.1.134. cir.vec.shuffle.dynamic (::cir::VecShuffleDynamicOp)

Shuffle a vector using indices in another vector

Syntax:

operation ::= `cir.vec.shuffle.dynamic` $vec `:` qualified(type($vec)) `,` $indices `:` qualified(type($indices))
              attr-dict

The cir.vec.shuffle.dynamic operation implements the undocumented form of Clang’s __builtin_shufflevector, where the indices of the shuffled result can be runtime values.

There are two input vectors, which must have the same number of elements. The second input vector must have an integral element type. The elements of the second vector are interpreted as indices into the first vector. The result vector is constructed by taking the elements from the first input vector from the indices indicated by the elements of the second vector.

%new_vec = cir.vec.shuffle.dynamic %vec : !cir.vector<4 x !s32i>, %indices
    : !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.134.1. Operands:

Operand

Description

vec

CIR vector type

indices

vector of integer type

1.1.134.2. Results:

Result

Description

result

CIR vector type

1.1.135. cir.vec.splat (::cir::VecSplatOp)

Convert a scalar into a vector

Syntax:

operation ::= `cir.vec.splat` $value `:` type($value) `,` qualified(type($result)) attr-dict

The cir.vec.splat operation creates a vector value from a scalar value. All elements of the vector have the same value, that of the given scalar.

It’s a separate operation from cir.vec.create because more efficient LLVM IR can be generated for it, and because some optimization and analysis passes can benefit from knowing that all elements of the vector have the same value.

%value = cir.const #cir.int<3> : !s32i
%value_vec = cir.vec.splat %value : !s32i, !cir.vector<4 x !s32i>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.135.1. Operands:

Operand

Description

value

any cir boolean, integer, floating point or pointer type

1.1.135.2. Results:

Result

Description

result

CIR vector type

1.1.136. cir.vec.ternary (::cir::VecTernaryOp)

The cond ? a : b ternary operator for vector types

Syntax:

operation ::= `cir.vec.ternary` `(` $cond `,` $lhs`,` $rhs `)` `:` qualified(type($cond)) `,`
              qualified(type($lhs)) attr-dict

The cir.vec.ternary operation represents the C/C++ ternary operator, ?:, for vector types, which does a select on individual elements of the vectors. Unlike a regular ?: operator, there is no short circuiting. All three arguments are always evaluated. Because there is no short circuiting, there are no regions in this operation, unlike cir.ternary.

The first argument is a vector of integral type. The second and third arguments are vectors of the same type and have the same number of elements as the first argument.

The result is a vector of the same type as the second and third arguments. Each element of the result is (bool)a[n] ? b[n] : c[n].

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.136.1. Operands:

Operand

Description

cond

vector of integer type

lhs

CIR vector type

rhs

CIR vector type

1.1.136.2. Results:

Result

Description

result

CIR vector type

1.1.137. cir.vtable.address_point (::cir::VTableAddrPointOp)

Get the vtable (global variable) address point

Syntax:

operation ::= `cir.vtable.address_point` `(`
              $name `,` `address_point` `=` $address_point
              `)`
              `:` qualified(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.

address_point.index (vtable index) provides the appropriate vtable within the vtable group (as specified by Itanium ABI), and address_point.offset (address point index) the actual address point within that vtable.

The return type is always !cir.vptr.

Example:

cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B,
          address_point = <index = 0, offset = 2>) : !cir.vptr

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface

Effects: MemoryEffects::Effect{}

1.1.137.1. Attributes:

AttributeMLIR TypeDescription
name::mlir::FlatSymbolRefAttrflat symbol reference attribute
address_point::cir::AddressPointAttrAddress point attribute

1.1.137.2. Results:

Result

Description

addr

CIR type that is used for the vptr member of C++ objects

1.1.138. cir.vtable.get_type_info (::cir::VTableGetTypeInfoOp)

Get the address of the type_info from the vtable

Syntax:

operation ::= `cir.vtable.get_type_info` $vptr attr-dict `:` qualified(type($vptr)) `->` qualified(type($result))

The vtable.get_type_info operation retreives the address of the dynamic type_info/rtti object from an object’s vtable. This is an ABI independent abstraction of this operation.

The vptr operand must be a !cir.vptr value, which would have been returned by a previous call to cir.vtable.get_vptr.

The return type is a loadable pointer to a type_info struct.

Example:

%5 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_A> -> !cir.ptr<!cir.vptr>
%6 = cir.load align(8) %5 : !cir.ptr<!cir.vptr>, !cir.vptr
%7 = cir.vtable.get_type_info %6 : !cir.vptr -> !cir.ptr<!cir.ptr<!rec_std3A3Atype_info>>
%8 = cir.load align(8) %7 : !cir.ptr<!cir.ptr<!rec_std3A3Atype_info>>, !cir.ptr<!rec_std3A3Atype_info>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.138.1. Operands:

Operand

Description

vptr

CIR type that is used for the vptr member of C++ objects

1.1.138.2. Results:

Result

Description

result

CIR pointer type

1.1.139. cir.vtable.get_virtual_fn_addr (::cir::VTableGetVirtualFnAddrOp)

Get a the address of a virtual function pointer

Syntax:

operation ::= `cir.vtable.get_virtual_fn_addr` $vptr `[` $index `]` attr-dict
              `:` qualified(type($vptr)) `->` qualified(type($result))

The vtable.get_virtual_fn_addr operation retrieves the address of a virtual function pointer from an object’s vtable (__vptr). This is an abstraction to perform the basic pointer arithmetic to get the address of the virtual function pointer, which can then be loaded and called.

The vptr operand must be a !cir.ptr<!cir.vptr> value, which would have been returned by a previous call to cir.vtable.get_vptr. The index operand is an index of the virtual function in the vtable.

The return type is a pointer-to-pointer to the function type.

Example:

%2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_C>>, !cir.ptr<!rec_C>
%3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_C> -> !cir.ptr<!cir.vptr>
%4 = cir.load %3 : !cir.ptr<!cir.vptr>, !cir.vptr
%5 = cir.vtable.get_virtual_fn_addr %4[2] : !cir.vptr
              -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>>
%6 = cir.load align(8) %5 : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_C>)
                                                             -> !s32i>>>,
                            !cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>
%7 = cir.call %6(%2) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>,
                        !cir.ptr<!rec_C>) -> !s32i

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.139.1. Attributes:

AttributeMLIR TypeDescription
index::mlir::IntegerAttr64-bit signless integer attribute

1.1.139.2. Operands:

Operand

Description

vptr

CIR type that is used for the vptr member of C++ objects

1.1.139.3. Results:

Result

Description

result

CIR pointer type

1.1.140. cir.vtable.get_vptr (::cir::VTableGetVPtrOp)

Get a the address of the vtable pointer for an object

Syntax:

operation ::= `cir.vtable.get_vptr` $src `:` qualified(type($src)) `->` qualified(type($result)) attr-dict

The vtable.get_vptr operation retrieves the address of the vptr for a C++ object. This operation requires that the object pointer points to the start of a complete object. (TODO: Describe how we get that). The vptr will always be at offset zero in the object, but this operation is more explicit about what is being retrieved than a direct bitcast.

The return type is always !cir.ptr<!cir.vptr>.

Example:

%2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_C>>, !cir.ptr<!rec_C>
%3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_C> -> !cir.ptr<!cir.vptr>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.140.1. Operands:

Operand

Description

src

CIR pointer type

1.1.140.2. Results:

Result

Description

result

pointer to vptr type

1.1.141. cir.vtt.address_point (::cir::VTTAddrPointOp)

Get the VTT address point

Syntax:

operation ::= `cir.vtt.address_point` ($name^)?
              ($sym_addr^ `:` type($sym_addr))?
              `,`
              `offset` `=` $offset
              `->` qualified(type($addr)) attr-dict

The vtt.address_point operation retrieves an element from the virtual table table (VTT), which is the address point of a C++ vtable. In virtual inheritance, a set of internal __vptr members for an object are initialized by this operation, which assigns an element from the VTT. The initialization order is as follows:

The complete object constructors and destructors find the VTT, via the mangled name of the VTT global variable. They pass the address of the subobject’s sub-VTT entry in the VTT as a second parameter when calling the base object constructors and destructors. The base object constructors and destructors use the address passed to initialize the primary virtual pointer and virtual pointers that point to the classes which either have virtual bases or override virtual functions with a virtual step.

The first parameter is either the mangled name of VTT global variable or the address of the subobject’s sub-VTT entry in the VTT. The second parameter offset provides a virtual step to adjust to the actual address point of the vtable.

The return type is always a !cir.ptr<!cir.ptr<void>>.

Example:

cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.base_class_addr(%1 : !cir.ptr<!rec_D> nonnull) [0]
         -> !cir.ptr<!rec_B>
%4 = cir.vtt.address_point @_ZTT1D, offset = 1
         -> !cir.ptr<!cir.ptr<!void>>
cir.call @_ZN1BC2Ev(%3, %4)

Or:

%7 = cir.vtt.address_point %3 : !cir.ptr<!cir.ptr<!void>>, offset = 1
         -> !cir.ptr<!cir.ptr<!void>>

Traits: AlwaysSpeculatableImplTrait

Interfaces: ConditionallySpeculatable, NoMemoryEffect (MemoryEffectOpInterface), SymbolUserOpInterface

Effects: MemoryEffects::Effect{}

1.1.141.1. Attributes:

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

1.1.141.2. Operands:

Operand

Description

sym_addr

CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.1.141.3. Results:

Result

Description

addr

CIR pointer type

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

1.1.143. cir.xor (::cir::XorOp)

Bitwise XOR

Syntax:

operation ::= `cir.xor` $lhs `,` $rhs `:` type($lhs) attr-dict

The cir.xor operation performs a bitwise XOR on integer operands. Both operands and the result must have the same integer type.

Example:

%0 = cir.xor %a, %b : !s32i
%1 = cir.xor %a, %b : !cir.bool

Traits: Commutative, SameOperandsAndResultType

Interfaces: BinaryOpInterface, InferTypeOpInterface, NoMemoryEffect (MemoryEffectOpInterface)

Effects: MemoryEffects::Effect{}

1.1.143.1. Operands:

Operand

Description

lhs

integer, boolean, or vector of integer

rhs

integer, boolean, or vector of integer

1.1.143.2. Results:

Result

Description

result

integer, boolean, or vector of integer

1.1.144. 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<ArrayCtor, ArrayDtor, AwaitOp, CaseOp, CleanupScopeOp, CoroBodyOp, DoWhileOp, ForOp, GlobalOp, IfOp, LocalInitOp, ScopeOp, SwitchOp, TernaryOp, TryOp, WhileOp>, ReturnLike, Terminator

Interfaces: NoMemoryEffect (MemoryEffectOpInterface), RegionBranchTerminatorOpInterface

Effects: MemoryEffects::Effect{}

1.1.144.1. Operands:

Operand

Description

args

variadic of CIR void type or CIR bool type or CIR array type or CIR vector type or Integer type with arbitrary precision up to a fixed limit or single float type or double float type or f16 type or bf16 type or f80 type or f128 type or long double type or CIR pointer type or CIR function type or CIR struct/class type or CIR union type or CIR complex type or CIR type that is used for the vptr member of C++ objects or CIR type that represents a pointer-to-data-member in C++ or CIR type that represents C++ pointer-to-member-function type or CIR exception handling token type or CIR cleanup token type or CIR catch token type

1.2. Attributes

1.2.1. ASTVarDeclAttr

Wraps a ‘const clang::VarDecl *’ AST node.

Operations optionally refer to this node, they could be available depending on the CIR lowering stage. Whether it’s attached to the appropriate CIR operation is delegated to the operation verifier.

Note: the AST pointer can be null when CIR is parsed from text, since there is no serialization support for AST nodes yet.

1.2.1.1. Parameters:

Parameter

C++ type

Description

ast

const clang::VarDecl *

1.2.2. AddressPointAttr

Address point attribute

Syntax:

#cir.address_point<
  int32_t,   # index
  int32_t   # offset
>

Attribute specifying the address point within a C++ virtual table (vtable).

The index (vtable index) parameter identifies which vtable to use within a vtable group, while the offset (address point index) specifies the offset within that vtable where the address begins.

Example:

cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B,
                              address_point = <index = 0, offset = 2>)
                             : !cir.vptr

1.2.2.1. Parameters:

Parameter

C++ type

Description

index

int32_t

offset

int32_t

1.2.3. AnnotationAttr

Annotation attribute for global variables and functions

Syntax:

#cir.annotation<
  ::mlir::StringAttr,   # name
  mlir::ArrayAttr   # args
>

Represents a C/C++ __attribute__((annotate(...))) in CIR.

Example C code:

int *a __attribute__((annotate("testptr", "21", 12)));

In CIR, the attribute for above annotation looks like:

[#cir.annotation<"testptr", ["21", 12 : i32]>]

1.2.3.1. Parameters:

Parameter

C++ type

Description

name

::mlir::StringAttr

args

mlir::ArrayAttr

1.2.4. BitfieldInfoAttr

Represents info for a bit-field member

Syntax:

#cir.bitfield_info<
  mlir::StringAttr,   # name
  mlir::Type,   # storage_type
  uint64_t,   # size
  uint64_t,   # offset
  bool   # is_signed
>

Holds the following information about bitfields: name, storage type, size and position in the storage, and signedness. Example: Given the following struct with bitfields: c++     typedef struct {       int a : 4;       int b : 27;       int c : 17;       int d : 2;       int e : 15;     } S;    

The CIR representation of the struct S might look like:

  !rec_S = !cir.record<struct "S" packed padded {!u64i, !u16i,
                                                 !cir.array<!u8i x 2>}>

And the bitfield info attribute for member a would be:

  #bfi_a = #cir.bitfield_info<name = "a", storage_type = !u64i,
                              size = 4, offset = 0, is_signed = true>

This metadata describes that field a is stored in a 64-bit integer, is 4 bits wide, starts at offset 0, and is signed.

1.2.4.1. Parameters:

Parameter

C++ type

Description

name

mlir::StringAttr

storage_type

mlir::Type

size

uint64_t

offset

uint64_t

is_signed

bool

1.2.5. BlockAddrInfoAttr

Block address attribute

Syntax:

#cir.block_addr_info<
  cir::PointerType,   # type
  mlir::FlatSymbolRefAttr,   # func
  mlir::StringAttr   # label
>

This attribute is used to represent the address of a basic block within a function. It combines the symbol reference to a function with the name of a label inside that function.

1.2.5.1. Parameters:

Parameter

C++ type

Description

type

cir::PointerType

func

mlir::FlatSymbolRefAttr

label

mlir::StringAttr

1.2.6. BoolAttr

Represent true/false for !cir.bool types

Syntax:

#cir.bool<
  cir::BoolType,   # type
  bool   # value
>

The BoolAttr represents a ‘true’ or ‘false’ value.

1.2.6.1. Parameters:

Parameter

C++ type

Description

type

cir::BoolType

value

bool

1.2.7. CUDABinaryHandleAttr

Fat binary handle for device code.

Syntax:

#cir.cu.binary_handle<
  mlir::StringAttr   # name
>

This attribute is attached to the ModuleOp and records the binary file name passed to host.

CUDA first compiles device-side code into a fat binary file. The file name is then passed into host-side code, which is used to create a handle and then generate various registration functions.

1.2.7.1. Parameters:

Parameter

C++ type

Description

name

mlir::StringAttr

1.2.8. CUDAExternallyInitializedAttr

The marked variable is externally initialized.

Syntax: #cir.cu.externally_initialized

CUDA device and constant variables, along with surface and textures, might be initialized by host, hence “externally initialized”. Therefore they must be emitted even if they are not referenced.

The attribute corresponds to the attribute on LLVM with the same name.

1.2.9. CUDAKernelNameAttr

Device-side function name for this stub.

Syntax:

#cir.cu.kernel_name<
  mlir::StringAttr   # kernel_name
>

This attribute is attached to function definitions and records the mangled name of the kernel function used on the device.

In CUDA, global functions (kernels) are processed differently for host and device. On host, Clang generates device stubs; on device, they are treated as normal functions. As they probably have different mangled names, we must record the corresponding device-side name for a stub. Preserving the device-side kernel name is crucial for performing its respective function runtime registration on the host.

1.2.9.1. Parameters:

Parameter

C++ type

Description

kernel_name

mlir::StringAttr

1.2.10. CUDAVarRegistrationInfoAttr

Device variable registration flags.

1.2.10.1. Parameters:

Parameter

C++ type

Description

device_side_name

std::string

kind

CUDADeviceVarKind

isExtern

bool

isConstant

bool

isManaged

bool

1.2.11. CXXAssignAttr

Marks a function as a CXX assignment operator

Syntax:

#cir.cxx_assign<
  mlir::Type,   # type
  `copy` | `move`,   # assign_kind
  bool   # is_trivial
>

This attribute identifies a C++ assignment operator and classifies its kind:

  • copy: a copy assignment

  • move: a move assignment

1.2.11.1. Parameters:

Parameter

C++ type

Description

type

mlir::Type

assign_kind

::cir::AssignKind

an enum of type AssignKind

is_trivial

bool

1.2.12. CXXCtorAttr

Marks a function as a C++ constructor

Syntax:

#cir.cxx_ctor<
  mlir::Type,   # type
  `custom` | `default` | `copy` | `move`,   # ctor_kind
  bool   # is_trivial
>

This attribute identifies a C++ constructor and classifies its kind:

  • custom: a user-defined constructor

  • default: a default constructor

  • copy: a copy constructor

  • move: a move constructor

Example:

#cir.cxx_ctor<!rec_a, copy>
#cir.cxx_ctor<!rec_b, default, trivial>

1.2.12.1. Parameters:

Parameter

C++ type

Description

type

mlir::Type

ctor_kind

::cir::CtorKind

an enum of type CtorKind

is_trivial

bool

1.2.13. CXXDtorAttr

Marks a function as a CXX destructor

Syntax:

#cir.cxx_dtor<
  mlir::Type,   # type
  bool   # is_trivial
>

This attribute identifies a C++ destructor.

1.2.13.1. Parameters:

Parameter

C++ type

Description

type

mlir::Type

is_trivial

bool

1.2.14. CatchAllAttr

Syntax: #cir.all

1.2.15. CleanupKindAttr

Cleanup kind attribute

Syntax:

#cir.cleanup_kind<
  `normal` | `eh` | `all`   # value
>

Cleanup kind attributes.

1.2.15.1. Parameters:

Parameter

C++ type

Description

value

::cir::CleanupKind

an enum of type CleanupKind

1.2.16. CmpThreeWayInfoAttr

Holds information about a three-way comparison operation

Syntax:

#cir.cmp3way_info<
  `strong` | `weak` | `partial`,   # ordering
  int64_t,   # lt
  int64_t,   # eq
  int64_t,   # gt
  std::optional<int64_t>   # unordered
>

The #cmpinfo attribute contains information about a three-way comparison operation cir.cmp3way.

The ordering parameter gives the ordering kind of the three-way comparison operation: strong ordering, weak ordering, or partial ordering. Strong and weak orderings are both total orderings (i.e. every two elements are comparable), while partial orderings can have incomparable elements.

Given the two input operands of the three-way comparison operation lhs and rhs, the lt, eq, gt, and unordered parameters gives the result value that should be produced by the three-way comparison operation when the ordering between lhs and rhs is lhs < rhs, lhs == rhs, lhs > rhs, or neither, respectively.

Example:

!s32i = !cir.int<s, 32>

#cmpinfo_partial_ltn1eq0gt1unn127 = #cir.cmp3way_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>
#cmpinfo_strong_ltn1eq0gt1 = #cir.cmp3way_info<strong, lt = -1, eq = 0, gt = 1>

%0 = cir.const #cir.int<0> : !s32i
%1 = cir.const #cir.int<1> : !s32i
%2 = cir.cmp3way(%0 : !s32i, %1, #cmpinfo_strong_ltn1eq0gt1) : !s8i

%3 = cir.const #cir.fp<0.0> : !cir.float
%4 = cir.const #cir.fp<1.0> : !cir.float
%5 = cir.cmp3way(%3 : !cir.float, %4, #cmpinfo_partial_ltn1eq0gt1unn127) : !s8

1.2.16.1. Parameters:

Parameter

C++ type

Description

ordering

::cir::CmpOrdering

an enum of type CmpOrdering

lt

int64_t

eq

int64_t

gt

int64_t

unordered

std::optional<int64_t>

1.2.17. ConstArrayAttr

A constant array from ArrayAttr or StringRefAttr

An CIR array attribute is an array of literals of the specified attr types.

1.2.17.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

elts

mlir::Attribute

trailingZerosNum

int

1.2.18. ConstComplexAttr

An attribute that contains a constant complex value

Syntax:

#cir.const_complex<
  cir::ComplexType,   # type
  ::mlir::TypedAttr,   # real
  ::mlir::TypedAttr   # imag
>

The #cir.const_complex attribute contains a constant value of complex number type. The real parameter gives the real part of the complex number and the imag parameter gives the imaginary part of the complex number.

The real and imag parameters must both reference the same type and must be either IntAttr or FPAttr.

%ci = #cir.const_complex<#cir.int<1> : !s32i, #cir.int<2> : !s32i>
    : !cir.complex<!s32i>
%cf = #cir.const_complex<#cir.fp<1.000000e+00> : !cir.float,
    #cir.fp<2.000000e+00> : !cir.float> : !cir.complex<!cir.float>

1.2.18.1. Parameters:

Parameter

C++ type

Description

type

cir::ComplexType

real

::mlir::TypedAttr

integer or floating point type

imag

::mlir::TypedAttr

integer or floating point type

1.2.19. ConstPtrAttr

Holds a constant pointer value

Syntax:

#cir.ptr<
  ::cir::PointerType,   # type
  mlir::IntegerAttr   # value
>

A pointer attribute is a literal attribute that represents an integral value of a pointer type.

1.2.19.1. Parameters:

Parameter

C++ type

Description

type

::cir::PointerType

value

mlir::IntegerAttr

1.2.20. ConstRecordAttr

Represents a constant record

Syntax:

#cir.const_record<
  ::mlir::Type,   # type
  mlir::ArrayAttr   # members
>

Effectively supports “struct-like” constants. It’s must be built from an mlir::ArrayAttr instance where each element is a typed attribute (mlir::TypedAttribute).

Example:

cir.global external @rgb2 = #cir.const_record<{0 : i8,
                                               5 : i64, #cir.null : !cir.ptr<i8>
                                              }> : !cir.record<"", i8, i64, !cir.ptr<i8>>

1.2.20.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

members

mlir::ArrayAttr

1.2.21. ConstVectorAttr

A constant vector from ArrayAttr

Syntax:

#cir.const_vector<
  ::mlir::Type,   # type
  mlir::ArrayAttr   # elts
>

A CIR vector attribute is an array of literals of the specified attribute types.

1.2.21.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

elts

mlir::ArrayAttr

1.2.22. DataMemberAttr

Holds a constant data member pointer value

Syntax:

#cir.data_member<
  cir::DataMemberType,   # type
  mlir::DenseI32ArrayAttr   # member_path
>

A data member attribute is a literal attribute that represents a constant pointer-to-data-member value.

The member_path parameter is a GEP-like sequence of field indices navigating from classTy down to the pointed-to member. An absent member_path represents a null pointer-to-data-member.

Examples:

// int Point::*p = &Point::z  (z is field 2)
#cir.data_member<[2]> : !cir.data_member<!s32i in !rec_Point>

// int Derived::*p = &Derived::x  (Base subobject at [0], x at [0])
#cir.data_member<[0, 0]> : !cir.data_member<!s32i in !rec_Derived>

// null
#cir.data_member<null> : !cir.data_member<!s32i in !rec_Point>

1.2.22.1. Parameters:

Parameter

C++ type

Description

type

cir::DataMemberType

member_path

mlir::DenseI32ArrayAttr

1.2.23. DynamicCastInfoAttr

ABI specific information about a dynamic cast

Syntax:

#cir.dyn_cast_info<
  ::cir::GlobalViewAttr,   # src_rtti
  ::cir::GlobalViewAttr,   # dest_rtti
  mlir::FlatSymbolRefAttr,   # runtime_func
  mlir::FlatSymbolRefAttr,   # bad_cast_func
  ::cir::IntAttr   # offset_hint
>

Provide ABI specific information about a dynamic cast operation.

The src_rtti and the dest_rtti parameters give the RTTI of the source record type and the destination record type, respectively.

The runtime_func parameter gives the __dynamic_cast function which is provided by the runtime. The bad_cast_func parameter gives the __cxa_bad_cast function which is also provided by the runtime.

The offset_hint parameter gives the hint value that should be passed to the __dynamic_cast runtime function.

1.2.23.1. Parameters:

Parameter

C++ type

Description

src_rtti

::cir::GlobalViewAttr

Provides constant access to a global address

dest_rtti

::cir::GlobalViewAttr

Provides constant access to a global address

runtime_func

mlir::FlatSymbolRefAttr

bad_cast_func

mlir::FlatSymbolRefAttr

offset_hint

::cir::IntAttr

An attribute containing an integer value

1.2.24. FPAttr

An attribute containing a floating-point value

Syntax:

#cir.fp<
  ::cir::FPTypeInterface,   # type
  ::llvm::APFloat   # value
>

An fp attribute is a literal attribute that represents a floating-point value of the specified floating-point type. Supporting only CIR FP types.

1.2.24.1. Parameters:

Parameter

C++ type

Description

type

::cir::FPTypeInterface

value

::llvm::APFloat

1.2.25. GlobalCtorAttr

Marks a function as a global constructor

Syntax:

#cir.global_ctor<
  mlir::StringAttr,   # name
  int   # priority
>

Marks the function as a global constructor in the module’s constructor list. It will be executed before main() is called.

1.2.25.1. Parameters:

Parameter

C++ type

Description

name

mlir::StringAttr

priority

int

1.2.26. GlobalDtorAttr

Marks a function as a global destructor

Syntax:

#cir.global_dtor<
  mlir::StringAttr,   # name
  int   # priority
>

Marks a function as a global destructor in the module dtors list. The function will be executed before the module unloading.

1.2.26.1. Parameters:

Parameter

C++ type

Description

name

mlir::StringAttr

priority

int

1.2.27. GlobalViewAttr

Provides constant access to a global address

Syntax:

#cir.global_view<
  ::mlir::Type,   # type
  mlir::FlatSymbolRefAttr,   # symbol
  mlir::ArrayAttr   # indices
>

Get constant address of global symbol and optionally apply offsets to access existing subelements. It provides a way to access globals from other global and always produces a pointer.

The type of the input symbol can be different from #cir.global_view output type, since a given view of the global might require a static cast for initializing other globals.

A list of indices can be optionally passed and each element subsequently indexes underlying types. For symbol types like !cir.array and !cir.record, it leads to the constant address of sub-elements, while for !cir.ptr, an offset is applied. The first index is relative to the original symbol type, not the produced one.

The result type of this attribute may be an integer type. In such a case, the pointer to the referenced global is casted to an integer and this attribute represents the casted result.

Example:

  cir.global external @s = @".str2": !cir.ptr<i8>
  cir.global external @x = #cir.global_view<@s> : !cir.ptr<i8>
  cir.global external @s_addr = #cir.global_view<@s> : !s64i

  cir.global external @rgb = #cir.const_array<[0 : i8, -23 : i8, 33 : i8]
                                               : !cir.array<i8 x 3>>
  cir.global external @elt_ptr = #cir.global_view<@rgb, [1]> : !cir.ptr<i8>

Note, that unlike LLVM IR’s gep instruction, CIR doesn’t add the leading zero index when it’s known to be constant zero, e.g. for pointers, i.e. we use indexes exactly to access sub elements or for the offset. The leading zero index is added later in the lowering.

Example:

struct A {
  int a;
};

struct B:  virtual A {
  int b;
};

VTT for B in CIR:

cir.global linkonce_odr @_ZTT1B = #cir.const_array<[
          #cir.global_view<@_ZTV1B, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>]>
               : !cir.array<!cir.ptr<!u8i> x 1>

VTT for B in LLVM IR:

@_ZTT1B = linkonce_odr global [1 x ptr] [ptr getelementptr inbounds
          ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 3)], align 8

1.2.27.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

symbol

mlir::FlatSymbolRefAttr

indices

mlir::ArrayAttr

1.2.28. IntAttr

An attribute containing an integer value

Syntax:

#cir.int<
  cir::IntTypeInterface,   # type
  ::llvm::APInt   # value
>

An integer attribute is a literal attribute that represents an integral value of the specified integer type.

1.2.28.1. Parameters:

Parameter

C++ type

Description

type

cir::IntTypeInterface

value

::llvm::APInt

1.2.29. LangAddressSpaceAttr

Represents a language address space

Syntax:

#cir.lang_address_space<
  `default` | `offload_private` | `offload_local` | `offload_global` | `offload_constant` | `offload_generic` | `offload_global_device` | `offload_global_host`   # value
>

Encodes the semantic address spaces defined by the front-end language (e.g. __shared__, __constant__, __local__). Values are stored using the cir::LangAddressSpace enum, keeping the representation compact and preserving the qualifier until it is mapped onto target/LLVM address-space numbers.

Example:

!cir.ptr<!s32i, lang_address_space(offload_local)>
cir.global constant external lang_address_space(offload_constant)

1.2.29.1. Parameters:

Parameter

C++ type

Description

value

::cir::LangAddressSpace

an enum of type LangAddressSpace

1.2.30. MethodAttr

Holds a constant pointer-to-member-function value

A method attribute is a literal attribute that represents a constant pointer-to-member-function value.

If the member function is a non-virtual function, the symbol parameter gives the global symbol for the non-virtual member function.

If the member function is a virtual function, the vtable_offset parameter gives the offset of the vtable entry corresponding to the virtual member function.

symbol and vtable_offset cannot be present at the same time. If both of symbol and vtable_offset are not present, the attribute represents a null pointer constant.

Examples:

// Non-virtual method
%0 = cir.const #cir.method<@_ZN1S2m1Ei> :
         !cir.method<!cir.func<(!s32i)> in !rec_S>

// Virtual method
%1 = cir.const #cir.method<vtable_offset = 8> :
         !cir.method<!cir.func<(!s32i)> in !rec_S>

// Null method pointer
%0 = cir.const #cir.method<null> :
         !cir.method<!cir.func<(!s32i)> in !rec_S>

1.2.30.1. Parameters:

Parameter

C++ type

Description

type

cir::MethodType

symbol

std::optional<mlir::FlatSymbolRefAttr>

vtable_offset

std::optional<uint64_t>

1.2.31. OpenCLKernelArgMetadataAttr

OpenCL kernel argument metadata

Syntax:

#cir.cl.kernel_arg_metadata<
  ::mlir::ArrayAttr,   # addr_space
  ::mlir::ArrayAttr,   # access_qual
  ::mlir::ArrayAttr,   # type
  ::mlir::ArrayAttr,   # base_type
  ::mlir::ArrayAttr,   # type_qual
  ::mlir::ArrayAttr   # name
>

Stores the OpenCL kernel argument metadata emitted to LLVM IR as kernel_arg_* metadata.

All parameters are arrays containing the argument information in source order. The name field is optional and is emitted only when requested by -cl-kernel-arg-info.

1.2.31.1. Parameters:

Parameter

C++ type

Description

addr_space

::mlir::ArrayAttr

language address space array attribute

access_qual

::mlir::ArrayAttr

string array attribute

type

::mlir::ArrayAttr

string array attribute

base_type

::mlir::ArrayAttr

string array attribute

type_qual

::mlir::ArrayAttr

string array attribute

name

::mlir::ArrayAttr

string array attribute or null

1.2.32. OptInfoAttr

A module-level attribute that holds the optimization information

Syntax:

#cir.opt_info<
  unsigned,   # level
  unsigned   # size
>

The #cir.opt_info attribute holds optimization related information. For now this attribute is a module-level attribute that gets attached to the module operation during CIRGen.

The level parameter gives the optimization level. It must be an integer between 0 and 3, inclusive. It corresponds to the OptimizationLevel field within the clang::CodeGenOptions structure.

The size parameter gives the code size optimization level. It must be an integer between 0 and 2, inclusive. It corresponds to the OptimizeSize field within the clang::CodeGenOptions structure.

The level and size parameters correspond to the optimization level command line options passed to clang driver. The table below lists the current correspondance relationship:

Flag

level

size

-O0 or nothing

0

0

-O1

1

0

-O2

2

0

-O3

3

0

-Os

2

1

-Oz

2

2

Examples:

#cir.opt_info<level = 2, size = 0>  // -O2

1.2.32.1. Parameters:

Parameter

C++ type

Description

level

unsigned

size

unsigned

1.2.33. PoisonAttr

Represent a typed poison constant

Syntax:

#cir.poison<
  ::mlir::Type   # type
>

The PoisonAttr represents a typed poison constant, corresponding to LLVM’s notion of poison.

1.2.33.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

1.2.34. RecordLayoutAttr

ABI layout metadata for a record type

Syntax:

#cir.record_layout<
  `can_pass_in_regs` | `cannot_pass_in_regs` | `can_never_pass_in_regs`,   # arg_passing_kind
  bool,   # has_trivial_dtor
  uint64_t   # record_align
>

Holds AST-derived ABI metadata for a named record type. These properties are translation-unit / target properties, not intrinsic to the type, so they live on the module rather than on RecordType.

Fields:

  • arg_passing_kind: whether the record can be passed in registers per the C++ ABI (mirrors RecordDecl::getArgPassingRestrictions()).

  • has_trivial_destructor: from CXXRecordDecl::hasTrivialDestructor().

  • record_align_in_bytes: from ASTRecordLayout::getAlignment(). Needed because CIR’s DataLayout cannot account for __attribute__((aligned(N))).

Example:

module attributes {
  cir.record_layouts = {
    "Trivial" = #cir.record_layout<
      arg_passing_kind = can_pass_in_regs,
      has_trivial_dtor = true,
      record_align = 4>,
    "NonTrivialDtor" = #cir.record_layout<
      arg_passing_kind = cannot_pass_in_regs,
      has_trivial_dtor = false,
      record_align = 4>
  }
}

1.2.34.1. Parameters:

Parameter

C++ type

Description

arg_passing_kind

::cir::ArgPassingKind

an enum of type ArgPassingKind

has_trivial_dtor

bool

record_align

uint64_t

1.2.35. SourceLanguageAttr

Module source language

Syntax:

#cir.lang<
  `c` | `cxx`   # value
>

Represents the source language used to generate the module.

Example:

// Module compiled from C.
module attributes {cir.lang = cir.lang<c>} {}
// Module compiled from C++.
module attributes {cir.lang = cir.lang<cxx>} {}

Module source language attribute name is cir.lang is defined by getSourceLanguageAttrName method in CIRDialect class.

1.2.35.1. Parameters:

Parameter

C++ type

Description

value

::cir::SourceLanguage

an enum of type SourceLanguage

1.2.36. StaticLocalGuardAttr

Guard variable name for static local variables

Syntax:

#cir.static_local_guard<
  mlir::StringAttr   # name
>

Contains the mangled guard variable name for static local variable initialization.

Example:

cir.global internal static_local_guard<"_ZGVZ3foovE1x"> @_ZZ3foovE1x = ...

1.2.36.1. Parameters:

Parameter

C++ type

Description

name

mlir::StringAttr

1.2.37. TargetAddressSpaceAttr

Represents a target-specific numeric address space

Syntax:

#cir.target_address_space<
  unsigned   # value
>

The TargetAddressSpaceAttr represents a target-specific numeric address space, corresponding to the LLVM IR addrspace qualifier and the clang address_space attribute.

A value of zero represents the default address space. The semantics of non-zero address spaces are target-specific.

Example:

// Target-specific numeric address spaces
!cir.ptr<!s32i, addrspace(target<1>)>
!cir.ptr<!s32i, addrspace(target<10>)>

1.2.37.1. Parameters:

Parameter

C++ type

Description

value

unsigned

1.2.38. ThreadLocalGlobalWrapperInitAttr

Wrapper and Init function names for thread local variables

Syntax:

#cir.tls_wrapper_init<
  mlir::StringAttr,   # wrapper_name
  mlir::StringAttr,   # init_name
  mlir::StringAttr   # guard_name
>

Contains the mangled name of the wrapper function, init function, and guard variable for a namespace/global scope thread local variable. The guard variable is optional, as it is only required for unordered thread local variables, as ordered thread local variables share a guard.

Unordered global thread local variables (such as variable template instantiations) are individually initialized when first used on a thread. Ordered global thread local variables are ALL initialized together when any that require initialization are referenced.

This is accomplished by rewriting all calls to these variables as calls to the wrapper. If the variable requires initialization, the wrapper calls the init function, then returns the global variable reference.

Throughout CIR though, these are just represented as normal get_global calls to globals with ctor/dtor regions (if necessary). The lowering-prepare pass manages the generation of the wrapper,x initialization, and call rewrites.

Example:

cir.global tls_dyn dyn_tls_refs = <"_ZTW7tls_var", "_ZTH7tls_var"> @_ZZZ7tls_var = ...
...
cir.get_global thread_local @ZZZ7tls_var : !cir.ptr<!s32i>

1.2.38.1. Parameters:

Parameter

C++ type

Description

wrapper_name

mlir::StringAttr

init_name

mlir::StringAttr

guard_name

mlir::StringAttr

1.2.39. TypeInfoAttr

Represents a typeinfo used for RTTI

Syntax:

#cir.typeinfo<
  ::mlir::Type,   # type
  ::mlir::ArrayAttr   # data
>

The typeinfo data for a given class is stored into an ArrayAttr. The layout is determined by the C++ ABI used (clang only implements itanium on CIRGen).

The verifier enforces that the output type is always a !cir.record, and that the ArrayAttr element types match the equivalent member type for the resulting record, i.e, a GlobalViewAttr for symbol reference or an IntAttr for flags.

Example:

cir.global "private" external @_ZTVN10__cxxabiv120__si_class_type_infoE
  : !cir.ptr<i32>

!rec_anon_struct = !cir.record<struct  {!cir.ptr<!u8i>, !cir.ptr<!u8i>,
  !cir.ptr<!u8i>}>

cir.global constant external @type_info = #cir.typeinfo<{
  #cir.global_view<@_ZTVN10__cxxabiv120__si_class_type_infoE, [2 : i32]>
  : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1B> : !cir.ptr<!u8i>,
  #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> : !rec_anon_struct

1.2.39.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

data

::mlir::ArrayAttr

integer or global view array attribute

1.2.40. UndefAttr

Represent an undef constant

Syntax:

#cir.undef<
  ::mlir::Type   # type
>

The UndefAttr represents an undef constant, corresponding to LLVM’s notion of undef.

1.2.40.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

1.2.41. UnwindAttr

Syntax: #cir.unwind

1.2.42. UsualDeleteParamsAttr

Parameters describing the usual operator delete signature

Syntax:

#cir.usual_delete_params<
  bool,   # size
  bool,   # alignment
  bool,   # type_aware_delete
  bool   # destroying_delete
>

Captures the properties of the usual deallocation function associated with an operator delete. These mirror the fields of clang::UsualDeleteParams.

1.2.42.1. Parameters:

Parameter

C++ type

Description

size

bool

alignment

bool

type_aware_delete

bool

destroying_delete

bool

1.2.43. VTableAttr

Represents a C++ vtable

Syntax:

#cir.vtable<
  ::mlir::Type,   # type
  mlir::ArrayAttr   # data
>

Wraps a #cir.const_record containing one or more vtable arrays.

In most cases, the anonymous record type wrapped by this attribute will contain a single array corresponding to the vtable for one class. However, in the case of multiple inheritence, the anonymous structure may contain multiple arrays, each of which is a vtable.

Example 1 (single vtable):

cir.global linkonce_odr @_ZTV6Mother =
  #cir.vtable<{
    #cir.const_array<[
      #cir.ptr<null> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI6Mother> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother9MotherFooEv> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
    ]> : !cir.array<!cir.ptr<!u8i> x 4>
  }> : !rec_anon_struct1

Example 2 (multiple vtables):

cir.global linkonce_odr @_ZTV5Child =
  #cir.vtable<{
    #cir.const_array<[
      #cir.ptr<null> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN5Child9MotherFooEv> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Mother10MotherFoo2Ev> : !cir.ptr<!u8i>
    ]> : !cir.array<!cir.ptr<!u8i> x 4>,
    #cir.const_array<[
      #cir.ptr<-8 : i64> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZTI5Child> : !cir.ptr<!u8i>,
      #cir.global_view<@_ZN6Father9FatherFooEv> : !cir.ptr<!u8i>
    ]> : !cir.array<!cir.ptr<!u8i> x 3>
  }> : !rec_anon_struct2

1.2.43.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

data

mlir::ArrayAttr

1.2.44. VisibilityAttr

Visibility attribute

Syntax:

#cir.visibility<
  `default` | `hidden` | `protected`   # value
>

Visibility attributes.

1.2.44.1. Parameters:

Parameter

C++ type

Description

value

::cir::VisibilityKind

an enum of type VisibilityKind

1.2.45. ZeroAttr

Attribute to represent zero initialization

Syntax:

#cir.zero<
  ::mlir::Type   # type
>

The ZeroAttr is used to indicate zero initialization on structs.

1.2.45.1. Parameters:

Parameter

C++ type

Description

type

::mlir::Type

1.3. Types

1.3.1. ArrayType

CIR array type

Syntax:

!cir.array<
  mlir::Type,   # elementType
  uint64_t   # size
>

!cir.array represents C/C++ constant arrays.

1.3.1.1. Parameters:

Parameter

C++ type

Description

elementType

mlir::Type

size

uint64_t

1.3.2. BF16Type

CIR bfloat16 16-bit float type

Syntax: !cir.bf16

A 16-bit floating-point type in the bfloat16 format, which is the same as IEEE binary32 except that the lower 16 bits of the mantissa are missing. It represents the type std::bfloat16_t in C++, also spelled __bf16 in some implementations.

1.3.3. BoolType

CIR bool type

Syntax: !cir.bool

!cir.bool represents C++ bool type.

1.3.4. CatchTokenType

CIR catch token type

Syntax: !cir.catch_token

!cir.catch_token is an opaque type used to track catch handling state in flattened CIR. It is returned by cir.begin_catch and consumed by cir.end_catch.

This token ensures that catch handlers are properly paired and allows the ABI lowering pass to generate appropriate exception catching code.

1.3.5. CleanupTokenType

CIR cleanup token type

Syntax: !cir.cleanup_token

!cir.cleanup_token is an opaque type used to track cleanup handling state in flattened CIR. It is returned by cir.begin_cleanup and consumed by cir.end_cleanup.

This token ensures that cleanup regions are properly paired and allows the ABI lowering pass to generate appropriate cleanup handling code.

1.3.6. ComplexType

CIR complex type

Syntax:

!cir.complex<
  ::mlir::Type   # elementType
>

CIR type that represents a C complex number. cir.complex models the C type T _Complex.

cir.complex type is not directly mapped to std::complex.

The type models complex values, per C99 6.2.5p11. It supports the C99 complex float types as well as the GCC integer complex extensions.

The parameter elementType gives the type of the real and imaginary part of the complex number. elementType must be either a CIR integer type or a CIR floating-point type.

!cir.complex<!s32i>
!cir.complex<!cir.float>

1.3.6.1. Parameters:

Parameter

C++ type

Description

elementType

::mlir::Type

integer or floating point type

1.3.7. DataMemberType

CIR type that represents a pointer-to-data-member in C++

Syntax:

!cir.data_member<
  mlir::Type,   # member_ty
  cir::RecordType   # class_ty
>

cir.data_member models a pointer-to-data-member in C++. Values of this type are essentially offsets of the pointed-to member within one of its containing record.

1.3.7.1. Parameters:

Parameter

C++ type

Description

member_ty

mlir::Type

class_ty

cir::RecordType

1.3.8. DoubleType

CIR double-precision 64-bit float type

Syntax: !cir.double

A 64-bit floating-point type whose format is IEEE-754 binary64. It represents the types double', '_Float64, std::float64_t, and _Float32x in C and C++. This is the underlying type for long double on some platforms, including Windows.

1.3.9. EhTokenType

CIR exception handling token type

Syntax: !cir.eh_token

!cir.eh_token is an opaque type used to track exception handling state in flattened CIR. It is returned by cir.eh.initiate and passed to cir.eh.dispatch, cir.begin_cleanup, and cir.begin_catch operations.

This token represents an in-flight exception and is used during ABI-lowering to generate the appropriate exception handling code.

1.3.10. FP16Type

CIR half-precision 16-bit float type

Syntax: !cir.f16

A 16-bit floating-point type whose format is IEEE-754 binary16. It represents the types ‘_Float16andstd::float16_t` in C and C++.

1.3.11. FP80Type

CIR x87 80-bit float type

Syntax: !cir.f80

An 80-bit floating-point type in the x87 extended precision format. The size and alignment of the type are both 128 bits, even though only 80 of those bits are used. This is the underlying type for long double on Linux x86 platforms, and it is available as an extension in some implementations.

1.3.12. FP128Type

CIR quad-precision 128-bit float type

Syntax: !cir.f128

A 128-bit floating-point type whose format is IEEE-754 binary128. It represents the types _Float128 and std::float128_t in C and C++, and the extension __float128 in some implementations. This is the underlying type for long double on some platforms including Linux Arm.

1.3.13. FuncType

CIR function type

Syntax:

!cir.func<
  ::llvm::ArrayRef<mlir::Type>,   # inputs
  mlir::Type,   # optionalReturnType
  bool   # varArg
>

The !cir.func is a function type. It consists of an optional return type, a list of parameter types and can optionally be variadic.

Example:

!cir.func<()>
!cir.func<() -> bool>
!cir.func<(!s8i, !s8i)>
!cir.func<(!s8i, !s8i) -> !s32i>
!cir.func<(!s32i, ...) -> !s32i>

1.3.13.1. Parameters:

Parameter

C++ type

Description

inputs

::llvm::ArrayRef<mlir::Type>

optionalReturnType

mlir::Type

varArg

bool

1.3.14. IntType

Integer type with arbitrary precision up to a fixed limit

CIR type that represents integer types with arbitrary precision, including standard integral types such as int and long, extended integral types such as __int128, and arbitrary width types such as _BitInt(n).

Those integer types that are directly available in C/C++ standard are called fundamental integer types. Said types are: signed char, short, int, long, long long, and their unsigned variations.

Examples: !cir.int<s, 32>, !cir.int<u, 64>, !cir.int<s, 128, bitint>

1.3.14.1. Parameters:

Parameter

C++ type

Description

width

unsigned

is_signed

bool

is_bit_int

bool

1.3.15. LongDoubleType

CIR float type for long double

Syntax:

!cir.long_double<
  ::mlir::Type   # underlying
>

A floating-point type that represents the long double type in C and C++.

The underlying floating-point format of a long double value depends on the target platform and the implementation. The underlying parameter specifies the CIR floating-point type that corresponds to this format. Underlying types of IEEE 64-bit, IEEE 128-bit, x87 80-bit, and IBM’s double-double format are all in use.

1.3.15.1. Parameters:

Parameter

C++ type

Description

underlying

::mlir::Type

expects !cir.double, !cir.fp80 or !cir.fp128

1.3.16. MethodType

CIR type that represents C++ pointer-to-member-function type

Syntax:

!cir.method<
  cir::FuncType,   # member_func_ty
  cir::RecordType   # class_ty
>

cir.method models the pointer-to-member-function type in C++. The layout of this type is ABI-dependent.

1.3.16.1. Parameters:

Parameter

C++ type

Description

member_func_ty

cir::FuncType

class_ty

cir::RecordType

1.3.17. PointerType

CIR pointer type

Syntax:

!cir.ptr<
  mlir::Type,   # pointee
  mlir::ptr::MemorySpaceAttrInterface   # addrSpace
>

The !cir.ptr type is a typed pointer type. It is used to represent pointers to objects in C/C++. The type of the pointed-to object is given by the pointee parameter. The addrSpace parameter is an optional address space attribute that specifies the address space of the pointer. If not specified, the pointer is assumed to be in the default address space.

The !cir.ptr type can point to any type, including fundamental types, records, arrays, vectors, functions, and other pointers. It can also point to incomplete types, such as incomplete records.

Examples:

!cir.ptr<!cir.int<u, 8>>
!cir.ptr<!cir.float>
!cir.ptr<!cir.record<struct "MyStruct">>
!cir.ptr<!cir.int<u, 8>, target_address_space(1)>
!cir.ptr<!cir.record<struct "MyStruct">, target_address_space(5)>

1.3.17.1. Parameters:

Parameter

C++ type

Description

pointee

mlir::Type

addrSpace

mlir::ptr::MemorySpaceAttrInterface

1.3.18. SingleType

CIR single-precision 32-bit float type

Syntax: !cir.float

A 32-bit floating-point type whose format is IEEE-754 binary32. It represents the types float, _Float32, and std::float32_t in C and C++.

1.3.19. StructType

CIR struct/class type

Each unique clang::RecordDecl with struct or class kind is mapped to a cir.struct type. Any object in C/C++ that has a struct or class type will have a !cir.struct in CIR.

There are three possible formats:

  • Identified and complete: unique name and a known body.

  • Identified and incomplete: unique name and unknown body.

  • Anonymous: no name and a known body.

The optional class keyword distinguishes C++ class declarations from plain struct declarations. Both are semantically identical; the keyword preserves the original source spelling.

Examples:

    !rec_complete = !cir.struct<"complete" {!u8i}>
    !rec_class    = !cir.struct<class "MyClass" {!s32i}>
    !rec_incomplete = !cir.struct<"incomplete" incomplete>
    !anonymous    = !cir.struct<{!u8i}>
    !rec_packed   = !cir.struct<"p1" packed {!u8i, !u8i}>
    !rec_padded   = !cir.struct<"p2" padded {!u8i, !u8i}>
    !recursive    = !cir.struct<"Node" {!cir.ptr<!cir.struct<"Node">>}>

1.3.19.1. Parameters:

Parameter

C++ type

Description

members

::llvm::ArrayRef<mlir::Type>

name

mlir::StringAttr

incomplete

bool

packed

bool

padded

bool

is_class

bool

1.3.20. UnionType

CIR union type

Each unique clang::RecordDecl with union kind is mapped to a cir.union type. Any object in C/C++ that has a union type will have a !cir.union in CIR.

There are three possible formats:

  • Identified and complete: unique name and a known body.

  • Identified and incomplete: unique name and unknown body.

  • Anonymous: no name and a known body.

Padded unions carry an explicit tail-padding type to ensure the LLVM struct that models the union has the correct byte size.

Examples:

    !u_complete   = !cir.union<"U" {!s32i, !u8i}>
    !u_incomplete = !cir.union<"U" incomplete>
    !u_anonymous  = !cir.union<{!s32i, !u8i}>
    !u_padded     = !cir.union<"U" {!s32i, !u8i}, padding = {!u8i}>

1.3.20.1. Parameters:

Parameter

C++ type

Description

members

::llvm::ArrayRef<mlir::Type>

name

mlir::StringAttr

incomplete

bool

packed

bool

padding

mlir::Type

1.3.21. VPtrType

CIR type that is used for the vptr member of C++ objects

Syntax: !cir.vptr

cir.vptr is a special type used as the type for the vptr member of a C++ object. This avoids using arbitrary pointer types to declare vptr values and allows stronger type-based checking for operations that use or provide access to the vptr.

This type will be the element type of the ‘vptr’ member of structures that require a vtable pointer. The cir.vtable.address_point operation returns this type. The cir.vtable.get_vptr operations returns a pointer to this type. This pointer may be passed to the cir.vtable.get_virtual_fn_addr operation to get the address of a virtual function pointer.

The pointer may also be cast to other pointer types in order to perform pointer arithmetic based on information encoded in the AST layout to get the offset from a pointer to a dynamic object to the base object pointer, the base object offset value from the vtable, or the type information entry for an object. TODO: We should have special operations to do that too.

1.3.22. VectorType

CIR vector type

The !cir.vector type represents a one-dimensional vector. It takes three parameters: the element type, the number of elements and the scalability flag (optional, defaults to false).

Syntax:

vector-type ::= !cir.vector<size x element-type>
size ::= (decimal-literal | `[` decimal-literal `]`)
element-type ::= float-type | integer-type | pointer-type

The element-type must be a scalar CIR type. Zero-sized vectors are not allowed. The size must be a positive integer.

Examples:

!cir.vector<4 x !cir.int<u, 8>>
!cir.vector<2 x !cir.float>

Scalable vectors are indicated by enclosing size in square brackets.

Example:

!cir.vector<[4] x !cir.int<u, 8>>

1.3.22.1. Parameters:

Parameter

C++ type

Description

element_type

::mlir::Type

any cir boolean, integer, floating point or pointer type

size

uint64_t

is_scalable

bool

1.3.23. VoidType

CIR void type

Syntax: !cir.void

The !cir.void type represents the C and C++ void type.

1.4. Enums

1.4.1. ArgPassingKind

Record argument passing eligibility

1.4.1.1. Cases:

Symbol

Value

String

CanPassInRegs

0

can_pass_in_regs

CannotPassInRegs

1

cannot_pass_in_regs

CanNeverPassInRegs

2

can_never_pass_in_regs

1.4.2. AsmFlavor

ATT or Intel

1.4.2.1. Cases:

Symbol

Value

String

x86_att

0

x86_att

x86_intel

1

x86_intel

1.4.3. AssignKind

CXX Assignment Operator Kind

1.4.3.1. Cases:

Symbol

Value

String

Copy

0

copy

Move

1

move

1.4.4. AssumeBundleKind

Kind of cir.assume operand bundle

1.4.4.1. Cases:

Symbol

Value

String

None

0

None

Align

1

align

SeparateStorage

2

separate_storage

Dereferenceable

3

dereferenceable

1.4.5. AtomicFetchKind

Binary opcode for atomic fetch-and-update operations

1.4.5.1. Cases:

Symbol

Value

String

Add

0

add

Sub

1

sub

And

2

and

Xor

3

xor

Or

4

or

Nand

5

nand

Max

6

max

Min

7

min

UIncWrap

8

uinc_wrap

UDecWrap

9

udec_wrap

1.4.6. AwaitKind

Await kind

1.4.6.1. Cases:

Symbol

Value

String

Init

0

init

User

1

user

Yield

2

yield

Final

3

final

1.4.7. CUDADeviceVarKind

CUDA device variable kind

1.4.7.1. Cases:

Symbol

Value

String

Variable

0

Variable

Surface

1

Surface

Texture

2

Texture

1.4.8. CallingConv

Calling convention

1.4.8.1. Cases:

Symbol

Value

String

C

0

c

PTXKernel

1

ptx_kernel

SpirFunction

2

spir_function

SpirKernel

3

spir_kernel

AMDGPUKernel

4

amdgpu_kernel

1.4.9. CaseOpKind

Case kind

1.4.9.1. Cases:

Symbol

Value

String

Default

0

default

Equal

1

equal

Anyof

2

anyof

Range

3

range

1.4.10. CastKind

Cast kind

1.4.10.1. Cases:

Symbol

Value

String

bitcast

1

bitcast

array_to_ptrdecay

11

array_to_ptrdecay

member_ptr_to_bool

17

member_ptr_to_bool

int_to_ptr

21

int_to_ptr

ptr_to_int

22

ptr_to_int

ptr_to_bool

23

ptr_to_bool

integral

27

integral

int_to_bool

28

int_to_bool

int_to_float

29

int_to_float

float_to_int

36

float_to_int

float_to_bool

37

float_to_bool

bool_to_int

38

bool_to_int

floating

39

floating

float_to_complex

44

float_to_complex

float_complex_to_real

45

float_complex_to_real

float_complex_to_bool

46

float_complex_to_bool

float_complex

47

float_complex

float_complex_to_int_complex

48

float_complex_to_int_complex

int_to_complex

49

int_to_complex

int_complex_to_real

50

int_complex_to_real

int_complex_to_bool

51

int_complex_to_bool

int_complex

52

int_complex

int_complex_to_float_complex

53

int_complex_to_float_complex

address_space

63

address_space

bool_to_float

1000

bool_to_float

1.4.11. CleanupKind

Cleanup kind

1.4.11.1. Cases:

Symbol

Value

String

Normal

1

normal

EH

2

eh

All

3

all

1.4.12. CmpOpKind

Compare operation kind

1.4.12.1. Cases:

Symbol

Value

String

lt

0

lt

le

1

le

gt

2

gt

ge

3

ge

eq

4

eq

ne

5

ne

one

6

one

uno

7

uno

1.4.13. CmpOrdering

Three-way comparison ordering kind

1.4.13.1. Cases:

Symbol

Value

String

Strong

0

strong

Weak

1

weak

Partial

2

partial

1.4.14. ComplexRangeKind

Complex multiplication and division implementation

1.4.14.1. Cases:

Symbol

Value

String

Full

0

full

Improved

1

improved

Promoted

2

promoted

Basic

3

basic

1.4.15. CtorKind

CXX Constructor Kind

1.4.15.1. Cases:

Symbol

Value

String

Custom

0

custom

Default

1

default

Copy

2

copy

Move

3

move

1.4.16. DynamicCastKind

Dynamic cast kind

1.4.16.1. Cases:

Symbol

Value

String

Ptr

0

ptr

Ref

1

ref

1.4.17. GlobalLinkageKind

Linkage kind

1.4.17.1. Cases:

Symbol

Value

String

ExternalLinkage

0

external

AvailableExternallyLinkage

1

available_externally

LinkOnceAnyLinkage

2

linkonce

LinkOnceODRLinkage

3

linkonce_odr

WeakAnyLinkage

4

weak

WeakODRLinkage

5

weak_odr

AppendingLinkage

6

appending

InternalLinkage

7

internal

PrivateLinkage

8

cir_private

ExternalWeakLinkage

9

extern_weak

CommonLinkage

10

common

1.4.18. InitCatchKind

Allowed 32-bit signless integer cases: 0, 1, 2, 3, 4, 5

1.4.18.1. Cases:

Symbol

Value

String

Reference

0

reference

Pointer

1

pointer

Scalar

2

scalar

Objc

3

objc

TrivialCopy

4

trivial_copy

NonTrivialCopy

5

non_trivial_copy

1.4.19. InlineKind

InlineKind

1.4.19.1. Cases:

Symbol

Value

String

NoInline

1

no_inline

AlwaysInline

2

always_inline

InlineHint

3

inline_hint

1.4.20. LangAddressSpace

Language address space kind

1.4.20.1. Cases:

Symbol

Value

String

Default

0

default

OffloadPrivate

1

offload_private

OffloadLocal

2

offload_local

OffloadGlobal

3

offload_global

OffloadConstant

4

offload_constant

OffloadGeneric

5

offload_generic

OffloadGlobalDevice

6

offload_global_device

OffloadGlobalHost

7

offload_global_host

1.4.21. MemOrder

Memory order according to C++11 memory model

1.4.21.1. Cases:

Symbol

Value

String

Relaxed

0

relaxed

Consume

1

consume

Acquire

2

acquire

Release

3

release

AcquireRelease

4

acq_rel

SequentiallyConsistent

5

seq_cst

1.4.22. SideEffect

Allowed side effects of a function

1.4.22.1. Cases:

Symbol

Value

String

All

0

all

Pure

1

pure

Const

2

const

1.4.23. SourceLanguage

Source language

1.4.23.1. Cases:

Symbol

Value

String

C

1

c

CXX

2

cxx

1.4.24. SyncScopeKind

Sync scope kind

1.4.24.1. Cases:

Symbol

Value

String

SingleThread

0

single_thread

System

1

system

Device

2

device

Workgroup

3

workgroup

Wavefront

4

wavefront

Cluster

5

cluster

HIPSingleThread

6

hip_single_thread

HIPSystem

7

hip_system

HIPAgent

8

hip_agent

HIPWorkgroup

9

hip_workgroup

HIPWavefront

10

hip_wavefront

HIPCluster

11

hip_cluster

OpenCLWorkGroup

12

opencl_work_group

OpenCLDevice

13

opencl_device

OpenCLAllSVMDevices

14

opencl_all_svm_devices

OpenCLSubGroup

15

opencl_sub_group

1.4.25. TLS_Model

TLS model

1.4.25.1. Cases:

Symbol

Value

String

GeneralDynamic

0

tls_dyn

LocalDynamic

1

tls_local_dyn

InitialExec

2

tls_init_exec

LocalExec

3

tls_local_exec

1.4.26. VisibilityKind

C/C++ visibility

1.4.26.1. Cases:

Symbol

Value

String

Default

0

default

Hidden

1

hidden

Protected

2

protected

1.4.27. FPClassTest

Floating-point class test flags

1.4.27.1. Cases:

Symbol

Value

String

SignalingNaN

1

fcSNan

QuietNaN

2

fcQNan

NegativeInfinity

4

fcNegInf

NegativeNormal

8

fcNegNormal

NegativeSubnormal

16

fcNegSubnormal

NegativeZero

32

fcNegZero

PositiveZero

64

fcPosZero

PositiveSubnormal

128

fcPosSubnormal

PositiveNormal

256

fcPosNormal

PositiveInfinity

512

fcPosInf

Nan

3

fcNan

Infinity

516

fcInf

Normal

264

fcNormal

Subnormal

144

fcSubnormal

Zero

96

fcZero

PositiveFinite

448

fcPosFinite

NegativeFinite

56

fcNegFinite

Finite

504

fcFinite

Positive

960

fcPositive

Negative

60

fcNegative

All

1023

fcAllFlags