1# RUN: rm -rf %t && mkdir -p %t
2# RUN: llvm-mc -triple=arm64-apple-darwin19 -filetype=obj -o %t/macho_reloc.o %s
3# RUN: llvm-jitlink -noexec -define-abs external_data=0xdeadbeef -define-abs external_func=0xcafef00d -check=%s %t/macho_reloc.o
4
5        .section        __TEXT,__text,regular,pure_instructions
6
7        .p2align  2
8Lanon_func:
9        ret
10
11        .globl  named_func
12        .p2align  2
13named_func:
14        ret
15
16# Check ARM64_RELOC_BRANCH26 handling with a call to a local function.
17# The branch instruction only encodes 26 bits of the 28-bit possible branch
18# range, since the low 2 bits will always be zero.
19#
20# jitlink-check: decode_operand(test_local_call, 0)[25:0] = (named_func - test_local_call)[27:2]
21        .globl  test_local_call
22        .p2align  2
23test_local_call:
24        bl   named_func
25
26        .globl  _main
27        .p2align  2
28_main:
29        ret
30
31# Check ARM64_RELOC_GOTPAGE21 / ARM64_RELOC_GOTPAGEOFF12 handling with a
32# reference to an external symbol. Validate both the reference to the GOT entry,
33# and also the content of the GOT entry.
34#
35# For the GOTPAGE21/ADRP instruction we have the 21-bit delta to the 4k page
36# containing the GOT entry for external_data.
37#
38# For the GOTPAGEOFF/LDR instruction we have the 12-bit offset of the entry
39# within the page.
40#
41# jitlink-check: *{8}(got_addr(macho_reloc.o, external_data)) = external_data
42# jitlink-check: decode_operand(test_gotpage21, 1) = (got_addr(macho_reloc.o, external_data)[32:12] - test_gotpage21[32:12])
43# jitlink-check: decode_operand(test_gotpageoff12, 2) = got_addr(macho_reloc.o, external_data)[11:3]
44        .globl  test_gotpage21
45        .p2align  2
46test_gotpage21:
47        adrp  x0, external_data@GOTPAGE
48        .globl  test_gotpageoff12
49test_gotpageoff12:
50        ldr   x0, [x0, external_data@GOTPAGEOFF]
51
52# Check ARM64_RELOC_PAGE21 / ARM64_RELOC_PAGEOFF12 handling with a reference to
53# a local symbol.
54#
55# For the PAGE21/ADRP instruction we have the 21-bit delta to the 4k page
56# containing the global.
57#
58# For the GOTPAGEOFF12 relocation we test the ADD instruction, all LDR/GPR
59# variants and all LDR/Neon variants.
60#
61# jitlink-check: decode_operand(test_page21, 1) = (named_data[32:12] - test_page21[32:12])
62# jitlink-check: decode_operand(test_pageoff12add, 2) = named_data[11:0]
63# jitlink-check: decode_operand(test_pageoff12gpr8, 2) = named_data[11:0]
64# jitlink-check: decode_operand(test_pageoff12gpr16, 2) = named_data[11:1]
65# jitlink-check: decode_operand(test_pageoff12gpr32, 2) = named_data[11:2]
66# jitlink-check: decode_operand(test_pageoff12gpr64, 2) = named_data[11:3]
67# jitlink-check: decode_operand(test_pageoff12neon8, 2) = named_data[11:0]
68# jitlink-check: decode_operand(test_pageoff12neon16, 2) = named_data[11:1]
69# jitlink-check: decode_operand(test_pageoff12neon32, 2) = named_data[11:2]
70# jitlink-check: decode_operand(test_pageoff12neon64, 2) = named_data[11:3]
71# jitlink-check: decode_operand(test_pageoff12neon128, 2) = named_data[11:4]
72        .globl  test_page21
73        .p2align  2
74test_page21:
75        adrp  x0, named_data@PAGE
76
77        .globl  test_pageoff12add
78test_pageoff12add:
79        add   x0, x0, named_data@PAGEOFF
80
81        .globl  test_pageoff12gpr8
82test_pageoff12gpr8:
83        ldrb  w0, [x0, named_data@PAGEOFF]
84
85        .globl  test_pageoff12gpr16
86test_pageoff12gpr16:
87        ldrh  w0, [x0, named_data@PAGEOFF]
88
89        .globl  test_pageoff12gpr32
90test_pageoff12gpr32:
91        ldr   w0, [x0, named_data@PAGEOFF]
92
93        .globl  test_pageoff12gpr64
94test_pageoff12gpr64:
95        ldr   x0, [x0, named_data@PAGEOFF]
96
97        .globl  test_pageoff12neon8
98test_pageoff12neon8:
99        ldr   b0, [x0, named_data@PAGEOFF]
100
101        .globl  test_pageoff12neon16
102test_pageoff12neon16:
103        ldr   h0, [x0, named_data@PAGEOFF]
104
105        .globl  test_pageoff12neon32
106test_pageoff12neon32:
107        ldr   s0, [x0, named_data@PAGEOFF]
108
109        .globl  test_pageoff12neon64
110test_pageoff12neon64:
111        ldr   d0, [x0, named_data@PAGEOFF]
112
113        .globl  test_pageoff12neon128
114test_pageoff12neon128:
115        ldr   q0, [x0, named_data@PAGEOFF]
116
117# Check that calls to external functions trigger the generation of stubs and GOT
118# entries.
119#
120# jitlink-check: decode_operand(test_external_call, 0) = (stub_addr(macho_reloc.o, external_func) - test_external_call)[27:2]
121# jitlink-check: *{8}(got_addr(macho_reloc.o, external_func)) = external_func
122        .globl  test_external_call
123        .p2align  2
124test_external_call:
125        bl   external_func
126
127        .section        __DATA,__data
128
129# Storage target for non-extern ARM64_RELOC_SUBTRACTOR relocs.
130        .p2align  3
131Lanon_data:
132        .quad   0x1111111111111111
133
134# Check ARM64_RELOC_SUBTRACTOR Quad/Long in anonymous storage with anonymous
135# minuend: "LA: .quad LA - B + C". The anonymous subtrahend form
136# "LA: .quad B - LA + C" is not tested as subtrahends are not permitted to be
137# anonymous.
138#
139# Note: +8 offset in expression below to accounts for sizeof(Lanon_data).
140# jitlink-check: *{8}(section_addr(macho_reloc.o, __data) + 8) = (section_addr(macho_reloc.o, __data) + 8) - named_data + 2
141        .p2align  3
142Lanon_minuend_quad:
143        .quad Lanon_minuend_quad - named_data + 2
144
145# Note: +16 offset in expression below to accounts for sizeof(Lanon_data) + sizeof(Lanon_minuend_long).
146# jitlink-check: *{4}(section_addr(macho_reloc.o, __data) + 16) = ((section_addr(macho_reloc.o, __data) + 16) - named_data + 2)[31:0]
147        .p2align  2
148Lanon_minuend_long:
149        .long Lanon_minuend_long - named_data + 2
150
151# Named quad storage target (first named atom in __data).
152# Align to 16 for use as 128-bit load target.
153        .globl named_data
154        .p2align  4
155named_data:
156        .quad   0x2222222222222222
157        .quad   0x3333333333333333
158
159# An alt-entry point for named_data
160        .globl named_data_alt_entry
161        .p2align  3
162        .alt_entry named_data_alt_entry
163named_data_alt_entry:
164        .quad   0
165
166# Check ARM64_RELOC_UNSIGNED / quad / extern handling by putting the address of
167# a local named function into a quad symbol.
168#
169# jitlink-check: *{8}named_func_addr_quad = named_func
170        .globl  named_func_addr_quad
171        .p2align  3
172named_func_addr_quad:
173        .quad   named_func
174
175# Check ARM64_RELOC_UNSIGNED / quad / non-extern handling by putting the
176# address of a local anonymous function into a quad symbol.
177#
178# jitlink-check: *{8}anon_func_addr_quad = section_addr(macho_reloc.o, __text)
179        .globl  anon_func_addr_quad
180        .p2align  3
181anon_func_addr_quad:
182        .quad   Lanon_func
183
184# ARM64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend
185#
186# jitlink-check: *{8}anon_minuend_quad1 = section_addr(macho_reloc.o, __data) - anon_minuend_quad1 + 2
187# Only the form "B: .quad LA - B + C" is tested. The form "B: .quad B - LA + C" is
188# invalid because the subtrahend can not be local.
189        .globl  anon_minuend_quad1
190        .p2align  3
191anon_minuend_quad1:
192        .quad Lanon_data - anon_minuend_quad1 + 2
193
194# jitlink-check: *{4}anon_minuend_long1 = (section_addr(macho_reloc.o, __data) - anon_minuend_long1 + 2)[31:0]
195        .globl  anon_minuend_long1
196        .p2align  2
197anon_minuend_long1:
198        .long Lanon_data - anon_minuend_long1 + 2
199
200# Check ARM64_RELOC_SUBTRACTOR Quad/Long in named storage with minuend and subtrahend.
201# Both forms "A: .quad A - B + C" and "A: .quad B - A + C" are tested.
202#
203# Check "A: .quad B - A + C".
204# jitlink-check: *{8}subtrahend_quad2 = (named_data - subtrahend_quad2 - 2)
205        .globl  subtrahend_quad2
206        .p2align  3
207subtrahend_quad2:
208        .quad named_data - subtrahend_quad2 - 2
209
210# Check "A: .long B - A + C".
211# jitlink-check: *{4}subtrahend_long2 = (named_data - subtrahend_long2 - 2)[31:0]
212        .globl  subtrahend_long2
213        .p2align  2
214subtrahend_long2:
215        .long named_data - subtrahend_long2 - 2
216
217# Check "A: .quad A - B + C".
218# jitlink-check: *{8}minuend_quad3 = (minuend_quad3 - named_data - 2)
219        .globl  minuend_quad3
220        .p2align  3
221minuend_quad3:
222        .quad minuend_quad3 - named_data - 2
223
224# Check "A: .long B - A + C".
225# jitlink-check: *{4}minuend_long3 = (minuend_long3 - named_data - 2)[31:0]
226        .globl  minuend_long3
227        .p2align  2
228minuend_long3:
229        .long minuend_long3 - named_data - 2
230
231# Check ARM64_RELOC_SUBTRACTOR handling for exprs of the form
232# "A: .quad/long B - C + D", where 'B' or 'C' is at a fixed offset from 'A'
233# (i.e. is part of an alt_entry chain that includes 'A').
234#
235# Check "A: .long B - C + D" where 'B' is an alt_entry for 'A'.
236# jitlink-check: *{4}subtractor_with_alt_entry_minuend_long = (subtractor_with_alt_entry_minuend_long_B - named_data + 2)[31:0]
237        .globl  subtractor_with_alt_entry_minuend_long
238        .p2align  2
239subtractor_with_alt_entry_minuend_long:
240        .long subtractor_with_alt_entry_minuend_long_B - named_data + 2
241
242        .globl  subtractor_with_alt_entry_minuend_long_B
243        .p2align  2
244        .alt_entry subtractor_with_alt_entry_minuend_long_B
245subtractor_with_alt_entry_minuend_long_B:
246        .long 0
247
248# Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
249# jitlink-check: *{8}subtractor_with_alt_entry_minuend_quad = (subtractor_with_alt_entry_minuend_quad_B - named_data + 2)
250        .globl  subtractor_with_alt_entry_minuend_quad
251        .p2align  3
252subtractor_with_alt_entry_minuend_quad:
253        .quad subtractor_with_alt_entry_minuend_quad_B - named_data + 2
254
255        .globl  subtractor_with_alt_entry_minuend_quad_B
256        .p2align  3
257        .alt_entry subtractor_with_alt_entry_minuend_quad_B
258subtractor_with_alt_entry_minuend_quad_B:
259        .quad 0
260
261# Check "A: .long B - C + D" where 'C' is an alt_entry for 'A'.
262# jitlink-check: *{4}subtractor_with_alt_entry_subtrahend_long = (named_data - subtractor_with_alt_entry_subtrahend_long_B + 2)[31:0]
263        .globl  subtractor_with_alt_entry_subtrahend_long
264        .p2align  2
265subtractor_with_alt_entry_subtrahend_long:
266        .long named_data - subtractor_with_alt_entry_subtrahend_long_B + 2
267
268        .globl  subtractor_with_alt_entry_subtrahend_long_B
269        .p2align  2
270        .alt_entry subtractor_with_alt_entry_subtrahend_long_B
271subtractor_with_alt_entry_subtrahend_long_B:
272        .long 0
273
274# Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
275# jitlink-check: *{8}subtractor_with_alt_entry_subtrahend_quad = (named_data - subtractor_with_alt_entry_subtrahend_quad_B + 2)
276        .globl  subtractor_with_alt_entry_subtrahend_quad
277        .p2align  3
278subtractor_with_alt_entry_subtrahend_quad:
279        .quad named_data - subtractor_with_alt_entry_subtrahend_quad_B + 2
280
281        .globl  subtractor_with_alt_entry_subtrahend_quad_B
282        .p2align  3
283        .alt_entry subtractor_with_alt_entry_subtrahend_quad_B
284subtractor_with_alt_entry_subtrahend_quad_B:
285        .quad 0
286
287# Check ARM64_POINTER_TO_GOT handling.
288# ARM64_POINTER_TO_GOT is a delta-32 to a GOT entry.
289#
290# jitlink-check: *{4}test_got = (got_addr(macho_reloc.o, external_data) - test_got)[31:0]
291        .globl test_got
292        .p2align  2
293test_got:
294        .long   external_data@got - .
295
296# Check that unreferenced atoms in no-dead-strip sections are not dead stripped.
297# We need to use a local symbol for this as any named symbol will end up in the
298# ORC responsibility set, which is automatically marked live and would couse
299# spurious passes.
300#
301# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_sect) = 0
302        .section        __DATA,__nds_test_sect,regular,no_dead_strip
303        .quad 0
304
305# Check that unreferenced local symbols that have been marked no-dead-strip are
306# not dead-striped.
307#
308# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_nlst) = 0
309        .section       __DATA,__nds_test_nlst,regular
310        .no_dead_strip no_dead_strip_test_symbol
311no_dead_strip_test_symbol:
312        .quad 0
313
314# Check that explicit zero-fill symbols are supported
315# jitlink-check: *{8}zero_fill_test = 0
316        .globl zero_fill_test
317.zerofill __DATA,__zero_fill_test,zero_fill_test,8,3
318
319# Check that section alignments are respected.
320# We test this by introducing two segments with alignment 8, each containing one
321# byte of data. We require both symbols to have an aligned address.
322#
323# jitlink-check: section_alignment_check1[2:0] = 0
324# jitlink-check: section_alignment_check2[2:0] = 0
325        .section        __DATA,__sec_align_chk1
326        .p2align 3
327
328        .globl section_alignment_check1
329section_alignment_check1:
330        .byte 0
331
332        .section        __DATA,__sec_align_chk2
333        .p2align 3
334
335        .globl section_alignment_check2
336section_alignment_check2:
337        .byte 0
338
339.subsections_via_symbols
340