We have been using the default names for global symbols to this point. This change introduces proper name mangling for functions. This requires introducing a CXXABI class in the CIRGenModule. Because only target independent name mangling is handled in this patch, the CXXABI class does not require a target-specific implementation. The general mechanism for selecting an implementation is introduced here, but the actual target-specific subclasses are deferred until needed.
390 lines
11 KiB
C++
390 lines
11 KiB
C++
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
|
|
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
|
|
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
|
|
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
|
|
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
|
|
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
|
|
|
|
void l0() {
|
|
for (;;) {
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func @_Z2l0v
|
|
// CIR: cir.scope {
|
|
// CIR: cir.for : cond {
|
|
// CIR: %[[TRUE:.*]] = cir.const #true
|
|
// CIR: cir.condition(%[[TRUE]])
|
|
// CIR: } body {
|
|
// CIR: cir.yield
|
|
// CIR: } step {
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: }
|
|
// CIR: cir.return
|
|
// CIR: }
|
|
|
|
// LLVM: define void @_Z2l0v()
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL5:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: br label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL5]]:
|
|
// LLVM: br label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z2l0v()
|
|
// OGCG: entry:
|
|
// OGCG: br label %[[FOR_COND:.*]]
|
|
// OGCG: [[FOR_COND]]:
|
|
// OGCG: br label %[[FOR_COND]]
|
|
|
|
void l1() {
|
|
for (int i = 0; ; ) {
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func @_Z2l1v
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
|
|
// CIR-NEXT: cir.store %[[ZERO]], %[[I]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: cir.for : cond {
|
|
// CIR-NEXT: %[[TRUE:.*]] = cir.const #true
|
|
// CIR-NEXT: cir.condition(%[[TRUE]])
|
|
// CIR-NEXT: } body {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: } step {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.return
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define void @_Z2l1v()
|
|
// LLVM: %[[I:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: store i32 0, ptr %[[I]], align 4
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL5:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: br label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL5]]:
|
|
// LLVM: br label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z2l1v()
|
|
// OGCG: entry:
|
|
// OGCG: %[[I:.*]] = alloca i32, align 4
|
|
// OGCG: store i32 0, ptr %[[I]], align 4
|
|
// OGCG: br label %[[FOR_COND:.*]]
|
|
// OGCG: [[FOR_COND]]:
|
|
// OGCG: br label %[[FOR_COND]]
|
|
|
|
void l2() {
|
|
for (;;) {
|
|
int i = 0;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func @_Z2l2v
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: cir.for : cond {
|
|
// CIR-NEXT: %[[TRUE:.*]] = cir.const #true
|
|
// CIR-NEXT: cir.condition(%[[TRUE]])
|
|
// CIR-NEXT: } body {
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
|
|
// CIR-NEXT: cir.store %[[ZERO]], %[[I]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: } step {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.return
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define void @_Z2l2v()
|
|
// LLVM: %[[I:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL5:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: store i32 0, ptr %[[I]], align 4
|
|
// LLVM: br label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL5]]:
|
|
// LLVM: br label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z2l2v()
|
|
// OGCG: entry:
|
|
// OGCG: %[[I:.*]] = alloca i32, align 4
|
|
// OGCG: br label %[[FOR_COND:.*]]
|
|
// OGCG: [[FOR_COND]]:
|
|
// OGCG: store i32 0, ptr %[[I]], align 4
|
|
// OGCG: br label %[[FOR_COND]]
|
|
|
|
// This is the same as l2 but without a compound statement for the body.
|
|
void l3() {
|
|
for (;;)
|
|
int i = 0;
|
|
}
|
|
|
|
// CIR: cir.func @_Z2l3v
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
|
|
// CIR-NEXT: cir.for : cond {
|
|
// CIR-NEXT: %[[TRUE:.*]] = cir.const #true
|
|
// CIR-NEXT: cir.condition(%[[TRUE]])
|
|
// CIR-NEXT: } body {
|
|
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
|
|
// CIR-NEXT: cir.store %[[ZERO]], %[[I]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: } step {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.return
|
|
// CIR-NEXT: }
|
|
|
|
// LLVM: define void @_Z2l3v()
|
|
// LLVM: %[[I:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL5:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: store i32 0, ptr %[[I]], align 4
|
|
// LLVM: br label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL5]]:
|
|
// LLVM: br label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z2l3v()
|
|
// OGCG: entry:
|
|
// OGCG: %[[I:.*]] = alloca i32, align 4
|
|
// OGCG: br label %[[FOR_COND:.*]]
|
|
// OGCG: [[FOR_COND]]:
|
|
// OGCG: store i32 0, ptr %[[I]], align 4
|
|
// OGCG: br label %[[FOR_COND]]
|
|
|
|
void test_do_while_false() {
|
|
do {
|
|
} while (0);
|
|
}
|
|
|
|
// CIR: cir.func @_Z19test_do_while_falsev()
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: cir.do {
|
|
// CIR-NEXT: cir.yield
|
|
// CIR-NEXT: } while {
|
|
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
|
|
// CIR-NEXT: %[[FALSE:.*]] = cir.cast(int_to_bool, %[[ZERO]] : !s32i), !cir.bool
|
|
// CIR-NEXT: cir.condition(%[[FALSE]])
|
|
|
|
// LLVM: define void @_Z19test_do_while_falsev()
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL3:.*]]
|
|
// LLVM: [[LABEL2:.*]]:
|
|
// LLVM: br i1 false, label %[[LABEL3]], label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL5:.*]]
|
|
// LLVM: [[LABEL5]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z19test_do_while_falsev()
|
|
// OGCG: entry:
|
|
// OGCG: br label %[[DO_BODY:.*]]
|
|
// OGCG: [[DO_BODY]]:
|
|
// OGCG: br label %[[DO_END:.*]]
|
|
// OGCG: [[DO_END]]:
|
|
// OGCG: ret void
|
|
|
|
void test_empty_while_true() {
|
|
while (true) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func @_Z21test_empty_while_truev()
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: cir.while {
|
|
// CIR-NEXT: %[[TRUE:.*]] = cir.const #true
|
|
// CIR-NEXT: cir.condition(%[[TRUE]])
|
|
// CIR-NEXT: } do {
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: cir.return
|
|
// CIR-NEXT: }
|
|
// CIR-NEXT: cir.yield
|
|
|
|
// LLVM: define void @_Z21test_empty_while_truev()
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: br label %[[LABEL4]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: ret void
|
|
// LLVM: [[LABEL5:.*]]:
|
|
// LLVM-SAME: ; No predecessors!
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: br label %[[LABEL7:.*]]
|
|
// LLVM: [[LABEL7]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z21test_empty_while_truev()
|
|
// OGCG: entry:
|
|
// OGCG: br label %[[WHILE_BODY:.*]]
|
|
// OGCG: [[WHILE_BODY]]:
|
|
// OGCG: ret void
|
|
|
|
void unreachable_after_continue() {
|
|
for (;;) {
|
|
continue;
|
|
int x = 1;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func @_Z26unreachable_after_continuev()
|
|
// CIR: cir.scope {
|
|
// CIR: cir.for : cond {
|
|
// CIR: %[[TRUE:.*]] = cir.const #true
|
|
// CIR: cir.condition(%[[TRUE]])
|
|
// CIR: } body {
|
|
// CIR: cir.scope {
|
|
// CIR: %[[X:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
|
|
// CIR: cir.continue
|
|
// CIR: ^bb1: // no predecessors
|
|
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
|
// CIR: cir.store %[[ONE]], %[[X]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: cir.yield
|
|
// CIR: } step {
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: }
|
|
// CIR: cir.return
|
|
// CIR: }
|
|
|
|
// LLVM: define void @_Z26unreachable_after_continuev()
|
|
// LLVM: %[[X:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL8:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: br label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL7:.*]]
|
|
// LLVM: [[LABEL5:.*]]:
|
|
// LLVM-SAME: ; No predecessors!
|
|
// LLVM: store i32 1, ptr %[[X]], align 4
|
|
// LLVM: br label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: br label %[[LABEL7:.*]]
|
|
// LLVM: [[LABEL7]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL8]]:
|
|
// LLVM: br label %[[LABEL9:]]
|
|
// LLVM: [[LABEL9]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z26unreachable_after_continuev()
|
|
// OGCG: entry:
|
|
// OGCG: %[[X:.*]] = alloca i32, align 4
|
|
// OGCG: br label %[[FOR_COND:.*]]
|
|
// OGCG: [[FOR_COND]]:
|
|
// OGCG: br label %[[FOR_COND]]
|
|
|
|
void unreachable_after_break() {
|
|
for (;;) {
|
|
break;
|
|
int x = 1;
|
|
}
|
|
}
|
|
|
|
// CIR: cir.func @_Z23unreachable_after_breakv()
|
|
// CIR: cir.scope {
|
|
// CIR: cir.for : cond {
|
|
// CIR: %[[TRUE:.*]] = cir.const #true
|
|
// CIR: cir.condition(%[[TRUE]])
|
|
// CIR: } body {
|
|
// CIR: cir.scope {
|
|
// CIR: %[[X:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
|
|
// CIR: cir.break
|
|
// CIR: ^bb1: // no predecessors
|
|
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
|
|
// CIR: cir.store %[[ONE]], %[[X]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: cir.yield
|
|
// CIR: } step {
|
|
// CIR: cir.yield
|
|
// CIR: }
|
|
// CIR: }
|
|
// CIR: cir.return
|
|
// CIR: }
|
|
|
|
// LLVM: define void @_Z23unreachable_after_breakv()
|
|
// LLVM: %[[X:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: br label %[[LABEL1:.*]]
|
|
// LLVM: [[LABEL1]]:
|
|
// LLVM: br label %[[LABEL2:.*]]
|
|
// LLVM: [[LABEL2]]:
|
|
// LLVM: br i1 true, label %[[LABEL3:.*]], label %[[LABEL8:.*]]
|
|
// LLVM: [[LABEL3]]:
|
|
// LLVM: br label %[[LABEL4:.*]]
|
|
// LLVM: [[LABEL4]]:
|
|
// LLVM: br label %[[LABEL8]]
|
|
// LLVM: [[LABEL5:.*]]:
|
|
// LLVM-SAME: ; No predecessors!
|
|
// LLVM: store i32 1, ptr %[[X]], align 4
|
|
// LLVM: br label %[[LABEL6:.*]]
|
|
// LLVM: [[LABEL6]]:
|
|
// LLVM: br label %[[LABEL7:.*]]
|
|
// LLVM: [[LABEL7]]:
|
|
// LLVM: br label %[[LABEL2]]
|
|
// LLVM: [[LABEL8]]:
|
|
// LLVM: br label %[[LABEL9:]]
|
|
// LLVM: [[LABEL9]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @_Z23unreachable_after_breakv()
|
|
// OGCG: entry:
|
|
// OGCG: %[[X:.*]] = alloca i32, align 4
|
|
// OGCG: br label %[[FOR_COND:.*]]
|
|
// OGCG: [[FOR_COND]]:
|
|
// OGCG: br label %[[FOR_END:.*]]
|
|
// OGCG: [[FOR_END]]:
|
|
// OGCG: ret void
|