xref: /llvm-project/llvm/test/CodeGen/WebAssembly/global.ll (revision ff9af4c43ad71eeba2cabe99609cfaa0fd54c1d0)
1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=-atomics | FileCheck %s
2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+atomics | FileCheck %s
3
4; Test that globals assemble as expected.
5
6target triple = "wasm32-unknown-unknown"
7
8; CHECK-NOT: llvm.used
9; CHECK-NOT: llvm.metadata
10@llvm.used = appending global [1 x ptr] [ptr @g], section "llvm.metadata"
11
12; CHECK: foo:
13; CHECK: i32.const $push0=, 0{{$}}
14; CHECK-NEXT: i32.load $push1=, answer($pop0){{$}}
15; CHECK-NEXT: return $pop1{{$}}
16define i32 @foo() {
17  %a = load i32, ptr @answer
18  ret i32 %a
19}
20
21; CHECK-LABEL: call_memcpy:
22; CHECK-NEXT: .functype call_memcpy (i32, i32, i32) -> (i32){{$}}
23; CHECK-NEXT: call            $push0=, memcpy, $0, $1, $2{{$}}
24; CHECK-NEXT: return          $pop0{{$}}
25declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture readonly, i32, i1)
26define ptr @call_memcpy(ptr %p, ptr nocapture readonly %q, i32 %n) {
27  tail call void @llvm.memcpy.p0.p0.i32(ptr %p, ptr %q, i32 %n, i1 false)
28  ret ptr %p
29}
30
31; CHECK: .type   .Lg,@object
32; CHECK: .p2align  2, 0x0{{$}}
33; CHECK-NEXT: .Lg:
34; CHECK-NEXT: .int32 1337{{$}}
35; CHECK-NEXT: .size .Lg, 4{{$}}
36@g = private global i32 1337
37
38; CHECK-LABEL: ud:
39; CHECK-NEXT: .skip 4{{$}}
40; CHECK-NEXT: .size ud, 4{{$}}
41@ud = internal global i32 undef
42
43; CHECK: .type nil,@object
44; CHECK: .p2align 2, 0x0
45; CHECK: nil:
46; CHECK: .int32 0
47; CHECK: .size nil, 4
48@nil = internal global i32 zeroinitializer
49
50; CHECK: .type z,@object
51; CHECK: .p2align 2, 0x0
52; CHECK: z:
53; CHECK: .int32 0
54; CHECK: .size z, 4
55@z = internal global i32 0
56
57; CHECK: .type one,@object
58; CHECK: .p2align 2, 0x0{{$}}
59; CHECK-NEXT: one:
60; CHECK-NEXT: .int32 1{{$}}
61; CHECK-NEXT: .size one, 4{{$}}
62@one = internal global i32 1
63
64; CHECK: .type answer,@object
65; CHECK: .p2align 2, 0x0{{$}}
66; CHECK-NEXT: answer:
67; CHECK-NEXT: .int32 42{{$}}
68; CHECK-NEXT: .size answer, 4{{$}}
69@answer = internal global i32 42
70
71; CHECK: .type u32max,@object
72; CHECK: .p2align 2, 0x0{{$}}
73; CHECK-NEXT: u32max:
74; CHECK-NEXT: .int32 4294967295{{$}}
75; CHECK-NEXT: .size u32max, 4{{$}}
76@u32max = internal global i32 -1
77
78; CHECK: .type ud64,@object
79; CHECK: .p2align 3, 0x0{{$}}
80; CHECK-NEXT: ud64:
81; CHECK-NEXT: .skip 8{{$}}
82; CHECK-NEXT: .size ud64, 8{{$}}
83@ud64 = internal global i64 undef
84
85; CHECK: .type nil64,@object
86; CHECK: .p2align 3, 0x0{{$}}
87; CHECK-NEXT: nil64:
88; CHECK-NEXT: .int64 0{{$}}
89; CHECK-NEXT: .size nil64, 8{{$}}
90@nil64 = internal global i64 zeroinitializer
91
92; CHECK: .type z64,@object
93; CHECK: .p2align 3, 0x0{{$}}
94; CHECK-NEXT: z64:
95; CHECK-NEXT: .int64 0{{$}}
96; CHECK-NEXT: .size z64, 8{{$}}
97@z64 = internal global i64 0
98
99; CHECK: .type twoP32,@object
100; CHECK: .p2align 3, 0x0{{$}}
101; CHECK-NEXT: twoP32:
102; CHECK-NEXT: .int64 4294967296{{$}}
103; CHECK-NEXT: .size twoP32, 8{{$}}
104@twoP32 = internal global i64 4294967296
105
106; CHECK: .type u64max,@object
107; CHECK: .p2align 3, 0x0{{$}}
108; CHECK-NEXT: u64max:
109; CHECK-NEXT: .int64 -1{{$}}
110; CHECK-NEXT: .size u64max, 8{{$}}
111@u64max = internal global i64 -1
112
113; CHECK: .type f32ud,@object
114; CHECK: .p2align 2, 0x0{{$}}
115; CHECK-NEXT: f32ud:
116; CHECK-NEXT: .skip 4{{$}}
117; CHECK-NEXT: .size f32ud, 4{{$}}
118@f32ud = internal global float undef
119
120; CHECK: .type f32nil,@object
121; CHECK: .p2align 2, 0x0{{$}}
122; CHECK-NEXT: f32nil:
123; CHECK-NEXT: .int32 0x00000000{{$}}
124; CHECK-NEXT: .size f32nil, 4{{$}}
125@f32nil = internal global float zeroinitializer
126
127; CHECK: .type f32z,@object
128; CHECK: .p2align 2, 0x0{{$}}
129; CHECK-NEXT: f32z:
130; CHECK-NEXT: .int32 0x00000000{{$}}
131; CHECK-NEXT: .size f32z, 4{{$}}
132@f32z = internal global float 0.0
133
134; CHECK: .type f32nz,@object
135; CHECK: .p2align 2, 0x0{{$}}
136; CHECK: f32nz:
137; CHECK: .int32 0x80000000{{$}}
138; CHECK: .size f32nz, 4{{$}}
139@f32nz = internal global float -0.0
140
141; CHECK: .type f32two,@object
142; CHECK: .p2align 2, 0x0{{$}}
143; CHECK-NEXT: f32two:
144; CHECK-NEXT: .int32 0x40000000{{$}}
145; CHECK-NEXT: .size f32two, 4{{$}}
146@f32two = internal global float 2.0
147
148; CHECK: .type f64ud,@object
149; CHECK: .p2align 3, 0x0{{$}}
150; CHECK-NEXT: f64ud:
151; CHECK-NEXT: .skip 8{{$}}
152; CHECK-NEXT: .size f64ud, 8{{$}}
153@f64ud = internal global double undef
154
155; CHECK: .type f64nil,@object
156; CHECK: .p2align 3, 0x0{{$}}
157; CHECK-NEXT: f64nil:
158; CHECK-NEXT: .int64 0x0000000000000000{{$}}
159; CHECK-NEXT: .size f64nil, 8{{$}}
160@f64nil = internal global double zeroinitializer
161
162; CHECK: .type f64z,@object
163; CHECK: .p2align 3, 0x0{{$}}
164; CHECK-NEXT: f64z:
165; CHECK-NEXT: .int64 0x0000000000000000{{$}}
166; CHECK-NEXT: .size f64z, 8{{$}}
167@f64z = internal global double 0.0
168
169; CHECK: .type f64nz,@object
170; CHECK: .p2align 3, 0x0{{$}}
171; CHECK-NEXT: f64nz:
172; CHECK-NEXT: .int64 0x8000000000000000{{$}}
173; CHECK-NEXT: .size f64nz, 8{{$}}
174@f64nz = internal global double -0.0
175
176; CHECK: .type f64two,@object
177; CHECK: .p2align 3, 0x0{{$}}
178; CHECK-NEXT: f64two:
179; CHECK-NEXT: .int64 0x4000000000000000{{$}}
180; CHECK-NEXT: .size f64two, 8{{$}}
181@f64two = internal global double 2.0
182
183; Indexing into a global array produces a relocation.
184; CHECK:      .type arr,@object
185; CHECK:      .type ptr,@object
186; CHECK:      ptr:
187; CHECK-NEXT: .int32 arr+80
188; CHECK-NEXT: .size ptr, 4
189@arr = global [128 x i32] zeroinitializer, align 16
190@ptr = global ptr getelementptr inbounds ([128 x i32], ptr @arr, i32 0, i32 20), align 4
191
192; Constant global.
193; CHECK: .type    rom,@object{{$}}
194; CHECK: .section .rodata.rom,""
195; CHECK: .globl   rom{{$}}
196; CHECK: .p2align   4, 0x0{{$}}
197; CHECK: rom:
198; CHECK: .skip    512{{$}}
199; CHECK: .size    rom, 512{{$}}
200@rom = constant [128 x i32] zeroinitializer, align 16
201
202; CHECK: .type       array,@object
203; CHECK: array:
204; CHECK-NEXT: .skip       8
205; CHECK-NEXT: .size       array, 8
206; CHECK: .type       pointer_to_array,@object
207; CHECK-NEXT: .section    .rodata.pointer_to_array,""
208; CHECK-NEXT: .globl      pointer_to_array
209; CHECK-NEXT: .p2align      2, 0x0
210; CHECK-NEXT: pointer_to_array:
211; CHECK-NEXT: .int32      array+4
212; CHECK-NEXT: .size       pointer_to_array, 4
213@array = internal constant [8 x i8] zeroinitializer, align 1
214@pointer_to_array = constant ptr getelementptr inbounds ([8 x i8], ptr @array, i32 0, i32 4), align 4
215
216; Handle external objects with opaque type.
217%struct.ASTRUCT = type opaque
218@g_struct = external global %struct.ASTRUCT, align 1
219define i32 @address_of_opaque()  {
220  ret i32 ptrtoint (ptr @g_struct to i32)
221}
222