1# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s 2# RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o 3# RUN: obj2yaml %t.wasm | FileCheck %s 4# RUN: llvm-objdump --disassemble-symbols=__wasm_call_ctors,__wasm_apply_data_relocs --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck %s --check-prefixes DIS 5 6.functype func_external () -> () 7 8# Linker-synthesized globals 9.globaltype __stack_pointer, i32 10.globaltype __table_base, i32, immutable 11.globaltype __memory_base, i32, immutable 12 13.section .data.data,"",@ 14data: 15 .p2align 2 16 .int32 2 17 .size data, 4 18 19.section .data.indirect_func_external,"",@ 20indirect_func_external: 21 .int32 func_external 22.size indirect_func_external, 4 23 24.section .data.indirect_func,"",@ 25indirect_func: 26 .int32 foo 27 .size indirect_func, 4 28 29# Test data relocations 30 31.section .data.data_addr,"",@ 32data_addr: 33 .int32 data 34 .size data_addr, 4 35 36# .. against external symbols 37 38.section .data.data_addr_external,"",@ 39data_addr_external: 40 .int32 data_external 41 .size data_addr_external, 4 42 43# .. including addends 44 45.section .data.extern_struct_internal_ptr,"",@ 46extern_struct_internal_ptr: 47 .int32 extern_struct + 4 48 .size extern_struct_internal_ptr, 4 49 50# Test use of __stack_pointer 51 52.section .text,"",@ 53foo: 54 # %ptr = alloca i32 55 # %0 = load i32, i32* @data, align 4 56 # %1 = load i32 ()*, i32 ()** @indirect_func, align 4 57 # call i32 %1() 58 # ret i32 %0 59 .functype foo () -> (i32) 60 .local i32, i32 61 global.get __stack_pointer 62 i32.const 16 63 i32.sub 64 local.tee 0 65 global.set __stack_pointer 66 global.get __memory_base 67 i32.const data@MBREL 68 i32.add 69 i32.load 0 70 local.set 1 71 global.get indirect_func@GOT 72 i32.load 0 73 call_indirect () -> (i32) 74 drop 75 local.get 0 76 i32.const 16 77 i32.add 78 global.set __stack_pointer 79 local.get 1 80 end_function 81 82get_func_address: 83 .functype get_func_address () -> (i32) 84 global.get func_external@GOT 85 end_function 86 87get_data_address: 88 .functype get_data_address () -> (i32) 89 global.get data_external@GOT 90 end_function 91 92get_local_func_address: 93 # Verify that a function which is otherwise not address taken *is* added to 94 # the wasm table with referenced via R_WASM_TABLE_INDEX_REL_SLEB 95 .functype get_local_func_address () -> (i32) 96 global.get __table_base 97 i32.const get_func_address@TBREL 98 i32.add 99 end_function 100 101.globl foo 102.globl data 103.globl indirect_func 104.globl indirect_func_external 105.globl data_addr 106.globl data_addr_external 107.globl extern_struct_internal_ptr 108.globl get_data_address 109.globl get_func_address 110.globl get_local_func_address 111 112.hidden foo 113.hidden data 114.hidden get_data_address 115.hidden get_func_address 116 117# Without this linking will fail because we import __stack_pointer (a mutable 118# global). 119# TODO(sbc): We probably want a nicer way to specify target_features section 120# in assembly. 121.section .custom_section.target_features,"",@ 122.int8 1 123.int8 43 124.int8 15 125.ascii "mutable-globals" 126 127# check for dylink section at start 128 129# CHECK: Sections: 130# CHECK-NEXT: - Type: CUSTOM 131# CHECK-NEXT: Name: dylink.0 132# CHECK-NEXT: MemorySize: 24 133# CHECK-NEXT: MemoryAlignment: 2 134# CHECK-NEXT: TableSize: 2 135# CHECK-NEXT: TableAlignment: 0 136# CHECK-NEXT: Needed: [] 137# CHECK-NEXT: - Type: TYPE 138 139# check for import of __table_base and __memory_base globals 140 141# CHECK: - Type: IMPORT 142# CHECK-NEXT: Imports: 143# CHECK-NEXT: - Module: env 144# CHECK-NEXT: Field: memory 145# CHECK-NEXT: Kind: MEMORY 146# CHECK-NEXT: Memory: 147# CHECK-NEXT: Minimum: 0x1 148# CHECK-NEXT: - Module: env 149# CHECK-NEXT: Field: __indirect_function_table 150# CHECK-NEXT: Kind: TABLE 151# CHECK-NEXT: Table: 152# CHECK-NEXT: Index: 0 153# CHECK-NEXT: ElemType: FUNCREF 154# CHECK-NEXT: Limits: 155# CHECK-NEXT: Minimum: 0x2 156# CHECK-NEXT: - Module: env 157# CHECK-NEXT: Field: __stack_pointer 158# CHECK-NEXT: Kind: GLOBAL 159# CHECK-NEXT: GlobalType: I32 160# CHECK-NEXT: GlobalMutable: true 161# CHECK-NEXT: - Module: env 162# CHECK-NEXT: Field: __memory_base 163# CHECK-NEXT: Kind: GLOBAL 164# CHECK-NEXT: GlobalType: I32 165# CHECK-NEXT: GlobalMutable: false 166# CHECK-NEXT: - Module: env 167# CHECK-NEXT: Field: __table_base 168# CHECK-NEXT: Kind: GLOBAL 169# CHECK-NEXT: GlobalType: I32 170# CHECK-NEXT: GlobalMutable: false 171# CHECK-NEXT: - Module: GOT.mem 172# CHECK-NEXT: Field: indirect_func 173# CHECK-NEXT: Kind: GLOBAL 174# CHECK-NEXT: GlobalType: I32 175# CHECK-NEXT: GlobalMutable: true 176# CHECK-NEXT: - Module: GOT.func 177# CHECK-NEXT: Field: func_external 178# CHECK-NEXT: Kind: GLOBAL 179# CHECK-NEXT: GlobalType: I32 180# CHECK-NEXT: GlobalMutable: true 181# CHECK-NEXT: - Module: GOT.mem 182# CHECK-NEXT: Field: data_external 183# CHECK-NEXT: Kind: GLOBAL 184# CHECK-NEXT: GlobalType: I32 185# CHECK-NEXT: GlobalMutable: true 186# CHECK-NEXT: - Module: GOT.mem 187# CHECK-NEXT: Field: extern_struct 188# CHECK-NEXT: Kind: GLOBAL 189# CHECK-NEXT: GlobalType: I32 190# CHECK-NEXT: GlobalMutable: true 191# CHECK-NEXT: - Type: FUNCTION 192 193# CHECK: - Type: EXPORT 194# CHECK-NEXT: Exports: 195# CHECK-NEXT: - Name: __wasm_call_ctors 196# CHECK-NEXT: Kind: FUNCTION 197# CHECK-NEXT: Index: 0 198 199# check for elem segment initialized with __table_base global as offset 200 201# CHECK: - Type: ELEM 202# CHECK-NEXT: Segments: 203# CHECK-NEXT: - Offset: 204# CHECK-NEXT: Opcode: GLOBAL_GET 205# CHECK-NEXT: Index: 2 206# CHECK-NEXT: Functions: [ 3, 2 ] 207 208# check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions 209 210# DIS: <__wasm_call_ctors>: 211# DIS-EMPTY: 212# DIS-NEXT: end 213 214# DIS: <__wasm_apply_data_relocs>: 215# DIS-EMPTY: 216# DIS-NEXT: i32.const 4 217# DIS-NEXT: global.get 1 218# DIS-NEXT: i32.add 219# DIS-NEXT: global.get 4 220# DIS-NEXT: i32.store 0 221# DIS-NEXT: i32.const 8 222# DIS-NEXT: global.get 1 223# DIS-NEXT: i32.add 224# DIS-NEXT: global.get 2 225# DIS-NEXT: i32.const 1 226# DIS-NEXT: i32.add 227# DIS-NEXT: i32.store 0 228# DIS-NEXT: i32.const 12 229# DIS-NEXT: global.get 1 230# DIS-NEXT: i32.add 231# DIS-NEXT: global.get 1 232# DIS-NEXT: i32.const 0 233# DIS-NEXT: i32.add 234# DIS-NEXT: i32.store 0 235# DIS-NEXT: i32.const 16 236# DIS-NEXT: global.get 1 237# DIS-NEXT: i32.add 238# DIS-NEXT: global.get 5 239# DIS-NEXT: i32.store 0 240# DIS-NEXT: i32.const 20 241# DIS-NEXT: global.get 1 242# DIS-NEXT: i32.add 243# DIS-NEXT: global.get 6 244# DIS-NEXT: i32.const 4 245# DIS-NEXT: i32.add 246# DIS-NEXT: i32.store 0 247# DIS-NEXT: end 248 249# check the data segment initialized with __memory_base global as offset 250 251# CHECK: - Type: DATA 252# CHECK-NEXT: Segments: 253# CHECK-NEXT: - SectionOffset: 6 254# CHECK-NEXT: InitFlags: 0 255# CHECK-NEXT: Offset: 256# CHECK-NEXT: Opcode: GLOBAL_GET 257# CHECK-NEXT: Index: 1 258# CHECK-NEXT: Content: '020000000000000001000000000000000000000000000000' 259