aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_Arm64_relocations.s
blob: b72e3b9d3a1dd893acf86ae803c0f0ebe599bbc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# RUN: rm -rf %t && mkdir -p %t
# RUN: llvm-mc -triple=arm64-apple-darwin19 -filetype=obj -o %t/macho_reloc.o %s
# RUN: llvm-jitlink -noexec -define-abs external_data=0xdeadbeef -define-abs external_func=0xcafef00d -check=%s %t/macho_reloc.o

        .section        __TEXT,__text,regular,pure_instructions

        .p2align  2
Lanon_func:
        ret

        .globl  named_func
        .p2align  2
named_func:
        ret

# Check ARM64_RELOC_BRANCH26 handling with a call to a local function.
# The branch instruction only encodes 26 bits of the 28-bit possible branch
# range, since the low 2 bits will always be zero.
#
# jitlink-check: decode_operand(test_local_call, 0)[25:0] = (named_func - test_local_call)[27:2]
        .globl  test_local_call
        .p2align  2
test_local_call:
        bl   named_func

        .globl  _main
        .p2align  2
_main:
        ret

# Check ARM64_RELOC_GOTPAGE21 / ARM64_RELOC_GOTPAGEOFF12 handling with a
# reference to an external symbol. Validate both the reference to the GOT entry,
# and also the content of the GOT entry.
#
# For the GOTPAGE21/ADRP instruction we have the 21-bit delta to the 4k page
# containing the GOT entry for external_data.
#
# For the GOTPAGEOFF/LDR instruction we have the 12-bit offset of the entry
# within the page.
#
# jitlink-check: *{8}(got_addr(macho_reloc.o, external_data)) = external_data
# jitlink-check: decode_operand(test_gotpage21, 1) = (got_addr(macho_reloc.o, external_data)[32:12] - test_gotpage21[32:12])
# jitlink-check: decode_operand(test_gotpageoff12, 2) = got_addr(macho_reloc.o, external_data)[11:3]
        .globl  test_gotpage21
        .p2align  2
test_gotpage21:
        adrp  x0, external_data@GOTPAGE
        .globl  test_gotpageoff12
test_gotpageoff12:
        ldr   x0, [x0, external_data@GOTPAGEOFF]

# Check ARM64_RELOC_PAGE21 / ARM64_RELOC_PAGEOFF12 handling with a reference to
# a local symbol.
#
# For the PAGE21/ADRP instruction we have the 21-bit delta to the 4k page
# containing the global.
#
# For the GOTPAGEOFF12 relocation we test the ADD instruction, all LDR/GPR
# variants and all LDR/Neon variants.
#
# jitlink-check: decode_operand(test_page21, 1) = (named_data[32:12] - test_page21[32:12])
# jitlink-check: decode_operand(test_pageoff12add, 2) = named_data[11:0]
# jitlink-check: decode_operand(test_pageoff12gpr8, 2) = named_data[11:0]
# jitlink-check: decode_operand(test_pageoff12gpr16, 2) = named_data[11:1]
# jitlink-check: decode_operand(test_pageoff12gpr32, 2) = named_data[11:2]
# jitlink-check: decode_operand(test_pageoff12gpr64, 2) = named_data[11:3]
# jitlink-check: decode_operand(test_pageoff12neon8, 2) = named_data[11:0]
# jitlink-check: decode_operand(test_pageoff12neon16, 2) = named_data[11:1]
# jitlink-check: decode_operand(test_pageoff12neon32, 2) = named_data[11:2]
# jitlink-check: decode_operand(test_pageoff12neon64, 2) = named_data[11:3]
# jitlink-check: decode_operand(test_pageoff12neon128, 2) = named_data[11:4]
        .globl  test_page21
        .p2align  2
test_page21:
        adrp  x0, named_data@PAGE

        .globl  test_pageoff12add
test_pageoff12add:
        add   x0, x0, named_data@PAGEOFF

        .globl  test_pageoff12gpr8
test_pageoff12gpr8:
        ldrb  w0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12gpr16
test_pageoff12gpr16:
        ldrh  w0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12gpr32
test_pageoff12gpr32:
        ldr   w0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12gpr64
test_pageoff12gpr64:
        ldr   x0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12neon8
test_pageoff12neon8:
        ldr   b0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12neon16
test_pageoff12neon16:
        ldr   h0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12neon32
test_pageoff12neon32:
        ldr   s0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12neon64
test_pageoff12neon64:
        ldr   d0, [x0, named_data@PAGEOFF]

        .globl  test_pageoff12neon128
test_pageoff12neon128:
        ldr   q0, [x0, named_data@PAGEOFF]

