llvm-project
261 строка · 8.2 Кб
1# RUN: llvm-mc -filetype=obj -triple=wasm64-unknown-unknown -o %t.o %s
2# RUN: wasm-ld -mwasm64 --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, 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
61global.get __stack_pointer
62i64.const 16
63i64.sub
64local.tee 0
65global.set __stack_pointer
66global.get __memory_base
67i64.const data@MBREL
68i64.add
69i32.load 0
70local.set 1
71global.get indirect_func@GOT
72i64.load 0
73i32.wrap_i64
74call_indirect () -> (i32)
75drop
76local.get 0
77i64.const 16
78i64.add
79global.set __stack_pointer
80local.get 1
81end_function
82
83get_func_address:
84.functype get_func_address () -> (i64)
85global.get func_external@GOT
86end_function
87
88get_data_address:
89.functype get_data_address () -> (i64)
90global.get data_external@GOT
91end_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)
97global.get __table_base
98i64.const get_func_address@TBREL
99i64.add
100end_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