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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
| ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-atomics | FileCheck %s
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+atomics | FileCheck %s
; Test that globals assemble as expected.
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
; CHECK-NOT: llvm.used
; CHECK-NOT: llvm.metadata
@llvm.used = appending global [1 x i32*] [i32* @g], section "llvm.metadata"
; CHECK: foo:
; CHECK: i32.const $push0=, 0{{$}}
; CHECK-NEXT: i32.load $push1=, answer($pop0){{$}}
; CHECK-NEXT: return $pop1{{$}}
define i32 @foo() {
%a = load i32, i32* @answer
ret i32 %a
}
; CHECK-LABEL: call_memcpy:
; CHECK-NEXT: .functype call_memcpy (i32, i32, i32) -> (i32){{$}}
; CHECK-NEXT: i32.call $push0=, memcpy, $0, $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1)
define i8* @call_memcpy(i8* %p, i8* nocapture readonly %q, i32 %n) {
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false)
ret i8* %p
}
; CHECK: .type .Lg,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: .Lg:
; CHECK-NEXT: .int32 1337{{$}}
; CHECK-NEXT: .size .Lg, 4{{$}}
@g = private global i32 1337
; CHECK-LABEL: ud:
; CHECK-NEXT: .skip 4{{$}}
; CHECK-NEXT: .size ud, 4{{$}}
@ud = internal global i32 undef
; CHECK: .type nil,@object
; CHECK: .p2align 2
; CHECK: nil:
; CHECK: .int32 0
; CHECK: .size nil, 4
@nil = internal global i32 zeroinitializer
; CHECK: .type z,@object
; CHECK: .p2align 2
; CHECK: z:
; CHECK: .int32 0
; CHECK: .size z, 4
@z = internal global i32 0
; CHECK: .type one,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: one:
; CHECK-NEXT: .int32 1{{$}}
; CHECK-NEXT: .size one, 4{{$}}
@one = internal global i32 1
; CHECK: .type answer,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: answer:
; CHECK-NEXT: .int32 42{{$}}
; CHECK-NEXT: .size answer, 4{{$}}
@answer = internal global i32 42
; CHECK: .type u32max,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: u32max:
; CHECK-NEXT: .int32 4294967295{{$}}
; CHECK-NEXT: .size u32max, 4{{$}}
@u32max = internal global i32 -1
; CHECK: .type ud64,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: ud64:
; CHECK-NEXT: .skip 8{{$}}
; CHECK-NEXT: .size ud64, 8{{$}}
@ud64 = internal global i64 undef
; CHECK: .type nil64,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: nil64:
; CHECK-NEXT: .int64 0{{$}}
; CHECK-NEXT: .size nil64, 8{{$}}
@nil64 = internal global i64 zeroinitializer
; CHECK: .type z64,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: z64:
; CHECK-NEXT: .int64 0{{$}}
; CHECK-NEXT: .size z64, 8{{$}}
@z64 = internal global i64 0
; CHECK: .type twoP32,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: twoP32:
; CHECK-NEXT: .int64 4294967296{{$}}
; CHECK-NEXT: .size twoP32, 8{{$}}
@twoP32 = internal global i64 4294967296
; CHECK: .type u64max,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: u64max:
; CHECK-NEXT: .int64 -1{{$}}
; CHECK-NEXT: .size u64max, 8{{$}}
@u64max = internal global i64 -1
; CHECK: .type f32ud,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: f32ud:
; CHECK-NEXT: .skip 4{{$}}
; CHECK-NEXT: .size f32ud, 4{{$}}
@f32ud = internal global float undef
; CHECK: .type f32nil,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: f32nil:
; CHECK-NEXT: .int32 0{{$}}
; CHECK-NEXT: .size f32nil, 4{{$}}
@f32nil = internal global float zeroinitializer
; CHECK: .type f32z,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: f32z:
; CHECK-NEXT: .int32 0{{$}}
; CHECK-NEXT: .size f32z, 4{{$}}
@f32z = internal global float 0.0
; CHECK: .type f32nz,@object
; CHECK: .p2align 2{{$}}
; CHECK: f32nz:
; CHECK: .int32 2147483648{{$}}
; CHECK: .size f32nz, 4{{$}}
@f32nz = internal global float -0.0
; CHECK: .type f32two,@object
; CHECK: .p2align 2{{$}}
; CHECK-NEXT: f32two:
; CHECK-NEXT: .int32 1073741824{{$}}
; CHECK-NEXT: .size f32two, 4{{$}}
@f32two = internal global float 2.0
; CHECK: .type f64ud,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: f64ud:
; CHECK-NEXT: .skip 8{{$}}
; CHECK-NEXT: .size f64ud, 8{{$}}
@f64ud = internal global double undef
; CHECK: .type f64nil,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: f64nil:
; CHECK-NEXT: .int64 0{{$}}
; CHECK-NEXT: .size f64nil, 8{{$}}
@f64nil = internal global double zeroinitializer
; CHECK: .type f64z,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: f64z:
; CHECK-NEXT: .int64 0{{$}}
; CHECK-NEXT: .size f64z, 8{{$}}
@f64z = internal global double 0.0
; CHECK: .type f64nz,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: f64nz:
; CHECK-NEXT: .int64 -9223372036854775808{{$}}
; CHECK-NEXT: .size f64nz, 8{{$}}
@f64nz = internal global double -0.0
; CHECK: .type f64two,@object
; CHECK: .p2align 3{{$}}
; CHECK-NEXT: f64two:
; CHECK-NEXT: .int64 4611686018427387904{{$}}
; CHECK-NEXT: .size f64two, 8{{$}}
@f64two = internal global double 2.0
; Indexing into a global array produces a relocation.
; CHECK: .type arr,@object
; CHECK: .type ptr,@object
; CHECK: ptr:
; CHECK-NEXT: .int32 arr+80
; CHECK-NEXT: .size ptr, 4
@arr = global [128 x i32] zeroinitializer, align 16
@ptr = global i32* getelementptr inbounds ([128 x i32], [128 x i32]* @arr, i32 0, i32 20), align 4
; Constant global.
; CHECK: .type rom,@object{{$}}
; CHECK: .section .rodata.rom,""
; CHECK: .globl rom{{$}}
; CHECK: .p2align 4{{$}}
; CHECK: rom:
; CHECK: .skip 512{{$}}
; CHECK: .size rom, 512{{$}}
@rom = constant [128 x i32] zeroinitializer, align 16
; CHECK: .type array,@object
; CHECK: array:
; CHECK-NEXT: .skip 8
; CHECK-NEXT: .size array, 8
; CHECK: .type pointer_to_array,@object
; CHECK-NEXT: .section .rodata.pointer_to_array,""
; CHECK-NEXT: .globl pointer_to_array
; CHECK-NEXT: .p2align 2
; CHECK-NEXT: pointer_to_array:
; CHECK-NEXT: .int32 array+4
; CHECK-NEXT: .size pointer_to_array, 4
@array = internal constant [8 x i8] zeroinitializer, align 1
@pointer_to_array = constant i8* getelementptr inbounds ([8 x i8], [8 x i8]* @array, i32 0, i32 4), align 4
; Handle external objects with opaque type.
%struct.ASTRUCT = type opaque
@g_struct = external global %struct.ASTRUCT, align 1
define i32 @address_of_opaque() {
ret i32 ptrtoint (%struct.ASTRUCT* @g_struct to i32)
}
|