# Check that calls to external functions trigger the generation of stubs and GOT
# entries.
#
# jitlink-check: decode_operand(test_external_call, 0) = (stub_addr(macho_reloc.o, external_func) - test_external_call)[27:2]
# jitlink-check: *{8}(got_addr(macho_reloc.o, external_func)) = external_func
        .globl  test_external_call
        .p2align  2
test_external_call:
        bl   external_func

        .section        __DATA,__data

# Storage target for non-extern ARM64_RELOC_SUBTRACTOR relocs.
        .p2align  3
Lanon_data:
        .quad   0x1111111111111111

# Check ARM64_RELOC_SUBTRACTOR Quad/Long in anonymous storage with anonymous
# minuend: "LA: .quad LA - B + C". The anonymous subtrahend form
# "LA: .quad B - LA + C" is not tested as subtrahends are not permitted to be
# anonymous.
#
# Note: +8 offset in expression below to accounts for sizeof(Lanon_data).
# jitlink-check: *{8}(section_addr(macho_reloc.o, __data) + 8) = (section_addr(macho_reloc.o, __data) + 8) - named_data + 2
        .p2align  3
Lanon_minuend_quad:
        .quad Lanon_minuend_quad - named_data + 2

# Note: +16 offset in expression below to accounts for sizeof(Lanon_data) + sizeof(Lanon_minuend_long).
# jitlink-check: *{4}(section_addr(macho_reloc.o, __data) + 16) = ((section_addr(macho_reloc.o, __data) + 16) - named_data + 2)[31:0]
        .p2align  2
Lanon_minuend_long:
        .long Lanon_minuend_long - named_data + 2

# Named quad storage target (first named atom in __data).
# Align to 16 for use as 128-bit load target.
        .globl named_data
        .p2align  4
named_data:
        .quad   0x2222222222222222
        .quad   0x3333333333333333

# An alt-entry point for named_data
        .globl named_data_alt_entry
        .p2align  3
        .alt_entry named_data_alt_entry
named_data_alt_entry:
        .quad   0

# Check ARM64_RELOC_UNSIGNED / quad / extern handling by putting the address of
# a local named function into a quad symbol.
#
# jitlink-check: *{8}named_func_addr_quad = named_func
        .globl  named_func_addr_quad
        .p2align  3
named_func_addr_quad:
        .quad   named_func

# Check ARM64_RELOC_UNSIGNED / quad / non-extern handling by putting the
# address of a local anonymous function into a quad symbol.
#
# jitlink-check: *{8}anon_func_addr_quad = section_addr(macho_reloc.o, __text)
        .globl  anon_func_addr_quad
        .p2align  3
anon_func_addr_quad:
        .quad   Lanon_func

# ARM64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend
#
# jitlink-check: *{8}anon_minuend_quad1 = section_addr(macho_reloc.o, __data) - anon_minuend_quad1 + 2
# Only the form "B: .quad LA - B + C" is tested. The form "B: .quad B - LA + C" is
# invalid because the subtrahend can not be local.
        .globl  anon_minuend_quad1
        .p2align  3
anon_minuend_quad1:
        .quad Lanon_data - anon_minuend_quad1 + 2

# jitlink-check: *{4}anon_minuend_long1 = (section_addr(macho_reloc.o, __data) - anon_minuend_long1 + 2)[31:0]
        .globl  anon_minuend_long1
        .p2align  2
anon_minuend_long1:
        .long Lanon_data - anon_minuend_long1 + 2

# Check ARM64_RELOC_SUBTRACTOR Quad/Long in named storage with minuend and subtrahend.
# Both forms "A: .quad A - B + C" and "A: .quad B - A + C" are tested.
#
# Check "A: .quad B - A + C".
# jitlink-check: *{8}subtrahend_quad2 = (named_data - subtrahend_quad2 - 2)
        .globl  subtrahend_quad2
        .p2align  3
subtrahend_quad2:
        .quad named_data - subtrahend_quad2 - 2

# Check "A: .long B - A + C".
# jitlink-check: *{4}subtrahend_long2 = (named_data - subtrahend_long2 - 2)[31:0]
        .globl  subtrahend_long2
        .p2align  2
subtrahend_long2:
        .long named_data - subtrahend_long2 - 2

# Check "A: .quad A - B + C".
# jitlink-check: *{8}minuend_quad3 = (minuend_quad3 - named_data - 2)
        .globl  minuend_quad3
        .p2align  3
minuend_quad3:
        .quad minuend_quad3 - named_data - 2

# Check "A: .long B - A + C".
# jitlink-check: *{4}minuend_long3 = (minuend_long3 - named_data - 2)[31:0]
        .globl  minuend_long3
        .p2align  2
minuend_long3:
        .long minuend_long3 - named_data - 2

