@@ -2594,7 +2594,7 @@ def CIR_GetGlobalOp : CIR_Op<"get_global", [
2594
2594
// VTableAddrPointOp
2595
2595
//===----------------------------------------------------------------------===//
2596
2596
2597
- def CIR_VTableAddrPointOp : CIR_Op<"vtable.address_point",[
2597
+ def CIR_VTableAddrPointOp : CIR_Op<"vtable.address_point", [
2598
2598
Pure, DeclareOpInterfaceMethods<SymbolUserOpInterface>
2599
2599
]> {
2600
2600
let summary = "Get the vtable (global variable) address point";
@@ -2603,39 +2603,116 @@ def CIR_VTableAddrPointOp : CIR_Op<"vtable.address_point",[
2603
2603
(address point) of a C++ virtual table. An object internal `__vptr`
2604
2604
gets initializated on top of the value returned by this operation.
2605
2605
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.
2609
2609
2610
- The return type is always a `!cir.ptr<!cir.ptr<() -> i32>> `.
2610
+ The return type is always `!cir.vptr `.
2611
2611
2612
2612
Example:
2613
2613
```mlir
2614
2614
cir.global linkonce_odr @_ZTV1B = ...
2615
2615
...
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
2617
2618
```
2618
2619
}];
2619
2620
2620
2621
let arguments = (ins
2621
- OptionalAttr<FlatSymbolRefAttr>:$name,
2622
- Optional<CIR_AnyType>:$sym_addr,
2622
+ FlatSymbolRefAttr:$name,
2623
2623
CIR_AddressPointAttr:$address_point
2624
2624
);
2625
2625
2626
- let results = (outs Res<CIR_PointerType , "", []>:$addr);
2626
+ let results = (outs Res<CIR_VPtrType , "", []>:$addr);
2627
2627
2628
2628
let assemblyFormat = [{
2629
2629
`(`
2630
- ($name^)?
2631
- ($sym_addr^ `:` type($sym_addr))?
2632
- `,`
2633
- `address_point` `=` $address_point
2630
+ $name `,` `address_point` `=` $address_point
2634
2631
`)`
2635
2632
`:` qualified(type($addr)) attr-dict
2636
2633
}];
2634
+ }
2637
2635
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
+ }];
2639
2716
}
2640
2717
2641
2718
//===----------------------------------------------------------------------===//
0 commit comments