@@ -3386,6 +3386,10 @@ def CIR_BaseClassAddrOp : CIR_Op<"base_class_addr"> {
33863386 cannot be known by the operation, and that information affects how the
33873387 operation is lowered.
33883388
3389+ The validity of the relationship of derived and base cannot yet be verified.
3390+ If the target class is not a valid base class for the object, the behavior
3391+ is undefined.
3392+
33893393 Example:
33903394 ```c++
33913395 struct Base { };
@@ -3399,8 +3403,6 @@ def CIR_BaseClassAddrOp : CIR_Op<"base_class_addr"> {
33993403 ```
34003404 }];
34013405
3402- // The validity of the relationship of derived and base cannot yet be
3403- // verified, currently not worth adding a verifier.
34043406 let arguments = (ins
34053407 Arg<CIR_PointerType, "derived class pointer", [MemRead]>:$derived_addr,
34063408 IndexAttr:$offset, UnitAttr:$assume_not_null);
@@ -3414,6 +3416,56 @@ def CIR_BaseClassAddrOp : CIR_Op<"base_class_addr"> {
34143416 }];
34153417}
34163418
3419+ //===----------------------------------------------------------------------===//
3420+ // DerivedClassAddrOp
3421+ //===----------------------------------------------------------------------===//
3422+
3423+ def CIR_DerivedClassAddrOp : CIR_Op<"derived_class_addr"> {
3424+ let summary = "Get the derived class address for a class/struct";
3425+ let description = [{
3426+ The `cir.derived_class_addr` operaration gets the address of a particular
3427+ derived class given a non-virtual base class pointer. The offset in bytes
3428+ of the base class must be passed in, similar to `cir.base_class_addr`, but
3429+ going into the other direction. This means lowering to a negative offset.
3430+
3431+ The operation contains a flag for whether or not the operand may be nullptr.
3432+ That depends on the context and cannot be known by the operation, and that
3433+ information affects how the operation is lowered.
3434+
3435+ The validity of the relationship of derived and base cannot yet be verified.
3436+ If the target class is not a valid derived class for the object, the
3437+ behavior is undefined.
3438+
3439+ Example:
3440+ ```c++
3441+ class A {};
3442+ class B : public A {};
3443+
3444+ B *getAsB(A *a) {
3445+ return static_cast<B*>(a);
3446+ }
3447+ ```
3448+
3449+ leads to
3450+ ```mlir
3451+ %2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
3452+ %3 = cir.base_class_addr %2 : !cir.ptr<!rec_B> [0] -> !cir.ptr<!rec_A>
3453+ ```
3454+ }];
3455+
3456+ let arguments = (ins
3457+ Arg<CIR_PointerType, "base class pointer", [MemRead]>:$base_addr,
3458+ IndexAttr:$offset, UnitAttr:$assume_not_null);
3459+
3460+ let results = (outs Res<CIR_PointerType, "">:$derived_addr);
3461+
3462+ let assemblyFormat = [{
3463+ $base_addr `:` qualified(type($base_addr))
3464+ (`nonnull` $assume_not_null^)?
3465+ ` ` `[` $offset `]` `->` qualified(type($derived_addr)) attr-dict
3466+ }];
3467+ }
3468+
34173469//===----------------------------------------------------------------------===//
34183470// ComplexCreateOp
34193471//===----------------------------------------------------------------------===//
@@ -4845,4 +4897,38 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> {
48454897 }];
48464898}
48474899
4900+ //===----------------------------------------------------------------------===//
4901+ // BlockAddressOp
4902+ //===----------------------------------------------------------------------===//
4903+
4904+ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> {
4905+ let summary = "Get the address of a cir.label within a function";
4906+ let description = [{
4907+ The `cir.blockaddress` operation takes a function name and a label and
4908+ produces a pointer value that represents the address of that cir.label
4909+ within the specified function.
4910+
4911+ This operation models GCC's "labels as values" extension (`&&label`), which
4912+ allows taking the address of a local label and using it as a computed
4913+ jump target (e.g., with `goto *addr;`).
4914+
4915+ Example:
4916+ ```mlir
4917+ %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init]
4918+ {alignment = 8 : i64}
4919+ %addr = cir.block_address <@c, "label1"> : !cir.ptr<!cir.void>
4920+ cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
4921+ cir.br ^bb1
4922+ ^bb1:
4923+ cir.label "label"
4924+ ```
4925+ }];
4926+
4927+ let arguments = (ins CIR_BlockAddrInfoAttr:$block_addr_info);
4928+ let results = (outs CIR_VoidPtrType:$addr);
4929+ let assemblyFormat = [{
4930+ $block_addr_info `:` qualified(type($addr)) attr-dict
4931+ }];
4932+ }
4933+
48484934#endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
0 commit comments