@@ -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