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