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