@@ -2594,7 +2594,7 @@ def CIR_GetGlobalOp : CIR_Op<"get_global", [
25942594// VTableAddrPointOp
25952595//===----------------------------------------------------------------------===//
25962596
2597- def CIR_VTableAddrPointOp : CIR_Op<"vtable.address_point",[
2597+ def CIR_VTableAddrPointOp : CIR_Op<"vtable.address_point", [
25982598 Pure, DeclareOpInterfaceMethods<SymbolUserOpInterface>
25992599]> {
26002600 let summary = "Get the vtable (global variable) address point";
@@ -2603,39 +2603,116 @@ def CIR_VTableAddrPointOp : CIR_Op<"vtable.address_point",[
26032603 (address point) of a C++ virtual table. An object internal `__vptr`
26042604 gets initializated on top of the value returned by this operation.
26052605
2606- `address_point.index` (vtable index) provides the appropriate vtable within the vtable group
2607- (as specified by Itanium ABI), and `address_point.offset` (address point index) the actual address
2608- point within that vtable.
2606+ `address_point.index` (vtable index) provides the appropriate vtable within
2607+ the vtable group (as specified by Itanium ABI), and `address_point.offset`
2608+ (address point index) the actual address point within that vtable.
26092609
2610- The return type is always a `!cir.ptr<!cir.ptr<() -> i32>> `.
2610+ The return type is always `!cir.vptr `.
26112611
26122612 Example:
26132613 ```mlir
26142614 cir.global linkonce_odr @_ZTV1B = ...
26152615 ...
2616- %3 = cir.vtable.address_point(@_ZTV1B, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<() -> i32>>
2616+ %3 = cir.vtable.address_point(@_ZTV1B,
2617+ address_point = <index = 0, offset = 2>) : !cir.vptr
26172618 ```
26182619 }];
26192620
26202621 let arguments = (ins
2621- OptionalAttr<FlatSymbolRefAttr>:$name,
2622- Optional<CIR_AnyType>:$sym_addr,
2622+ FlatSymbolRefAttr:$name,
26232623 CIR_AddressPointAttr:$address_point
26242624 );
26252625
2626- let results = (outs Res<CIR_PointerType , "", []>:$addr);
2626+ let results = (outs Res<CIR_VPtrType , "", []>:$addr);
26272627
26282628 let assemblyFormat = [{
26292629 `(`
2630- ($name^)?
2631- ($sym_addr^ `:` type($sym_addr))?
2632- `,`
2633- `address_point` `=` $address_point
2630+ $name `,` `address_point` `=` $address_point
26342631 `)`
26352632 `:` qualified(type($addr)) attr-dict
26362633 }];
2634+ }
26372635
2638- let hasVerifier = 1;
2636+ //===----------------------------------------------------------------------===//
2637+ // VTableGetVPtr
2638+ //===----------------------------------------------------------------------===//
2639+
2640+ def CIR_VTableGetVPtrOp : CIR_Op<"vtable.get_vptr", [Pure]> {
2641+ let summary = "Get a the address of the vtable pointer for an object";
2642+ let description = [{
2643+ The `vtable.get_vptr` operation retrieves the address of the vptr for a
2644+ C++ object. This operation requires that the object pointer points to
2645+ the start of a complete object. (TODO: Describe how we get that).
2646+ The vptr will always be at offset zero in the object, but this operation
2647+ is more explicit about what is being retrieved than a direct bitcast.
2648+
2649+ The return type is always `!cir.ptr<!cir.vptr>`.
2650+
2651+ Example:
2652+ ```mlir
2653+ %2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_C>>, !cir.ptr<!rec_C>
2654+ %3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_C> -> !cir.ptr<!cir.vptr>
2655+ ```
2656+ }];
2657+
2658+ let arguments = (ins
2659+ Arg<CIR_PointerType, "the vptr address", [MemRead]>:$src
2660+ );
2661+
2662+ let results = (outs CIR_PtrToVPtr:$result);
2663+
2664+ let assemblyFormat = [{
2665+ $src `:` qualified(type($src)) `->` qualified(type($result)) attr-dict
2666+ }];
2667+
2668+ }
2669+
2670+ //===----------------------------------------------------------------------===//
2671+ // VTableGetVirtualFnAddrOp
2672+ //===----------------------------------------------------------------------===//
2673+
2674+ def CIR_VTableGetVirtualFnAddrOp : CIR_Op<"vtable.get_virtual_fn_addr", [
2675+ Pure
2676+ ]> {
2677+ let summary = "Get a the address of a virtual function pointer";
2678+ let description = [{
2679+ The `vtable.get_virtual_fn_addr` operation retrieves the address of a
2680+ virtual function pointer from an object's vtable (__vptr).
2681+ This is an abstraction to perform the basic pointer arithmetic to get
2682+ the address of the virtual function pointer, which can then be loaded and
2683+ called.
2684+
2685+ The `vptr` operand must be a `!cir.ptr<!cir.vptr>` value, which would
2686+ have been returned by a previous call to `cir.vatble.get_vptr`. The
2687+ `index` operand is an index of the virtual function in the vtable.
2688+
2689+ The return type is a pointer-to-pointer to the function type.
2690+
2691+ Example:
2692+ ```mlir
2693+ %2 = cir.load %0 : !cir.ptr<!cir.ptr<!rec_C>>, !cir.ptr<!rec_C>
2694+ %3 = cir.vtable.get_vptr %2 : !cir.ptr<!rec_C> -> !cir.ptr<!cir.vptr>
2695+ %4 = cir.load %3 : !cir.ptr<!cir.vptr>, !cir.vptr
2696+ %5 = cir.vtable.get_virtual_fn_addr %4[2] : !cir.vptr
2697+ -> !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>>
2698+ %6 = cir.load align(8) %5 : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!rec_C>)
2699+ -> !s32i>>>,
2700+ !cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>
2701+ %7 = cir.call %6(%2) : (!cir.ptr<!cir.func<(!cir.ptr<!rec_C>) -> !s32i>>,
2702+ !cir.ptr<!rec_C>) -> !s32i
2703+ ```
2704+ }];
2705+
2706+ let arguments = (ins
2707+ Arg<CIR_VPtrType, "vptr", [MemRead]>:$vptr,
2708+ I64Attr:$index);
2709+
2710+ let results = (outs CIR_PointerType:$result);
2711+
2712+ let assemblyFormat = [{
2713+ $vptr `[` $index `]` attr-dict
2714+ `:` qualified(type($vptr)) `->` qualified(type($result))
2715+ }];
26392716}
26402717
26412718//===----------------------------------------------------------------------===//
0 commit comments