
This change adds a handler for emitting a cir.constant op when a character literal is encountered outside an initializer expression.
326 lines
11 KiB
C
326 lines
11 KiB
C
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
|
|
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
|
|
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
|
|
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
|
|
|
|
enum A {
|
|
A_one,
|
|
A_two
|
|
};
|
|
enum A a;
|
|
|
|
// CHECK: cir.global external @a = #cir.int<0> : !u32i
|
|
|
|
enum B : int;
|
|
enum B b;
|
|
|
|
// CHECK: cir.global external @b = #cir.int<0> : !u32i
|
|
|
|
|
|
enum C : int {
|
|
C_one,
|
|
C_two
|
|
};
|
|
enum C c;
|
|
|
|
// CHECK: cir.global external @c = #cir.int<0> : !u32i
|
|
|
|
int f1(int i);
|
|
|
|
int f1(int i) {
|
|
i;
|
|
return i;
|
|
}
|
|
|
|
// CIR: cir.func @f1(%arg0: !s32i loc({{.*}})) -> !s32i
|
|
// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
|
|
// CIR-NEXT: cir.store{{.*}} %arg0, %[[I_PTR]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[I_IGNORED:.*]] = cir.load{{.*}} %[[I_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: %[[I:.*]] = cir.load{{.*}} %[[I_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[I]], %[[RV]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %[[RV]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.return %[[R]] : !s32i
|
|
|
|
// LLVM: define i32 @f1(i32 %[[IP:.*]])
|
|
// LLVM-NEXT: %[[I_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: %[[RV:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: store i32 %[[IP]], ptr %[[I_PTR]], align 4
|
|
// LLVM-NEXT: %[[I_IGNORED:.*]] = load i32, ptr %[[I_PTR]], align 4
|
|
// LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4
|
|
// LLVM-NEXT: store i32 %[[I]], ptr %[[RV]], align 4
|
|
// LLVM-NEXT: %[[R:.*]] = load i32, ptr %[[RV]], align 4
|
|
// LLVM-NEXT: ret i32 %[[R]]
|
|
|
|
// OGCG: define{{.*}} i32 @f1(i32 noundef %[[I:.*]])
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: %[[I_PTR:.*]] = alloca i32, align 4
|
|
// OGCG-NEXT: store i32 %[[I]], ptr %[[I_PTR]], align 4
|
|
// OGCG-NEXT: %[[I_IGNORED:.*]] = load i32, ptr %[[I_PTR]], align 4
|
|
// OGCG-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4
|
|
// OGCG-NEXT: ret i32 %[[I]]
|
|
|
|
int f2(void) { return 3; }
|
|
|
|
// CIR: cir.func @f2() -> !s32i
|
|
// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[THREE]], %[[RV]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %0 : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.return %[[R]] : !s32i
|
|
|
|
// LLVM: define i32 @f2()
|
|
// LLVM-NEXT: %[[RV:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: store i32 3, ptr %[[RV]], align 4
|
|
// LLVM-NEXT: %[[R:.*]] = load i32, ptr %[[RV]], align 4
|
|
// LLVM-NEXT: ret i32 %[[R]]
|
|
|
|
// OGCG: define{{.*}} i32 @f2()
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: ret i32 3
|
|
|
|
int f3(void) {
|
|
int i = 3;
|
|
return i;
|
|
}
|
|
|
|
// CIR: cir.func @f3() -> !s32i
|
|
// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[THREE]], %[[I_PTR]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[I:.*]] = cir.load{{.*}} %[[I_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[I]], %[[RV]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %[[RV]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.return %[[R]] : !s32i
|
|
|
|
// LLVM: define i32 @f3()
|
|
// LLVM-NEXT: %[[RV:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: %[[I_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: store i32 3, ptr %[[I_PTR]], align 4
|
|
// LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4
|
|
// LLVM-NEXT: store i32 %[[I]], ptr %[[RV]], align 4
|
|
// LLVM-NEXT: %[[R:.*]] = load i32, ptr %[[RV]], align 4
|
|
// LLVM-NEXT: ret i32 %[[R]]
|
|
|
|
// OGCG: define{{.*}} i32 @f3
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: %[[I_PTR:.*]] = alloca i32, align 4
|
|
// OGCG-NEXT: store i32 3, ptr %[[I_PTR]], align 4
|
|
// OGCG-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4
|
|
// OGCG-NEXT: ret i32 %[[I]]
|
|
|
|
// Verify null statement handling.
|
|
void f4(void) {
|
|
;
|
|
}
|
|
|
|
// CIR: cir.func @f4()
|
|
// CIR-NEXT: cir.return
|
|
|
|
// LLVM: define void @f4()
|
|
// LLVM-NEXT: ret void
|
|
|
|
// OGCG: define{{.*}} void @f4()
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: ret void
|
|
|
|
// Verify null statement as for-loop body.
|
|
void f5(void) {
|
|
for (;;)
|
|
;
|
|
}
|
|
|
|
// CIR: cir.func @f5()
|
|
// CIR-NEXT: cir.scope {
|
|
// CIR-NEXT: cir.for : cond {
|
|
// CIR-NEXT: %0 = cir.const #true
|
|
// CIR-NEXT: cir.condition(%0)
|
|
// 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 @f5()
|
|
// LLVM: br label %[[SCOPE:.*]]
|
|
// LLVM: [[SCOPE]]:
|
|
// LLVM: br label %[[LOOP:.*]]
|
|
// LLVM: [[LOOP]]:
|
|
// LLVM: br i1 true, label %[[LOOP_STEP:.*]], label %[[LOOP_EXIT:.*]]
|
|
// LLVM: [[LOOP_STEP]]:
|
|
// LLVM: br label %[[LOOP_BODY:.*]]
|
|
// LLVM: [[LOOP_BODY]]:
|
|
// LLVM: br label %[[LOOP]]
|
|
// LLVM: [[LOOP_EXIT]]:
|
|
// LLVM: ret void
|
|
|
|
// OGCG: define{{.*}} void @f5()
|
|
// OGCG: entry:
|
|
// OGCG: br label %[[LOOP:.*]]
|
|
// OGCG: [[LOOP]]:
|
|
// OGCG: br label %[[LOOP]]
|
|
|
|
int gv;
|
|
int f6(void) {
|
|
return gv;
|
|
}
|
|
|
|
// CIR: cir.func @f6() -> !s32i
|
|
// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
|
|
// CIR-NEXT: %[[GV_PTR:.*]] = cir.get_global @gv : !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[GV:.*]] = cir.load{{.*}} %[[GV_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.store{{.*}} %[[GV]], %[[RV]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %[[RV]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR-NEXT: cir.return %[[R]] : !s32i
|
|
|
|
// LLVM: define i32 @f6()
|
|
// LLVM-NEXT: %[[RV_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: %[[GV:.*]] = load i32, ptr @gv, align 4
|
|
// LLVM-NEXT: store i32 %[[GV]], ptr %[[RV_PTR]], align 4
|
|
// LLVM-NEXT: %[[RV:.*]] = load i32, ptr %[[RV_PTR]], align 4
|
|
// LLVM-NEXT: ret i32 %[[RV]]
|
|
|
|
// OGCG: define{{.*}} i32 @f6()
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: %[[GV:.*]] = load i32, ptr @gv, align 4
|
|
// OGCG-NEXT: ret i32 %[[GV]]
|
|
|
|
int f7(int a, int b, int c) {
|
|
return a + (b + c);
|
|
}
|
|
|
|
// CIR: cir.func @f7
|
|
// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
|
|
// CIR: %[[B_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]
|
|
// CIR: %[[C_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init]
|
|
// CIR: %[[A:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR: %[[B:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR: %[[C:.*]] = cir.load{{.*}} %[[C_PTR]] : !cir.ptr<!s32i>, !s32i
|
|
// CIR: %[[B_PLUS_C:.*]] = cir.binop(add, %[[B]], %[[C]]) nsw : !s32i
|
|
// CIR: %[[RETVAL:.*]] = cir.binop(add, %[[A]], %[[B_PLUS_C]]) nsw : !s32i
|
|
|
|
// LLVM: define i32 @f7
|
|
// LLVM: %[[A_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: %[[B_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: %[[C_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM: %[[A:.*]] = load i32, ptr %[[A_PTR]], align 4
|
|
// LLVM: %[[B:.*]] = load i32, ptr %[[B_PTR]], align 4
|
|
// LLVM: %[[C:.*]] = load i32, ptr %[[C_PTR]], align 4
|
|
// LLVM: %[[B_PLUS_C:.*]] = add nsw i32 %[[B]], %[[C]]
|
|
// LLVM: %[[RETVAL:.*]] = add nsw i32 %[[A]], %[[B_PLUS_C]]
|
|
|
|
// OGCG: define{{.*}} i32 @f7
|
|
// OGCG: entry:
|
|
// OGCG: %[[A_PTR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[B_PTR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[C_PTR:.*]] = alloca i32, align 4
|
|
// OGCG: %[[A:.*]] = load i32, ptr %[[A_PTR]], align 4
|
|
// OGCG: %[[B:.*]] = load i32, ptr %[[B_PTR]], align 4
|
|
// OGCG: %[[C:.*]] = load i32, ptr %[[C_PTR]], align 4
|
|
// OGCG: %[[B_PLUS_C:.*]] = add nsw i32 %[[B]], %[[C]]
|
|
// OGCG: %[[RETVAL:.*]] = add nsw i32 %[[A]], %[[B_PLUS_C]]
|
|
|
|
int f8(int *p) {
|
|
(*p) = 2;
|
|
return (*p);
|
|
}
|
|
|
|
// CIR: cir.func @f8
|
|
// CIR: %[[P_PTR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["p", init]
|
|
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
|
|
// CIR: %[[P:.*]] = cir.load deref{{.*}} %[[P_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
|
|
// CIR: cir.store{{.*}} %[[TWO]], %[[P]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR: %[[P2:.*]] = cir.load deref{{.*}} %[[P_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
|
|
// CIR: %[[STAR_P:.*]] = cir.load{{.*}} %[[P2]] : !cir.ptr<!s32i>, !s32i
|
|
|
|
// LLVM: define i32 @f8
|
|
// LLVM: %[[P_PTR:.*]] = alloca ptr, i64 1, align 8
|
|
// LLVM: %[[P:.*]] = load ptr, ptr %[[P_PTR]], align 8
|
|
// LLVM: store i32 2, ptr %[[P]], align 4
|
|
// LLVM: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8
|
|
// LLVM: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4
|
|
|
|
// OGCG: define{{.*}} i32 @f8
|
|
// OGCG: entry:
|
|
// OGCG: %[[P_PTR:.*]] = alloca ptr, align 8
|
|
// OGCG: %[[P:.*]] = load ptr, ptr %[[P_PTR]], align 8
|
|
// OGCG: store i32 2, ptr %[[P]], align 4
|
|
// OGCG: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8
|
|
// OGCG: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4
|
|
|
|
|
|
void f9() {}
|
|
|
|
// CIR: cir.func @f9()
|
|
// CIR-NEXT: cir.return
|
|
|
|
// LLVM: define void @f9()
|
|
// LLVM-NEXT: ret void
|
|
|
|
// OGCG: define{{.*}} void @f9()
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: ret void
|
|
|
|
void f10(int arg0, ...) {}
|
|
|
|
// CIR: cir.func @f10(%[[ARG0:.*]]: !s32i loc({{.*}}), ...)
|
|
// CIR-NEXT: %[[ARG0_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["arg0", init] {alignment = 4 : i64}
|
|
// CIR-NEXT: cir.store{{.*}} %[[ARG0]], %[[ARG0_PTR]] : !s32i, !cir.ptr<!s32i>
|
|
// CIR-NEXT: cir.return
|
|
|
|
// LLVM: define void @f10(i32 %[[ARG0:.*]], ...)
|
|
// LLVM-NEXT: %[[ARG0_PTR:.*]] = alloca i32, i64 1, align 4
|
|
// LLVM-NEXT: store i32 %[[ARG0]], ptr %[[ARG0_PTR]], align 4
|
|
// LLVM-NEXT: ret void
|
|
|
|
// OGCG: define{{.*}} void @f10(i32 noundef %[[ARG0:.*]], ...)
|
|
// OGCG-NEXT: entry:
|
|
// OGCG-NEXT: %[[ARG0_PTR:.*]] = alloca i32, align 4
|
|
// OGCG-NEXT: store i32 %[[ARG0]], ptr %[[ARG0_PTR]], align 4
|
|
// OGCG-NEXT: ret void
|
|
|
|
typedef unsigned long size_type;
|
|
typedef unsigned long _Tp;
|
|
|
|
size_type max_size(void) {
|
|
return (size_type)~0 / sizeof(_Tp);
|
|
}
|
|
|
|
// CIR: cir.func @max_size()
|
|
// CIR: %0 = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"] {alignment = 8 : i64}
|
|
// CIR: %1 = cir.const #cir.int<0> : !s32i
|
|
// CIR: %2 = cir.unary(not, %1) : !s32i, !s32i
|
|
// CIR: %3 = cir.cast(integral, %2 : !s32i), !u64i
|
|
// CIR: %4 = cir.const #cir.int<8> : !u64i
|
|
// CIR: %5 = cir.binop(div, %3, %4) : !u64i
|
|
|
|
// LLVM: define i64 @max_size()
|
|
// LLVM: store i64 2305843009213693951, ptr
|
|
|
|
// OGCG: define{{.*}} i64 @max_size()
|
|
// OGCG: ret i64 2305843009213693951
|
|
// CHECK: cir.store{{.*}} %5, %0 : !u64i, !cir.ptr<!u64i>
|
|
// CHECK: %6 = cir.load{{.*}} %0 : !cir.ptr<!u64i>, !u64i
|
|
// CHECK: cir.return %6 : !u64i
|
|
// CHECK: }
|
|
|
|
void test_char_literal() {
|
|
char c;
|
|
c = 'X';
|
|
}
|
|
|
|
// CIR: cir.func @test_char_literal
|
|
// CIR: cir.const #cir.int<88>
|
|
|
|
// LLVM: define void @test_char_literal()
|
|
// LLVM: store i8 88, ptr %{{.*}}, align 1
|
|
|
|
// OGCG: define{{.*}} void @test_char_literal()
|
|
// OGCG: store i8 88, ptr %{{.*}}, align 1
|