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