1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
; RUN: opt -flatten-globals %s -S | FileCheck %s
; RUN: opt -flatten-globals %s -S | FileCheck %s -check-prefix=CLEANED
target datalayout = "p:32:32:32"
; Check simple cases
@var_i32 = global i32 258
; CHECK: @var_i32 = global [4 x i8] c"\02\01\00\00"
; CHECK-CLEANED-NOT: global i32 258
@external_var = external global i32
; CHECK: @external_var = external global [4 x i8]
@zero_init = global i32 0
; CHECK: @zero_init = global [4 x i8] zeroinitializer
@big_zero_init = global [2000 x i8] zeroinitializer
; CHECK: @big_zero_init = global [2000 x i8] zeroinitializer
@null_ptr = global i32* null
; CHECK: @null_ptr = global [4 x i8] zeroinitializer
@undef_value = global i32 undef
; CHECK: @undef_value = global [4 x i8] zeroinitializer
; Check various data types
@var_i1 = global i8 1
; CHECK: @var_i1 = global [1 x i8] c"\01"
@var_i8 = global i8 65
; CHECK: @var_i8 = global [1 x i8] c"A"
@var_i16 = global i16 258
; CHECK: @var_i16 = global [2 x i8] c"\02\01"
@var_i64 = global i64 72623859790382856
; CHECK: @var_i64 = global [8 x i8] c"\08\07\06\05\04\03\02\01"
@var_i128 = global i128 1339673755198158349044581307228491536
; CHECK: @var_i128 = global [16 x i8] c"\10\0F\0E\0D\0C\0B\0A\09\08\07\06\05\04\03\02\01"
; Check that padding bits come out as zero.
@var_i121 = global i121 1339673755198158349044581307228491536
; CHECK: @var_i121 = global [16 x i8] c"\10\0F\0E\0D\0C\0B\0A\09\08\07\06\05\04\03\02\01"
@var_double = global double 123.456
; CHECK: @var_double = global [8 x i8] c"w\BE\9F\1A/\DD^@"
@var_float = global float 123.0
; CHECK: @var_float = global [4 x i8] c"\00\00\F6B"
; Check aggregates
@padded_struct = global { i8, i8, i32 } { i8 65, i8 66, i32 258 }
; CHECK: @padded_struct = global [8 x i8] c"AB\00\00\02\01\00\00"
@packed_struct = global <{ i8, i8, i32 }> <{ i8 67, i8 68, i32 258 }>
; CHECK: @packed_struct = global [6 x i8] c"CD\02\01\00\00"
@i8_array = global [6 x i8] c"Hello\00"
; CHECK: @i8_array = global [6 x i8] c"Hello\00"
@i16_array = global [3 x i16] [ i16 1, i16 2, i16 3 ]
; CHECK: @i16_array = global [6 x i8] c"\01\00\02\00\03\00"
%s = type { i8, i8 }
@struct_array = global [2 x %s] [%s { i8 1, i8 2 }, %s { i8 3, i8 4 }]
; CHECK: @struct_array = global [4 x i8] c"\01\02\03\04"
@vector = global <2 x i32> <i32 259, i32 520>
; CHECK: @vector = global [8 x i8] c"\03\01\00\00\08\02\00\00"
; Check that various attributes are preserved
@constant_var = constant i32 259
; CHECK: @constant_var = constant [4 x i8] c"\03\01\00\00"
@weak_external_var = extern_weak global i32
; CHECK: @weak_external_var = extern_weak global [4 x i8]
@tls_var = external thread_local global i32
; CHECK: @tls_var = external thread_local global [4 x i8]
@aligned_var = global i32 260, align 8
; CHECK: @aligned_var = global [4 x i8] c"\04\01\00\00", align 8
; Check alignment handling
@implicit_alignment_i32 = global i32 zeroinitializer
; CHECK: @implicit_alignment_i32 = global [4 x i8] zeroinitializer, align 4
@implicit_alignment_double = global double zeroinitializer
; CHECK: @implicit_alignment_double = global [8 x i8] zeroinitializer, align 8
; FlattenGlobals is not allowed to increase the alignment of the
; variable when an explicit section is specified (although PNaCl does
; not support this attribute).
@lower_alignment_section = global i32 0, section "mysection", align 1
; CHECK: @lower_alignment_section = global [4 x i8] zeroinitializer, section "mysection", align 1
; FlattenGlobals could increase the alignment when no section is
; specified, but it does not.
@lower_alignment = global i32 0, align 1
; CHECK: @lower_alignment = global [4 x i8] zeroinitializer, align 1
; Check handling of global references
@var1 = external global i32
@var2 = external global i8
%ptrs1 = type { i32*, i8*, i32 }
@ptrs1 = global %ptrs1 { i32* @var1, i8* null, i32 259 }
; CHECK: @ptrs1 = global <{ i32, [8 x i8] }> <{ i32 ptrtoint ([4 x i8]* @var1 to i32), [8 x i8] c"\00\00\00\00\03\01\00\00" }>
%ptrs2 = type { i32, i32*, i8* }
@ptrs2 = global %ptrs2 { i32 259, i32* @var1, i8* @var2 }
; CHECK: @ptrs2 = global <{ [4 x i8], i32, i32 }> <{ [4 x i8] c"\03\01\00\00", i32 ptrtoint ([4 x i8]* @var1 to i32), i32 ptrtoint ([1 x i8]* @var2 to i32) }>
%ptrs3 = type { i32*, [3 x i8], i8* }
@ptrs3 = global %ptrs3 { i32* @var1, [3 x i8] c"foo", i8* @var2 }
; CHECK: @ptrs3 = global <{ i32, [4 x i8], i32 }> <{ i32 ptrtoint ([4 x i8]* @var1 to i32), [4 x i8] c"foo\00", i32 ptrtoint ([1 x i8]* @var2 to i32) }>
@ptr = global i32* @var1
; CHECK: @ptr = global i32 ptrtoint ([4 x i8]* @var1 to i32)
@func_ptr = global i32* ()* @get_address
; CHECK: @func_ptr = global i32 ptrtoint (i32* ()* @get_address to i32)
@block_addr = global i8* blockaddress(@func_with_block, %label)
; CHECK: @block_addr = global i32 ptrtoint (i8* blockaddress(@func_with_block, %label) to i32)
@vector_reloc = global <2 x i32*> <i32* @var1, i32* @var1>
; CHECK: global <{ i32, i32 }> <{ i32 ptrtoint ([4 x i8]* @var1 to i32), i32 ptrtoint ([4 x i8]* @var1 to i32) }>
; Global references with addends
@reloc_addend = global i32* getelementptr (%ptrs1* @ptrs1, i32 0, i32 2)
; CHECK: @reloc_addend = global i32 add (i32 ptrtoint (<{ i32, [8 x i8] }>* @ptrs1 to i32), i32 8)
@negative_addend = global %ptrs1* getelementptr (%ptrs1* @ptrs1, i32 -1)
; CHECK: @negative_addend = global i32 add (i32 ptrtoint (<{ i32, [8 x i8] }>* @ptrs1 to i32), i32 -12)
@const_ptr = global i32* getelementptr (%ptrs1* null, i32 0, i32 2)
; CHECK: @const_ptr = global [4 x i8] c"\08\00\00\00"
@int_to_ptr = global i32* inttoptr (i16 260 to i32*)
; CHECK: @int_to_ptr = global [4 x i8] c"\04\01\00\00"
; Clang allows "(uintptr_t) &var" as a global initializer, so we
; handle this case.
@ptr_to_int = global i32 ptrtoint (i8* @var2 to i32)
; CHECK: @ptr_to_int = global i32 ptrtoint ([1 x i8]* @var2 to i32)
; This is handled via Constant folding. The getelementptr is
; converted to an undef when it is created, so the pass does not see a
; getelementptr here.
@undef_gep = global i32* getelementptr (%ptrs1* undef, i32 0, i32 2)
; CHECK: @undef_gep = global [4 x i8] zeroinitializer
; Adding an offset to a function address isn't useful, but check that
; the pass handles it anyway.
@func_addend = global i8* getelementptr (
i8* bitcast (void ()* @func_with_block to i8*), i32 123)
; CHECK: @func_addend = global i32 add (i32 ptrtoint (void ()* @func_with_block to i32), i32 123)
; Similarly, adding an offset to a label address isn't useful, but
; check it anyway.
@block_addend = global i8* getelementptr (
i8* blockaddress(@func_with_block, %label), i32 100)
; CHECK: @block_addend = global i32 add (i32 ptrtoint (i8* blockaddress(@func_with_block, %label) to i32), i32 100)
; Special cases
; Leave vars with "appending" linkage alone.
@appending = appending global [1 x i32*] [i32* @var1]
; CHECK: @appending = appending global [1 x i32*] [i32* bitcast ([4 x i8]* @var1 to i32*)]
define i32* @get_address() {
ret i32* @var_i32
}
; CHECK: define i32* @get_address() {
; CHECK-NEXT: ret i32* bitcast ([4 x i8]* @var_i32 to i32*)
define void @func_with_block() {
br label %label
label:
ret void
}
|