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