1; RUN: llc < %s --mtriple=wasm32-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i32 2; RUN: llc < %s --mtriple=wasm32-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i32 3; RUN: llc < %s --mtriple=wasm64-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i64 4; RUN: llc < %s --mtriple=wasm64-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i64 5 6; Test that globals assemble as expected with -fPIC. 7; We test here both with and without fast-isel. 8 9@hidden_global = external hidden global i32 10@hidden_global_array = external hidden global [10 x i32] 11@external_global = external global i32 12@external_global_array = external global [10 x i32] 13 14declare i32 @foo(); 15 16; For hidden symbols PIC code needs to offset all loads and stores 17; by the value of the __memory_base global 18 19define i32 @load_hidden_global() { 20; CHECK-LABEL: load_hidden_global: 21; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} 22; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global@MBREL{{$}} 23; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 24; PIC-NEXT: i32.load $push[[L3:[0-9]+]]=, 0($pop[[L2]]){{$}} 25; CHECK-NEXT: end_function 26 27 %1 = load i32, i32* @hidden_global 28 ret i32 %1 29} 30 31define i32 @load_hidden_global_offset() { 32; CHECK-LABEL: load_hidden_global_offset: 33; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} 34; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global_array@MBREL{{$}} 35; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1:[0-9]+]]{{$}} 36; PIC-NEXT: [[PTR]].const $push[[L3:[0-9]+]]=, 20{{$}} 37; PIC-NEXT: [[PTR]].add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} 38; PIC-NEXT: i32.load $push{{[0-9]+}}=, 0($pop[[L4]]){{$}} 39; CHECK-NEXT: end_function 40 41 %1 = getelementptr [10 x i32], [10 x i32]* @hidden_global_array, i32 0, i32 5 42 %2 = load i32, i32* %1 43 ret i32 %2 44} 45 46; Store to a hidden global 47 48define void @store_hidden_global(i32 %n) { 49; CHECK-LABEL: store_hidden_global: 50; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} 51; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global@MBREL{{$}} 52; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 53; PIC-NEXT: i32.store 0($pop[[L2]]), $0{{$}} 54; CHECK-NEXT: end_function 55 56 store i32 %n, i32* @hidden_global 57 ret void 58} 59 60define void @store_hidden_global_offset(i32 %n) { 61; CHECK-LABEL: store_hidden_global_offset: 62; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} 63; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global_array@MBREL{{$}} 64; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 65; PIC-NEXT: [[PTR]].const $push[[L3:[0-9]+]]=, 20{{$}} 66; PIC-NEXT: [[PTR]].add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} 67; PIC-NEXT: i32.store 0($pop[[L4]]), $0{{$}} 68 69; CHECK-NEXT: end_function 70 71 %1 = getelementptr [10 x i32], [10 x i32]* @hidden_global_array, i32 0, i32 5 72 store i32 %n, i32* %1 73 ret void 74} 75 76; For non-hidden globals PIC code has to load the address from a wasm global 77; using the @GOT relocation type. 78 79 80define i32 @load_external_global() { 81; CHECK-LABEL: load_external_global: 82; PIC: global.get $push[[L0:[0-9]+]]=, external_global@GOT{{$}} 83; PIC-NEXT: i32.load $push{{[0-9]+}}=, 0($pop[[L0]]){{$}} 84 85; CHECK-NEXT: end_function 86 87 %1 = load i32, i32* @external_global 88 ret i32 %1 89} 90 91define i32 @load_external_global_offset() { 92; CHECK-LABEL: load_external_global_offset: 93; PIC: global.get $push[[L0:[0-9]+]]=, external_global_array@GOT{{$}} 94; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, 20{{$}} 95; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 96; PIC-NEXT: i32.load $push{{[0-9]+}}=, 0($pop[[L2]]){{$}} 97 98; CHECK-NEXT: end_function 99 100 %1 = getelementptr [10 x i32], [10 x i32]* @external_global_array, i32 0, i32 5 101 %2 = load i32, i32* %1 102 ret i32 %2 103} 104 105; Store to a non-hidden global via the wasm global. 106 107define void @store_external_global(i32 %n) { 108; CHECK-LABEL: store_external_global: 109; PIC: global.get $push[[L0:[0-9]+]]=, external_global@GOT{{$}} 110; PIC-NEXT: i32.store 0($pop[[L0]]), $0{{$}} 111 112; CHECK-NEXT: end_function 113 114 store i32 %n, i32* @external_global 115 ret void 116} 117 118define void @store_external_global_offset(i32 %n) { 119; CHECK-LABEL: store_external_global_offset: 120; PIC: global.get $push[[L0:[0-9]+]]=, external_global_array@GOT{{$}} 121; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, 20{{$}} 122; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 123; PIC-NEXT: i32.store 0($pop[[L2]]), $0{{$}} 124 125; CHECK-NEXT: end_function 126 127 %1 = getelementptr [10 x i32], [10 x i32]* @external_global_array, i32 0, i32 5 128 store i32 %n, i32* %1 129 ret void 130} 131 132; PIC: .globaltype __memory_base, [[PTR]] 133