# Check ARM64_RELOC_SUBTRACTOR handling for exprs of the form
# "A: .quad/long B - C + D", where 'B' or 'C' is at a fixed offset from 'A'
# (i.e. is part of an alt_entry chain that includes 'A').
#
# Check "A: .long B - C + D" where 'B' is an alt_entry for 'A'.
# jitlink-check: *{4}subtractor_with_alt_entry_minuend_long = (subtractor_with_alt_entry_minuend_long_B - named_data + 2)[31:0]
        .globl  subtractor_with_alt_entry_minuend_long
        .p2align  2
subtractor_with_alt_entry_minuend_long:
        .long subtractor_with_alt_entry_minuend_long_B - named_data + 2

        .globl  subtractor_with_alt_entry_minuend_long_B
        .p2align  2
        .alt_entry subtractor_with_alt_entry_minuend_long_B
subtractor_with_alt_entry_minuend_long_B:
        .long 0

# Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
# jitlink-check: *{8}subtractor_with_alt_entry_minuend_quad = (subtractor_with_alt_entry_minuend_quad_B - named_data + 2)
        .globl  subtractor_with_alt_entry_minuend_quad
        .p2align  3
subtractor_with_alt_entry_minuend_quad:
        .quad subtractor_with_alt_entry_minuend_quad_B - named_data + 2

        .globl  subtractor_with_alt_entry_minuend_quad_B
        .p2align  3
        .alt_entry subtractor_with_alt_entry_minuend_quad_B
subtractor_with_alt_entry_minuend_quad_B:
        .quad 0

# Check "A: .long B - C + D" where 'C' is an alt_entry for 'A'.
# jitlink-check: *{4}subtractor_with_alt_entry_subtrahend_long = (named_data - subtractor_with_alt_entry_subtrahend_long_B + 2)[31:0]
        .globl  subtractor_with_alt_entry_subtrahend_long
        .p2align  2
subtractor_with_alt_entry_subtrahend_long:
        .long named_data - subtractor_with_alt_entry_subtrahend_long_B + 2

        .globl  subtractor_with_alt_entry_subtrahend_long_B
        .p2align  2
        .alt_entry subtractor_with_alt_entry_subtrahend_long_B
subtractor_with_alt_entry_subtrahend_long_B:
        .long 0

# Check "A: .quad B - C + D" where 'B' is an alt_entry for 'A'.
# jitlink-check: *{8}subtractor_with_alt_entry_subtrahend_quad = (named_data - subtractor_with_alt_entry_subtrahend_quad_B + 2)
        .globl  subtractor_with_alt_entry_subtrahend_quad
        .p2align  3
subtractor_with_alt_entry_subtrahend_quad:
        .quad named_data - subtractor_with_alt_entry_subtrahend_quad_B + 2

        .globl  subtractor_with_alt_entry_subtrahend_quad_B
        .p2align  3
        .alt_entry subtractor_with_alt_entry_subtrahend_quad_B
subtractor_with_alt_entry_subtrahend_quad_B:
        .quad 0

# Check ARM64_POINTER_TO_GOT handling.
# ARM64_POINTER_TO_GOT is a delta-32 to a GOT entry.
#
# jitlink-check: *{4}test_got = (got_addr(macho_reloc.o, external_data) - test_got)[31:0]
        .globl test_got
        .p2align  2
test_got:
        .long   external_data@got - .

# Check that unreferenced atoms in no-dead-strip sections are not dead stripped.
# We need to use a local symbol for this as any named symbol will end up in the
# ORC responsibility set, which is automatically marked live and would couse
# spurious passes.
#
# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_sect) = 0
        .section        __DATA,__nds_test_sect,regular,no_dead_strip
        .quad 0

# Check that unreferenced local symbols that have been marked no-dead-strip are
# not dead-striped.
#
# jitlink-check: *{8}section_addr(macho_reloc.o, __nds_test_nlst) = 0
        .section       __DATA,__nds_test_nlst,regular
        .no_dead_strip no_dead_strip_test_symbol
no_dead_strip_test_symbol:
        .quad 0

# Check that explicit zero-fill symbols are supported
# jitlink-check: *{8}zero_fill_test = 0
        .globl zero_fill_test
.zerofill __DATA,__zero_fill_test,zero_fill_test,8,3

# Check that section alignments are respected.
# We test this by introducing two segments with alignment 8, each containing one
# byte of data. We require both symbols to have an aligned address.
#
# jitlink-check: section_alignment_check1[2:0] = 0
# jitlink-check: section_alignment_check2[2:0] = 0
        .section        __DATA,__sec_align_chk1
        .p2align 3

        .globl section_alignment_check1
section_alignment_check1:
        .byte 0

        .section        __DATA,__sec_align_chk2
        .p2align 3

        .globl section_alignment_check2
section_alignment_check2:
        .byte 0

.subsections_via_symbols