This commit implements the entirety of the now-accepted [N3017 - Preprocessor Embed](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm) and its sister C++ paper [p1967](https://wg21.link/p1967). It implements everything in the specification, and includes an implementation that drastically improves the time it takes to embed data in specific scenarios (the initialization of character type arrays). The mechanisms used to do this are used under the "as-if" rule, and in general when the system cannot detect it is initializing an array object in a variable declaration, will generate EmbedExpr AST node which will be expanded by AST consumers (CodeGen or constant expression evaluators) or expand embed directive as a comma expression. --------- Co-authored-by: Aaron Ballman <aaron@aaronballman.com> Co-authored-by: cor3ntin <corentinjabot@gmail.com> Co-authored-by: H. Vetinari <h.vetinari@gmx.com> Co-authored-by: Podchishchaeva, Mariya <mariya.podchishchaeva@intel.com>
85 lines
3.2 KiB
C++
85 lines
3.2 KiB
C++
// RUN: %clang_cc1 %s -triple x86_64 --embed-dir=%S/Inputs -emit-llvm -o - | FileCheck %s
|
|
|
|
// CHECK: @__const._Z3fooi.ca = private unnamed_addr constant [3 x i32] [i32 0, i32 106, i32 107], align 4
|
|
// CHECK: @__const._Z3fooi.sc = private unnamed_addr constant %struct.S1 { i32 106, i32 107, i32 0 }, align 4
|
|
// CHECK: @__const._Z3fooi.t = private unnamed_addr constant [3 x %struct.T] [%struct.T { [2 x i32] [i32 48, i32 49], %struct.S1 { i32 50, i32 51, i32 52 } }, %struct.T { [2 x i32] [i32 53, i32 54], %struct.S1 { i32 55, i32 56, i32 57 } }, %struct.T { [2 x i32] [i32 10, i32 0], %struct.S1 zeroinitializer }], align 16
|
|
void foo(int a) {
|
|
// CHECK: %a.addr = alloca i32, align 4
|
|
// CHECK: store i32 %a, ptr %a.addr, align 4
|
|
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %ca, ptr align 4 @__const._Z3fooi.ca, i64 12, i1 false)
|
|
int ca[] = {
|
|
0
|
|
#embed <jk.txt> prefix(,)
|
|
};
|
|
|
|
// CHECK: %arrayinit.element = getelementptr inbounds i32, ptr %notca, i64 1
|
|
// CHECK: store i8 106, ptr %arrayinit.element, align 4
|
|
// CHECK: %arrayinit.element1 = getelementptr inbounds i32, ptr %notca, i64 2
|
|
// CHECK: store i8 107, ptr %arrayinit.element1, align 4
|
|
int notca[] = {
|
|
a
|
|
#embed <jk.txt> prefix(,)
|
|
};
|
|
|
|
struct S1 {
|
|
int x, y, z;
|
|
};
|
|
|
|
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %sc, ptr align 4 @__const._Z3fooi.sc, i64 12, i1 false)
|
|
S1 sc = {
|
|
#embed <jk.txt> suffix(,)
|
|
0
|
|
};
|
|
|
|
// CHECK: %x = getelementptr inbounds %struct.S1, ptr %s, i32 0, i32 0
|
|
// CHECK: store i32 106, ptr %x, align 4
|
|
// CHECK: %y = getelementptr inbounds %struct.S1, ptr %s, i32 0, i32 1
|
|
// CHECK: store i32 107, ptr %y, align 4
|
|
// CHECK: %z = getelementptr inbounds %struct.S1, ptr %s, i32 0, i32 2
|
|
// CHECK: %1 = load i32, ptr %a.addr, align 4
|
|
S1 s = {
|
|
#embed <jk.txt> suffix(,)
|
|
a
|
|
};
|
|
|
|
// CHECK: store i32 107, ptr %b, align 4
|
|
int b =
|
|
#embed<jk.txt>
|
|
;
|
|
|
|
|
|
struct T {
|
|
int arr[2];
|
|
struct S1 s;
|
|
};
|
|
|
|
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %t, ptr align 16 @__const._Z3fooi.t, i64 60, i1 false)
|
|
constexpr struct T t[] = {
|
|
#embed <numbers.txt>
|
|
};
|
|
|
|
// CHECK: %arr = getelementptr inbounds %struct.T, ptr %tnonc, i32 0, i32 0
|
|
// CHECK: %2 = load i32, ptr %a.addr, align 4
|
|
// CHECK: store i32 %2, ptr %arr, align 4
|
|
// CHECK: %arrayinit.element2 = getelementptr inbounds i32, ptr %arr, i64 1
|
|
// CHECK: store i32 300, ptr %arrayinit.element2, align 4
|
|
// CHECK: %s3 = getelementptr inbounds %struct.T, ptr %tnonc, i32 0, i32 1
|
|
// CHECK: %x4 = getelementptr inbounds %struct.S1, ptr %s3, i32 0, i32 0
|
|
// CHECK: store i32 1, ptr %x4, align 4
|
|
// CHECK: %y5 = getelementptr inbounds %struct.S1, ptr %s3, i32 0, i32 1
|
|
// CHECK: store i32 2, ptr %y5, align 4
|
|
// CHECK: %z6 = getelementptr inbounds %struct.S1, ptr %s3, i32 0, i32 2
|
|
// CHECK: store i32 3, ptr %z6, align 4
|
|
// CHECK: %arrayinit.element7 = getelementptr inbounds %struct.T, ptr %tnonc, i64 1
|
|
// CHECK: call void @llvm.memset.p0.i64(ptr align 4 %arrayinit.element7, i8 0, i64 20, i1 false)
|
|
// CHECK: %arr8 = getelementptr inbounds %struct.T, ptr %arrayinit.element7, i32 0, i32 0
|
|
// CHECK: store i8 106, ptr %arr8, align 4
|
|
// CHECK: %arrayinit.element9 = getelementptr inbounds i32, ptr %arr8, i64 1
|
|
// CHECK: store i8 107, ptr %arrayinit.element9, align 4
|
|
struct T tnonc[] = {
|
|
a, 300, 1, 2, 3
|
|
#embed <jk.txt> prefix(,)
|
|
};
|
|
|
|
}
|