blob: a1d813cc43dfd645ed6659bfbdbb001deeb555cd [file] [edit]
// RUN: %clang_cc1 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s
// embed-data.txt contains "0123456789" (48 ... 57) without a trailing newline.
struct S {
int a, b;
};
struct A {
A(char);
};
// CHECK-LABEL: define {{.*}}void @_Z2f1i(
// CHECK: icmp ult i64 %{{.*}}, 4
// CHECK: %[[A1:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 48, ptr %[[A1]]
// CHECK: %[[F1E1:.*]] = getelementptr inbounds i32, ptr %[[A1]], i64 1
// CHECK: store i32 49, ptr %[[F1E1]]
// CHECK: %[[F1E2:.*]] = getelementptr inbounds i32, ptr %[[F1E1]], i64 1
// CHECK: store i32 50, ptr %[[F1E2]]
// CHECK: %[[F1E3:.*]] = getelementptr inbounds i32, ptr %[[F1E2]], i64 1
// CHECK: store i32 51, ptr %[[F1E3]]
// CHECK: %[[F1REST:.*]] = sub i64 %{{.*}}, 16
// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F1REST]], i1 false)
void f1(int x) {
int *p = new int[x]{
#embed <embed-data.txt> limit(4)
};
}
// CHECK-LABEL: define {{.*}}void @_Z2f2i(
// CHECK: icmp ult i64 %{{.*}}, 4
// CHECK: %[[A2:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 500, ptr %[[A2]]
// CHECK: %[[F2E1:.*]] = getelementptr inbounds i32, ptr %[[A2]], i64 1
// CHECK: store i32 48, ptr %[[F2E1]]
// CHECK: %[[F2E2:.*]] = getelementptr inbounds i32, ptr %[[F2E1]], i64 1
// CHECK: store i32 49, ptr %[[F2E2]]
// CHECK: %[[F2E3:.*]] = getelementptr inbounds i32, ptr %[[F2E2]], i64 1
// CHECK: store i32 600, ptr %[[F2E3]]
// CHECK: %[[F2REST:.*]] = sub i64 %{{.*}}, 16
// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F2REST]], i1 false)
void f2(int x) {
int *p = new int[x]{
500,
#embed <embed-data.txt> limit(2) suffix(, 600)
};
}
// char arrays go through the string literal initialization path.
// CHECK-LABEL: define {{.*}}void @_Z2f3i(
// CHECK: icmp ult i64 %{{.*}}, 4
// CHECK: %[[A3:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[A3]], ptr align 1 @{{.*}}, i64 4, i1 false)
// CHECK: %[[F3END:.*]] = getelementptr inbounds i8, ptr %[[A3]], i64 4
// CHECK: %[[F3REST:.*]] = sub i64 %{{.*}}, 4
// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %[[F3END]], i8 0, i64 %[[F3REST]], i1 false)
void f3(int x) {
char *p = new char[x]{
#embed <embed-data.txt> limit(4)
};
}
// CHECK-LABEL: define {{.*}}void @_Z2f4i(
// CHECK: icmp ult i64 %{{.*}}, 2
// CHECK: %[[A4:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 900, ptr %[[A4]]
// CHECK: %[[F4E1:.*]] = getelementptr inbounds i32, ptr %[[A4]], i64 1
// CHECK: store i32 48, ptr %[[F4E1]]
// CHECK: %[[F4REST:.*]] = sub i64 %{{.*}}, 8
// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F4REST]], i1 false)
void f4(int x) {
int *p = new int[x]{
#embed <embed-data.txt> limit(1) prefix(900, )
};
}
// Constant size fully covered by the embed data: no trailing fill.
// CHECK-LABEL: define {{.*}}void @_Z2f5v(
// CHECK: %[[A5:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 48, ptr %[[A5]]
// CHECK: %[[F5E1:.*]] = getelementptr inbounds i32, ptr %[[A5]], i64 1
// CHECK: store i32 49, ptr %[[F5E1]]
// CHECK: %[[F5E2:.*]] = getelementptr inbounds i32, ptr %[[F5E1]], i64 1
// CHECK: store i32 50, ptr %[[F5E2]]
// CHECK: %[[F5E3:.*]] = getelementptr inbounds i32, ptr %[[F5E2]], i64 1
// CHECK: store i32 51, ptr %[[F5E3]]
// CHECK-NOT: call void @llvm.memset
// CHECK: ret void
void f5() {
int *p = new int[4]{
#embed <embed-data.txt> limit(4)
};
}
// Sema wraps the EmbedExpr in an implicit conversion to the element type.
// CHECK-LABEL: define {{.*}}void @_Z2f6i(
// CHECK: icmp ult i64 %{{.*}}, 4
// CHECK: %[[A6:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i64 48, ptr %[[A6]]
// CHECK: %[[F6E1:.*]] = getelementptr inbounds i64, ptr %[[A6]], i64 1
// CHECK: store i64 49, ptr %[[F6E1]]
// CHECK: %[[F6E2:.*]] = getelementptr inbounds i64, ptr %[[F6E1]], i64 1
// CHECK: store i64 50, ptr %[[F6E2]]
// CHECK: %[[F6E3:.*]] = getelementptr inbounds i64, ptr %[[F6E2]], i64 1
// CHECK: store i64 51, ptr %[[F6E3]]
// CHECK: %[[F6REST:.*]] = sub i64 %{{.*}}, 32
// CHECK: call void @llvm.memset.p0.i64(ptr align 8 %{{.*}}, i8 0, i64 %[[F6REST]], i1 false)
void f6(int x) {
long long *p = new long long[x]{
#embed <embed-data.txt> limit(4)
};
}
// CHECK-LABEL: define {{.*}}void @_Z2f7i(
// CHECK: icmp ult i64 %{{.*}}, 2
// CHECK: call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 48, ptr
// CHECK: store i32 49, ptr
// CHECK: store i32 50, ptr
// CHECK: store i32 51, ptr
// CHECK: %[[F7REST:.*]] = sub i64 %{{.*}}, 16
// CHECK: call void @llvm.memset.p0.i64(ptr align {{[0-9]+}} %{{.*}}, i8 0, i64 %[[F7REST]], i1 false)
void f7(int x) {
int (*p)[2] = new int[x][2]{
#embed <embed-data.txt> limit(4)
};
}
// CHECK-LABEL: define {{.*}}void @_Z2f8i(
// CHECK: icmp ult i64 %{{.*}}, 2
// CHECK: call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 48, ptr
// CHECK: store i32 49, ptr
// CHECK: store i32 50, ptr
// CHECK: store i32 51, ptr
// CHECK: %[[F8REST:.*]] = sub i64 %{{.*}}, 16
// CHECK: call void @llvm.memset.p0.i64(ptr align {{[0-9]+}} %{{.*}}, i8 0, i64 %[[F8REST]], i1 false)
void f8(int x) {
S *p = new S[x]{
#embed <embed-data.txt> limit(4)
};
}
// CHECK-LABEL: define {{.*}}void @_Z2f9i(
// CHECK: icmp ult i64 %{{.*}}, 2
// CHECK: call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store i32 48, ptr
// CHECK: store i32 49, ptr
// CHECK: store i32 50, ptr
// CHECK: store i32 51, ptr
// CHECK: store i32 52, ptr
// CHECK: store i32 53, ptr
// CHECK: store i32 54, ptr
// CHECK: store i32 55, ptr
// CHECK: %[[F9REST:.*]] = sub i64 %{{.*}}, 32
// CHECK: call void @llvm.memset.p0.i64(ptr align {{[0-9]+}} %{{.*}}, i8 0, i64 %[[F9REST]], i1 false)
void f9(int x) {
S (*p)[2] = new S[x][2]{
#embed <embed-data.txt> limit(8)
};
}
// CHECK-LABEL: define {{.*}}void @_Z3f10v(
// CHECK: %[[A10:.*]] = call {{.*}}ptr @_Znam(i64 noundef 16)
// CHECK: store i32 48, ptr %[[A10]]
// CHECK: %[[F10E1:.*]] = getelementptr inbounds i32, ptr %[[A10]], i64 1
// CHECK: store i32 49, ptr %[[F10E1]]
// CHECK: %[[F10E2:.*]] = getelementptr inbounds i32, ptr %[[F10E1]], i64 1
// CHECK: store i32 50, ptr %[[F10E2]]
// CHECK: %[[F10E3:.*]] = getelementptr inbounds i32, ptr %[[F10E2]], i64 1
// CHECK: store i32 51, ptr %[[F10E3]]
// CHECK-NOT: call void @llvm.memset
// CHECK: ret void
void f10() {
int *p = new int[]{
#embed <embed-data.txt> limit(4)
};
}
// CHECK-LABEL: define {{.*}}void @_Z3f11i(
// CHECK: icmp ult i64 %{{.*}}, 4
// CHECK: %[[A11:.*]] = call {{.*}}ptr @_Znam(i64 {{.*}})
// CHECK: store float 4.800000e+01, ptr %[[A11]]
// CHECK: %[[F11E1:.*]] = getelementptr inbounds float, ptr %[[A11]], i64 1
// CHECK: store float 4.900000e+01, ptr %[[F11E1]]
// CHECK: %[[F11E2:.*]] = getelementptr inbounds float, ptr %[[F11E1]], i64 1
// CHECK: store float 5.000000e+01, ptr %[[F11E2]]
// CHECK: %[[F11E3:.*]] = getelementptr inbounds float, ptr %[[F11E2]], i64 1
// CHECK: store float 5.100000e+01, ptr %[[F11E3]]
// CHECK: %[[F11REST:.*]] = sub i64 %{{.*}}, 16
// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %{{.*}}, i8 0, i64 %[[F11REST]], i1 false)
void f11(int x) {
float *p = new float[x]{
#embed <embed-data.txt> limit(4)
};
}
// Class elements are constructed from one data element each.
// CHECK-LABEL: define {{.*}}void @_Z3f12v(
// CHECK: %[[A12:.*]] = call {{.*}}ptr @_Znam(i64 noundef 2)
// CHECK: call void @_ZN1AC1Ec(ptr {{.*}}%[[A12]], i8 noundef signext 48)
// CHECK: %[[F12E1:.*]] = getelementptr inbounds %struct.A, ptr %[[A12]], i64 1
// CHECK: call void @_ZN1AC1Ec(ptr {{.*}}%[[F12E1]], i8 noundef signext 49)
void f12() {
A *p = new A[]{
#embed <embed-data.txt> limit(2)
};
}
// Complex elements are not integer or floating-point type, so Sema slices
// the embed into single-element EmbedExprs wrapped in an int-to-complex
// conversion, one per element.
// CHECK-LABEL: define {{.*}}void @_Z3f13v(
// CHECK: call {{.*}}ptr @_Znam(i64 noundef 32)
// CHECK: store double 4.800000e+01, ptr
// CHECK: store double 0.000000e+00, ptr
// CHECK: store double 4.900000e+01, ptr
// CHECK: store double 0.000000e+00, ptr
void f13() {
_Complex double *p = new _Complex double[]{
#embed <embed-data.txt> limit(2)
};
}
// CHECK-LABEL: define {{.*}}void @_Z3f14v(
// CHECK: %[[A14:.*]] = call {{.*}}ptr @_Znam(i64 noundef 16)
// CHECK: store double 4.800000e+01, ptr
// CHECK: store double 0.000000e+00, ptr
void f14() {
_Complex double *p = new _Complex double[]{
#embed <embed-data.txt> limit(1)
};
}