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