brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.8 KiB · 9ddb68f Raw
209 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O1 -fclangir -clangir-disable-passes -emit-cir -o %t.cir %s2// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR3// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O1 -fclangir -emit-llvm -o %t-cir.ll %s4// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s5// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O1 -emit-llvm -o %t.ll %s6// RUN: FileCheck --input-file=%t.ll --check-prefix=OGCG %s7 8struct Base1 {9  virtual ~Base1();10};11 12struct Base2 {13  virtual ~Base2();14};15 16struct Derived final : Base1 {};17 18Derived *ptr_cast(Base1 *ptr) {19  return dynamic_cast<Derived *>(ptr);20}21 22//      CIR: cir.func {{.*}} @_Z8ptr_castP5Base123//      CIR:   %[[SRC:.*]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base1>>, !cir.ptr<!rec_Base1>24// CIR-NEXT:   %[[NULL_PTR:.*]] = cir.const #cir.ptr<null>25// CIR-NEXT:   %[[SRC_IS_NULL:.*]] = cir.cmp(eq, %[[SRC]], %[[NULL_PTR]])26// CIR-NEXT:   %[[RESULT:.*]] = cir.ternary(%[[SRC_IS_NULL]], true {27// CIR-NEXT:     %[[NULL_PTR_DEST:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_Derived>28// CIR-NEXT:     cir.yield %[[NULL_PTR_DEST]] : !cir.ptr<!rec_Derived>29// CIR-NEXT:   }, false {30// CIR-NEXT:     %[[EXPECTED_VPTR:.*]] = cir.vtable.address_point(@_ZTV7Derived, address_point = <index = 0, offset = 2>) : !cir.vptr31// CIR-NEXT:     %[[SRC_VPTR_PTR:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base1> -> !cir.ptr<!cir.vptr>32// CIR-NEXT:     %[[SRC_VPTR:.*]] = cir.load{{.*}} %[[SRC_VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr33// CIR-NEXT:     %[[SUCCESS:.*]] = cir.cmp(eq, %[[SRC_VPTR]], %[[EXPECTED_VPTR]]) : !cir.vptr, !cir.bool34// CIR-NEXT:     %[[EXACT_RESULT:.*]] = cir.ternary(%[[SUCCESS]], true {35// CIR-NEXT:       %[[RES:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base1> -> !cir.ptr<!rec_Derived>36// CIR-NEXT:       cir.yield %[[RES]] : !cir.ptr<!rec_Derived>37// CIR-NEXT:     }, false {38// CIR-NEXT:       %[[NULL:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_Derived>39// CIR-NEXT:       cir.yield %[[NULL]] : !cir.ptr<!rec_Derived>40// CIR-NEXT:     }) : (!cir.bool) -> !cir.ptr<!rec_Derived>41// CIR-NEXT:     cir.yield %[[EXACT_RESULT]] : !cir.ptr<!rec_Derived>42// CIR-NEXT:   }) : (!cir.bool) -> !cir.ptr<!rec_Derived>43 44// Note: The LLVM output omits the label for the entry block (which is45//       implicitly %1), so we use %{{.*}} to match the implicit label in the46//       phi check.47 48//      LLVM: define dso_local ptr @_Z8ptr_castP5Base1(ptr{{.*}} %[[SRC:.*]])49// LLVM-NEXT:   %[[SRC_IS_NULL:.*]] = icmp eq ptr %0, null50// LLVM-NEXT:   br i1 %[[SRC_IS_NULL]], label %[[LABEL_END:.*]], label %[[LABEL_NOTNULL:.*]]51//      LLVM: [[LABEL_NOTNULL]]:52// LLVM-NEXT:   %[[VPTR:.*]] = load ptr, ptr %[[SRC]], align 853// LLVM-NEXT:   %[[SUCCESS:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds nuw (i8, ptr @_ZTV7Derived, i64 16)54// LLVM-NEXT:   %[[EXACT_RESULT:.*]] = select i1 %[[SUCCESS]], ptr %[[SRC]], ptr null55// LLVM-NEXT:   br label %[[LABEL_END]]56//      LLVM: [[LABEL_END]]:57// LLVM-NEXT:   %[[RESULT:.*]] = phi ptr [ %[[EXACT_RESULT]], %[[LABEL_NOTNULL]] ], [ null, %{{.*}} ]58// LLVM-NEXT:   ret ptr %[[RESULT]]59// LLVM-NEXT: }60 61//      OGCG: define{{.*}} ptr @_Z8ptr_castP5Base1(ptr {{.*}} %[[SRC:.*]])62// OGCG-NEXT: entry:63// OGCG-NEXT:   %[[NULL_CHECK:.*]] = icmp eq ptr %[[SRC]], null64// OGCG-NEXT:   br i1 %[[NULL_CHECK]], label %[[LABEL_NULL:.*]], label %[[LABEL_NOTNULL:.*]]65//      OGCG: [[LABEL_NOTNULL]]:66// OGCG-NEXT:   %[[VTABLE:.*]] = load ptr, ptr %[[SRC]], align 867// OGCG-NEXT:   %[[VTABLE_CHECK:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds {{.*}} (i8, ptr @_ZTV7Derived, i64 16)68// OGCG-NEXT:   br i1 %[[VTABLE_CHECK]], label %[[LABEL_END:.*]], label %[[LABEL_NULL]]69//      OGCG: [[LABEL_NULL]]:70// OGCG-NEXT:   br label %[[LABEL_END]]71//      OGCG: [[LABEL_END]]:72// OGCG-NEXT:   %[[RESULT:.*]] = phi ptr [ %[[SRC]], %[[LABEL_NOTNULL]] ], [ null, %[[LABEL_NULL]] ]73// OGCG-NEXT:   ret ptr %[[RESULT]]74// OGCG-NEXT: }75 76Derived &ref_cast(Base1 &ref) {77  return dynamic_cast<Derived &>(ref);78}79 80//      CIR: cir.func {{.*}} @_Z8ref_castR5Base181//      CIR:   %[[SRC:.*]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base1>>, !cir.ptr<!rec_Base1>82// CIR-NEXT:   %[[EXPECTED_VPTR:.*]] = cir.vtable.address_point(@_ZTV7Derived, address_point = <index = 0, offset = 2>) : !cir.vptr83// CIR-NEXT:   %[[SRC_VPTR_PTR:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base1> -> !cir.ptr<!cir.vptr>84// CIR-NEXT:   %[[SRC_VPTR:.*]] = cir.load{{.*}} %[[SRC_VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr85// CIR-NEXT:   %[[SUCCESS:.*]] = cir.cmp(eq, %[[SRC_VPTR]], %[[EXPECTED_VPTR]]) : !cir.vptr, !cir.bool86// CIR-NEXT:   %[[FAILED:.*]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool87// CIR-NEXT:   cir.if %[[FAILED]] {88// CIR-NEXT:     cir.call @__cxa_bad_cast() : () -> ()89// CIR-NEXT:     cir.unreachable90// CIR-NEXT:   }91// CIR-NEXT:   %{{.+}} = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base1> -> !cir.ptr<!rec_Derived>92 93//      LLVM: define{{.*}} ptr @_Z8ref_castR5Base1(ptr{{.*}} %[[SRC:.*]])94// LLVM-NEXT:   %[[VPTR:.*]] = load ptr, ptr %[[SRC]], align 895// LLVM-NEXT:   %[[OK:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds nuw (i8, ptr @_ZTV7Derived, i64 16)96// LLVM-NEXT:   br i1 %[[OK]], label %[[LABEL_OK:.*]], label %[[LABEL_FAIL:.*]]97//      LLVM: [[LABEL_FAIL]]:98// LLVM-NEXT:   tail call void @__cxa_bad_cast()99// LLVM-NEXT:   unreachable100//      LLVM: [[LABEL_OK]]:101// LLVM-NEXT:   ret ptr %[[SRC]]102// LLVM-NEXT: }103 104//      OGCG: define{{.*}} ptr @_Z8ref_castR5Base1(ptr {{.*}} %[[REF:.*]])105// OGCG-NEXT: entry:106// OGCG-NEXT:   %[[VTABLE:.*]] = load ptr, ptr %[[REF]], align 8107// OGCG-NEXT:   %[[VTABLE_CHECK:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds {{.*}} (i8, ptr @_ZTV7Derived, i64 16)108// OGCG-NEXT:   br i1 %[[VTABLE_CHECK]], label %[[LABEL_END:.*]], label %[[LABEL_NULL:.*]]109//      OGCG: [[LABEL_NULL]]:110// OGCG-NEXT:   {{.*}}call void @__cxa_bad_cast()111// OGCG-NEXT:   unreachable112//      OGCG: [[LABEL_END]]:113// OGCG-NEXT:   ret ptr %[[REF]]114// OGCG-NEXT: }115 116struct Offset { virtual ~Offset(); };117struct A { virtual ~A(); };118struct B final : Offset, A { };119 120B *offset_cast(A *a) {121  return dynamic_cast<B*>(a);122}123 124//      CIR: cir.func {{.*}} @_Z11offset_castP1A125//      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.vptr133// 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.vptr135// CIR-NEXT:     %[[SUCCESS:.*]] = cir.cmp(eq, %[[SRC_VPTR]], %[[EXPECTED_VPTR]]) : !cir.vptr, !cir.bool136// CIR-NEXT:     %[[EXACT_RESULT:.*]] = cir.ternary(%[[SUCCESS]], true {137// CIR-NEXT:       %[[MINUS_EIGHT:.*]] = cir.const #cir.int<18446744073709551608> : !u64i138// 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, null151// 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 -8156// LLVM-NEXT:   %[[EXACT_RESULT:.*]] = select i1 %[[VTABLE_CHECK]], ptr %[[SRC_OFFSET]], ptr null157// 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]], null165// 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 -8170// 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]] ]175 176Derived *ptr_cast_always_fail(Base2 *ptr) {177    return dynamic_cast<Derived *>(ptr);178  }179 180//      CIR: cir.func {{.*}} @_Z20ptr_cast_always_failP5Base2181//      CIR:   %{{.+}} = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2>182// CIR-NEXT:   %[[RESULT:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!rec_Derived>183// CIR-NEXT:   cir.store %[[RESULT]], %{{.*}} : !cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!rec_Derived>>184 185//      LLVM: define {{.*}} ptr @_Z20ptr_cast_always_failP5Base2186// LLVM-NEXT:   ret ptr null187 188//      OGCG: define {{.*}} ptr @_Z20ptr_cast_always_failP5Base2189// OGCG-NEXT: entry:190// OGCG-NEXT:   ret ptr null191 192Derived &ref_cast_always_fail(Base2 &ref) {193  return dynamic_cast<Derived &>(ref);194}195 196//      CIR: cir.func {{.*}} @_Z20ref_cast_always_failR5Base2197//      CIR:   %{{.+}} = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2>198// CIR-NEXT:   cir.call @__cxa_bad_cast() : () -> ()199// CIR-NEXT:   cir.unreachable200 201//      LLVM: define {{.*}} ptr @_Z20ref_cast_always_failR5Base2202// LLVM-NEXT:   tail call void @__cxa_bad_cast()203// LLVM-NEXT:   unreachable204 205//      OGCG: define {{.*}} ptr @_Z20ref_cast_always_failR5Base2206// OGCG-NEXT: entry:207// OGCG-NEXT:   tail call void @__cxa_bad_cast()208// OGCG-NEXT:   unreachable209