Skip to content

Commit 8cf166a

Browse files
committed
Add test for offset exact cast (and fix it)
1 parent a8a6019 commit 8cf166a

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2064,7 +2064,7 @@ static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi,
20642064
mlir::Type u8PtrTy = builder.getUInt8PtrTy();
20652065

20662066
mlir::Value strideToApply =
2067-
builder.getConstInt(loc, builder.getUInt64Ty(), offset->getQuantity());
2067+
builder.getConstInt(loc, builder.getUInt64Ty(), -offset->getQuantity());
20682068
mlir::Value srcU8Ptr = builder.createBitcast(src.getPointer(), u8PtrTy);
20692069
mlir::Value resultU8Ptr = cir::PtrStrideOp::create(builder, loc, u8PtrTy,
20702070
srcU8Ptr, strideToApply);

clang/test/CIR/CodeGen/dynamic-cast-exact.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Derived *ptr_cast(Base1 *ptr) {
3939
// CIR-NEXT: cir.yield %[[NULL]] : !cir.ptr<!rec_Derived>
4040
// CIR-NEXT: }) : (!cir.bool) -> !cir.ptr<!rec_Derived>
4141
// CIR-NEXT: cir.yield %[[EXACT_RESULT]] : !cir.ptr<!rec_Derived>
42-
// CIR-NEXT: }) : (!cir.bool) -> !cir.ptr<!rec_Derived>
42+
// CIR-NEXT: }) : (!cir.bool) -> !cir.ptr<!rec_Derived>
4343

4444
// Note: The LLVM output omits the label for the entry block (which is
4545
// implicitly %1), so we use %{{.*}} to match the implicit label in the
@@ -112,3 +112,63 @@ Derived &ref_cast(Base1 &ref) {
112112
// OGCG: [[LABEL_END]]:
113113
// OGCG-NEXT: ret ptr %[[REF]]
114114
// OGCG-NEXT: }
115+
116+
struct Offset { virtual ~Offset(); };
117+
struct A { virtual ~A(); };
118+
struct B final : Offset, A { };
119+
120+
B *offset_cast(A *a) {
121+
return dynamic_cast<B*>(a);
122+
}
123+
124+
// CIR: cir.func {{.*}} @_Z11offset_castP1A
125+
// CIR: %[[SRC:.*]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
126+
// CIR-NEXT: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null>
127+
// CIR-NEXT: %[[SRC_IS_NULL:.*]] = cir.cmp(eq, %[[SRC]], %[[NULL_PTR]])
128+
// CIR-NEXT: %[[RESULT:.*]] = cir.ternary(%[[SRC_IS_NULL]], true {
129+
// CIR-NEXT: %[[NULL_PTR_DEST:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_B>
130+
// CIR-NEXT: cir.yield %[[NULL_PTR_DEST]] : !cir.ptr<!rec_B>
131+
// CIR-NEXT: }, false {
132+
// CIR-NEXT: %[[EXPECTED_VPTR:.*]] = cir.vtable.address_point(@_ZTV1B, address_point = <index = 1, offset = 2>) : !cir.vptr
133+
// CIR-NEXT: %[[SRC_VPTR_PTR:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_A> -> !cir.ptr<!cir.vptr>
134+
// CIR-NEXT: %[[SRC_VPTR:.*]] = cir.load{{.*}} %[[SRC_VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
135+
// CIR-NEXT: %[[SUCCESS:.*]] = cir.cmp(eq, %[[SRC_VPTR]], %[[EXPECTED_VPTR]]) : !cir.vptr, !cir.bool
136+
// CIR-NEXT: %[[EXACT_RESULT:.*]] = cir.ternary(%[[SUCCESS]], true {
137+
// CIR-NEXT: %[[MINUS_EIGHT:.*]] = cir.const #cir.int<18446744073709551608> : !u64i
138+
// CIR-NEXT: %[[SRC_VOID:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_A> -> !cir.ptr<!u8i>
139+
// CIR-NEXT: %[[SRC_OFFSET:.*]] = cir.ptr_stride %[[SRC_VOID]], %[[MINUS_EIGHT]]
140+
// CIR-NEXT: %[[RES:.*]] = cir.cast bitcast %[[SRC_OFFSET]] : !cir.ptr<!u8i> -> !cir.ptr<!rec_B>
141+
// CIR-NEXT: cir.yield %[[RES]] : !cir.ptr<!rec_B>
142+
// CIR-NEXT: }, false {
143+
// CIR-NEXT: %[[NULL:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_B>
144+
// CIR-NEXT: cir.yield %[[NULL]] : !cir.ptr<!rec_B>
145+
// CIR-NEXT: }) : (!cir.bool) -> !cir.ptr<!rec_B>
146+
// CIR-NEXT: cir.yield %[[EXACT_RESULT]] : !cir.ptr<!rec_B>
147+
// CIR-NEXT: }) : (!cir.bool) -> !cir.ptr<!rec_B>
148+
149+
// LLVM: define dso_local ptr @_Z11offset_castP1A(ptr{{.*}} %[[SRC:.*]])
150+
// LLVM-NEXT: %[[SRC_IS_NULL:.*]] = icmp eq ptr %0, null
151+
// LLVM-NEXT: br i1 %[[SRC_IS_NULL]], label %[[LABEL_END:.*]], label %[[LABEL_NOTNULL:.*]]
152+
// LLVM: [[LABEL_NOTNULL]]:
153+
// LLVM-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[SRC]]
154+
// LLVM-NEXT: %[[VTABLE_CHECK:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds nuw (i8, ptr @_ZTV1B, i64 48)
155+
// LLVM-NEXT: %[[SRC_OFFSET:.*]] = getelementptr i8, ptr %[[SRC]], i64 -8
156+
// LLVM-NEXT: %[[EXACT_RESULT:.*]] = select i1 %[[VTABLE_CHECK]], ptr %[[SRC_OFFSET]], ptr null
157+
// LLVM-NEXT: br label %[[LABEL_END]]
158+
// LLVM: [[LABEL_END]]:
159+
// LLVM-NEXT: %[[RESULT:.*]] = phi ptr [ %[[EXACT_RESULT]], %[[LABEL_NOTNULL]] ], [ null, %{{.*}} ]
160+
// LLVM-NEXT: ret ptr %[[RESULT]]
161+
// LLVM-NEXT: }
162+
163+
// OGCG: define{{.*}} ptr @_Z11offset_castP1A(ptr{{.*}} %[[SRC:.*]])
164+
// OGCG: %[[SRV_NULL:.*]] = icmp eq ptr %[[SRC]], null
165+
// OGCG-NEXT: br i1 %[[SRV_NULL]], label %[[LABEL_NULL:.*]], label %[[LABEL_NOTNULL:.*]]
166+
// OGCG: [[LABEL_NOTNULL]]:
167+
// OGCG-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[SRC]]
168+
// OGCG-NEXT: %[[VTABLE_CHECK:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds nuw inrange(-16, 16) (i8, ptr @_ZTV1B, i64 48)
169+
// OGCG-NEXT: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[SRC]], i64 -8
170+
// OGCG-NEXT: br i1 %[[VTABLE_CHECK]], label %[[LABEL_END:.*]], label %[[LABEL_NULL]]
171+
// OGCG: [[LABEL_NULL]]:
172+
// OGCG-NEXT: br label %[[LABEL_END]]
173+
// OGCG: [[LABEL_END]]:
174+
// OGCG-NEXT: phi ptr [ %[[RESULT]], %[[LABEL_NOTNULL]] ], [ null, %[[LABEL_NULL]] ]

0 commit comments

Comments
 (0)