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