@@ -101,3 +101,59 @@ Derived &ref_cast(Base &b) {
101101// OGCG: br i1 %[[IS_NULL]], label %[[BAD_CAST:.*]], label %[[DONE:.*]]
102102// OGCG: [[BAD_CAST]]:
103103// OGCG: call void @__cxa_bad_cast()
104+
105+ void *ptr_cast_to_complete (Base *ptr) {
106+ return dynamic_cast <void *>(ptr);
107+ }
108+
109+ // CIR-BEFORE: cir.func dso_local @_Z20ptr_cast_to_completeP4Base
110+ // CIR-BEFORE: %{{.+}} = cir.dyn_cast ptr %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!void>
111+ // CIR-BEFORE: }
112+
113+ // CIR-AFTER: cir.func dso_local @_Z20ptr_cast_to_completeP4Base
114+ // CIR-AFTER: %[[SRC:.*]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base>>, !cir.ptr<!rec_Base>
115+ // CIR-AFTER-NEXT: %[[SRC_IS_NOT_NULL:.*]] = cir.cast ptr_to_bool %[[SRC]] : !cir.ptr<!rec_Base> -> !cir.bool
116+ // CIR-AFTER-NEXT: %{{.+}} = cir.ternary(%[[SRC_IS_NOT_NULL]], true {
117+ // CIR-AFTER-NEXT: %[[VPTR_PTR:.*]] = cir.vtable.get_vptr %[[SRC]] : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr>
118+ // CIR-AFTER-NEXT: %[[VPTR:.*]] = cir.load %[[VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr
119+ // CIR-AFTER-NEXT: %[[ELEM_PTR:.*]] = cir.cast bitcast %[[VPTR]] : !cir.vptr -> !cir.ptr<!s64i>
120+ // CIR-AFTER-NEXT: %[[MINUS_TWO:.*]] = cir.const #cir.int<-2> : !s64i
121+ // CIR-AFTER-NEXT: %[[BASE_OFFSET_PTR:.*]] = cir.ptr_stride %[[ELEM_PTR]], %[[MINUS_TWO]] : (!cir.ptr<!s64i>, !s64i) -> !cir.ptr<!s64i>
122+ // CIR-AFTER-NEXT: %[[BASE_OFFSET:.*]] = cir.load{{.*}} %[[BASE_OFFSET_PTR]] : !cir.ptr<!s64i>, !s64i
123+ // CIR-AFTER-NEXT: %[[SRC_BYTES_PTR:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base> -> !cir.ptr<!u8i>
124+ // CIR-AFTER-NEXT: %[[DST_BYTES_PTR:.*]] = cir.ptr_stride %[[SRC_BYTES_PTR]], %[[BASE_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i>
125+ // CIR-AFTER-NEXT: %[[CASTED_PTR:.*]] = cir.cast bitcast %[[DST_BYTES_PTR]] : !cir.ptr<!u8i> -> !cir.ptr<!void>
126+ // CIR-AFTER-NEXT: cir.yield %[[CASTED_PTR]] : !cir.ptr<!void>
127+ // CIR-AFTER-NEXT: }, false {
128+ // CIR-AFTER-NEXT: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
129+ // CIR-AFTER-NEXT: cir.yield %[[NULL_PTR]] : !cir.ptr<!void>
130+ // CIR-AFTER-NEXT: }) : (!cir.bool) -> !cir.ptr<!void>
131+ // CIR-AFTER: }
132+
133+ // LLVM: define {{.*}} @_Z20ptr_cast_to_completeP4Base
134+ // LLVM: %[[IS_NOT_NULL:.*]] = icmp ne ptr %[[PTR:.*]], null
135+ // LLVM: br i1 %[[IS_NOT_NULL]], label %[[NOT_NULL:.*]], label %[[NULL:.*]]
136+ // LLVM: [[NOT_NULL]]:
137+ // LLVM: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]
138+ // LLVM: %[[BASE_OFFSET_PTR:.*]] = getelementptr i64, ptr %7, i64 -2
139+ // LLVM: %[[BASE_OFFSET:.*]] = load i64, ptr %[[BASE_OFFSET_PTR]]
140+ // LLVM: %[[RESULT:.*]] = getelementptr i8, ptr %[[PTR]], i64 %[[BASE_OFFSET]]
141+ // LLVM: br label %[[DONE:.*]]
142+ // LLVM: [[NULL]]:
143+ // LLVM: br label %[[DONE]]
144+ // LLVM: [[DONE]]:
145+ // LLVM: %[[RET:.*]] = phi ptr [ null, %[[NULL]] ], [ %[[RESULT]], %[[NOT_NULL]] ]
146+
147+ // OGCG: define {{.*}} @_Z20ptr_cast_to_completeP4Base
148+ // OGCG: %[[IS_NULL:.*]] = icmp eq ptr %[[PTR:.*]], null
149+ // OGCG: br i1 %[[IS_NULL]], label %[[NULL:.*]], label %[[NOT_NULL:.*]]
150+ // OGCG: [[NOT_NULL]]:
151+ // OGCG: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]
152+ // OGCG: %[[BASE_OFFSET_PTR:.*]] = getelementptr inbounds i64, ptr %[[VPTR]], i64 -2
153+ // OGCG: %[[BASE_OFFSET:.*]] = load i64, ptr %[[BASE_OFFSET_PTR]]
154+ // OGCG: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 %[[BASE_OFFSET]]
155+ // OGCG: br label %[[DONE:.*]]
156+ // OGCG: [[NULL]]:
157+ // OGCG: br label %[[DONE]]
158+ // OGCG: [[DONE]]:
159+ // OGCG: %[[RET:.*]] = phi ptr [ %[[RESULT]], %[[NOT_NULL]] ], [ null, %[[NULL]] ]
0 commit comments