Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,36 @@ def GlobalAnnotationValuesAttr : CIR_Attr<"GlobalAnnotationValues",
let genVerifyDecl = 1;
}

//===----------------------------------------------------------------------===//
// AddressPointAttr
//===----------------------------------------------------------------------===//

def AddressPointAttr : CIR_Attr<"AddressPoint", "address_point"> {
let summary = "Address point attribute";

let description = [{
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:
```mlir
cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B, address_point = <index = 0, offset = 2>)) : !cir.ptr<!cir.ptr<() -> i32>>
```
}];

let parameters = (ins "int32_t":$index,
"int32_t":$offset);

let assemblyFormat = [{
`<` struct($index, $offset) `>`
}];
}

include "clang/CIR/Dialect/IR/CIRTBAAAttrs.td"

include "clang/CIR/Dialect/IR/CIROpenCLAttrs.td"
Expand Down
12 changes: 5 additions & 7 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2575,8 +2575,8 @@ def VTableAddrPointOp : CIR_Op<"vtable.address_point",
(address point) of a C++ virtual table. An object internal `__vptr`
gets initializated on top of the value returned by this operation.

`vtable_index` provides the appropriate vtable within the vtable group
(as specified by Itanium ABI), and `addr_point_index` the actual address
`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 a `!cir.ptr<!cir.ptr<() -> i32>>`.
Expand All @@ -2585,23 +2585,21 @@ def VTableAddrPointOp : CIR_Op<"vtable.address_point",
```mlir
cir.global linkonce_odr @_ZTV1B = ...
...
%3 = cir.vtable.address_point(@_ZTV1B, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<() -> i32>>
%3 = cir.vtable.address_point(@_ZTV1B, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<() -> i32>>
```
}];

let arguments = (ins OptionalAttr<FlatSymbolRefAttr>:$name,
Optional<CIR_AnyType>:$sym_addr,
I32Attr:$vtable_index,
I32Attr:$address_point_index);
AddressPointAttr:$address_point);
let results = (outs Res<CIR_PointerType, "", []>:$addr);

let assemblyFormat = [{
`(`
($name^)?
($sym_addr^ `:` type($sym_addr))?
`,`
`vtable_index` `=` $vtable_index `,`
`address_point_index` `=` $address_point_index
`address_point` `=` $address_point
`)`
`:` qualified(type($addr)) attr-dict
}];
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,8 @@ CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
auto VTableSlotPtr = CGF.getBuilder().create<cir::VTableAddrPointOp>(
loc, CGF.getBuilder().getPointerTo(TyPtr),
::mlir::FlatSymbolRefAttr{}, VTable,
/*vtable_index=*/0, VTableIndex);
cir::AddressPointAttr::get(CGF.getBuilder().getContext(), 0,
VTableIndex));
VFuncLoad = CGF.getBuilder().createAlignedLoad(loc, TyPtr, VTableSlotPtr,
CGF.getPointerAlign());
}
Expand Down Expand Up @@ -1011,7 +1012,9 @@ CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
return builder.create<cir::VTableAddrPointOp>(
CGM.getLoc(VTableClass->getSourceRange()), vtablePtrTy,
mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()), mlir::Value{},
AddressPoint.VTableIndex, AddressPoint.AddressPointIndex);
cir::AddressPointAttr::get(CGM.getBuilder().getContext(),
AddressPoint.VTableIndex,
AddressPoint.AddressPointIndex));
}

mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ buildDynamicCastToVoidAfterNullCheck(CIRBaseBuilderTy &builder,
auto vtablePtr = builder.createLoad(loc, vtablePtrPtr);
auto offsetToTopSlotPtr = builder.create<cir::VTableAddrPointOp>(
loc, vtablePtrTy, mlir::FlatSymbolRefAttr{}, vtablePtr,
/*vtable_index=*/0, -2ULL);
cir::AddressPointAttr::get(builder.getContext(), 0, -2));
auto offsetToTop =
builder.createAlignedLoad(loc, offsetToTopSlotPtr, vtableElemAlign);

Expand Down
8 changes: 5 additions & 3 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3661,13 +3661,15 @@ mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
if (!symAddr) {
symAddr = getValueForVTableSymbol(op, rewriter, getTypeConverter(),
op.getNameAttr(), eltType);
offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{0, op.getVtableIndex(),
op.getAddressPointIndex()};
offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{
0, op.getAddressPointAttr().getIndex(),
op.getAddressPointAttr().getOffset()};
} else {
// Get indirect vtable address point retrieval
symAddr = adaptor.getSymAddr();
eltType = converter->convertType(symAddr.getType());
offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{op.getAddressPointIndex()};
offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{
op.getAddressPointAttr().getOffset()};
}

assert(eltType && "Shouldn't ever be missing an eltType here");
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/derived-to-base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void vcall(C1 &c1) {
// CHECK: %6 = cir.load %3 : !cir.ptr<!ty_buffy>, !ty_buffy
// CHECK: %7 = cir.cast(bitcast, %4 : !cir.ptr<!ty_C1_>), !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>>
// CHECK: %8 = cir.load %7 : !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>>, !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>
// CHECK: %9 = cir.vtable.address_point( %8 : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>
// CHECK: %9 = cir.vtable.address_point( %8 : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>
// CHECK: %10 = cir.load align(8) %9 : !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>>, !cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>
// CHECK: %11 = cir.call %10(%4, %5, %6) : (!cir.ptr<!cir.func<(!cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i>>, !cir.ptr<!ty_C1_>, !s32i, !ty_buffy) -> !s32i
// CHECK: cir.return
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/dynamic-cast-exact.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct Derived final : Base1 {};
Derived *ptr_cast(Base1 *ptr) {
return dynamic_cast<Derived *>(ptr);
// CHECK: %[[#SRC:]] = cir.load %{{.+}} : !cir.ptr<!cir.ptr<!ty_Base1_>>, !cir.ptr<!ty_Base1_>
// CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK-NEXT: %[[#SRC_VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr<!ty_Base1_>), !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>
// CHECK-NEXT: %[[#SRC_VPTR:]] = cir.load %[[#SRC_VPTR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>, !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK-NEXT: %[[#SUCCESS:]] = cir.cmp(eq, %[[#SRC_VPTR]], %[[#EXPECTED_VPTR]]) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>, !cir.bool
Expand All @@ -39,7 +39,7 @@ Derived *ptr_cast(Base1 *ptr) {
Derived &ref_cast(Base1 &ref) {
return dynamic_cast<Derived &>(ref);
// CHECK: %[[#SRC:]] = cir.load %{{.+}} : !cir.ptr<!cir.ptr<!ty_Base1_>>, !cir.ptr<!ty_Base1_>
// CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK-NEXT: %[[#EXPECTED_VPTR:]] = cir.vtable.address_point(@_ZTV7Derived, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK-NEXT: %[[#SRC_VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr<!ty_Base1_>), !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>
// CHECK-NEXT: %[[#SRC_VPTR:]] = cir.load %[[#SRC_VPTR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>, !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK-NEXT: %[[#SUCCESS:]] = cir.cmp(eq, %[[#SRC_VPTR]], %[[#EXPECTED_VPTR]]) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>, !cir.bool
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/dynamic-cast-relative-layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void *ptr_cast_to_complete(Base *ptr) {
// AFTER-NEXT: %{{.+}} = cir.ternary(%[[#SRC_IS_NOT_NULL]], true {
// AFTER-NEXT: %[[#VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr<!ty_Base>), !cir.ptr<!cir.ptr<!s32i>>
// AFTER-NEXT: %[[#VPTR:]] = cir.load %[[#VPTR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// AFTER-NEXT: %[[#OFFSET_TO_TOP_PTR:]] = cir.vtable.address_point( %[[#VPTR]] : !cir.ptr<!s32i>, vtable_index = 0, address_point_index = -2) : !cir.ptr<!s32i>
// AFTER-NEXT: %[[#OFFSET_TO_TOP_PTR:]] = cir.vtable.address_point( %[[#VPTR]] : !cir.ptr<!s32i>, address_point = <index = 0, offset = -2>) : !cir.ptr<!s32i>
// AFTER-NEXT: %[[#OFFSET_TO_TOP:]] = cir.load align(4) %[[#OFFSET_TO_TOP_PTR]] : !cir.ptr<!s32i>, !s32i
// AFTER-NEXT: %[[#SRC_BYTES_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr<!ty_Base>), !cir.ptr<!u8i>
// AFTER-NEXT: %[[#DST_BYTES_PTR:]] = cir.ptr_stride(%[[#SRC_BYTES_PTR]] : !cir.ptr<!u8i>, %[[#OFFSET_TO_TOP]] : !s32i), !cir.ptr<!u8i>
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/dynamic-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void *ptr_cast_to_complete(Base *ptr) {
// AFTER-NEXT: %{{.+}} = cir.ternary(%[[#SRC_IS_NOT_NULL]], true {
// AFTER-NEXT: %[[#VPTR_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr<!ty_Base>), !cir.ptr<!cir.ptr<!s64i>>
// AFTER-NEXT: %[[#VPTR:]] = cir.load %[[#VPTR_PTR]] : !cir.ptr<!cir.ptr<!s64i>>, !cir.ptr<!s64i>
// AFTER-NEXT: %[[#BASE_OFFSET_PTR:]] = cir.vtable.address_point( %[[#VPTR]] : !cir.ptr<!s64i>, vtable_index = 0, address_point_index = -2) : !cir.ptr<!s64i>
// AFTER-NEXT: %[[#BASE_OFFSET_PTR:]] = cir.vtable.address_point( %[[#VPTR]] : !cir.ptr<!s64i>, address_point = <index = 0, offset = -2>) : !cir.ptr<!s64i>
// AFTER-NEXT: %[[#BASE_OFFSET:]] = cir.load align(8) %[[#BASE_OFFSET_PTR]] : !cir.ptr<!s64i>, !s64i
// AFTER-NEXT: %[[#SRC_BYTES_PTR:]] = cir.cast(bitcast, %[[#SRC]] : !cir.ptr<!ty_Base>), !cir.ptr<!u8i>
// AFTER-NEXT: %[[#DST_BYTES_PTR:]] = cir.ptr_stride(%[[#SRC_BYTES_PTR]] : !cir.ptr<!u8i>, %[[#BASE_OFFSET]] : !s64i), !cir.ptr<!u8i>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/vtable-rtti.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class B : public A
// CHECK: %1 = cir.load %0 : !cir.ptr<!cir.ptr<![[ClassB]]>>, !cir.ptr<![[ClassB]]>
// CHECK: %2 = cir.base_class_addr(%1 : !cir.ptr<![[ClassB]]> nonnull) [0] -> !cir.ptr<![[ClassA]]>
// CHECK: cir.call @_ZN1AC2Ev(%2) : (!cir.ptr<![[ClassA]]>) -> ()
// CHECK: %3 = cir.vtable.address_point(@_ZTV1B, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK: %3 = cir.vtable.address_point(@_ZTV1B, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK: %4 = cir.cast(bitcast, %1 : !cir.ptr<![[ClassB]]>), !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>
// CHECK: cir.store %3, %4 : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>, !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>
// CHECK: cir.return
Expand Down Expand Up @@ -73,7 +73,7 @@ class B : public A
// CHECK: %0 = cir.alloca !cir.ptr<![[ClassA]]>, !cir.ptr<!cir.ptr<![[ClassA]]>>, ["this", init] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<![[ClassA]]>, !cir.ptr<!cir.ptr<![[ClassA]]>>
// CHECK: %1 = cir.load %0 : !cir.ptr<!cir.ptr<![[ClassA]]>>, !cir.ptr<![[ClassA]]>
// CHECK: %2 = cir.vtable.address_point(@_ZTV1A, vtable_index = 0, address_point_index = 2) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK: %2 = cir.vtable.address_point(@_ZTV1A, address_point = <index = 0, offset = 2>) : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>
// CHECK: %3 = cir.cast(bitcast, %1 : !cir.ptr<![[ClassA]]>), !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>
// CHECK: cir.store %2, %3 : !cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>, !cir.ptr<!cir.ptr<!cir.ptr<!cir.func<() -> !u32i>>>>
// CHECK: cir.return
Expand Down
Loading