Skip to content

Commit 9b8059e

Browse files
committed
Add thunk range test cases
Feedback from review
1 parent e3b915a commit 9b8059e

File tree

3 files changed

+285
-0
lines changed

3 files changed

+285
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# REQUIRES: hexagon
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o
4+
# RUN: ld.lld main.o -o test
5+
# RUN: llvm-objdump -d --no-show-raw-insn test | FileCheck %s
6+
7+
## Test thunk range scenarios for Hexagon R_HEX_B22_PCREL relocations.
8+
## R_HEX_B22_PCREL has a range of +/- 8MB (0x800000 bytes).
9+
10+
#--- main.s
11+
.globl _start
12+
.type _start, %function
13+
_start:
14+
call target_within_range_max
15+
call target_beyond_range
16+
call target_within_range_min
17+
call target_beyond_range_min
18+
call target_multiple_calls
19+
call target_multiple_calls
20+
call target_close
21+
jumpr r31
22+
23+
target_close:
24+
jumpr r31
25+
26+
## Target at maximum positive range (8MB - 4 bytes from _start)
27+
## We need to account for the instructions above: 7 calls + 1 jumpr = 8 * 4 = 32 bytes
28+
.skip 0X7fffbc
29+
.globl target_within_range_max
30+
.type target_within_range_max, %function
31+
target_within_range_max:
32+
jumpr r31
33+
34+
## Target just beyond maximum positive range (needs thunk)
35+
.skip 8
36+
.globl target_beyond_range
37+
.type target_beyond_range, %function
38+
target_beyond_range:
39+
call target_within_range_max
40+
jumpr r31
41+
42+
## Target for multiple calls test
43+
.skip 0x100000
44+
.globl target_multiple_calls
45+
.type target_multiple_calls, %function
46+
target_multiple_calls:
47+
jumpr r31
48+
49+
## Now place targets at maximum negative range
50+
## We'll put these before _start in memory layout
51+
.section .text_negative, "ax", %progbits
52+
53+
## Target at maximum negative range (-8MB + 4 bytes from _start)
54+
.globl target_within_range_min
55+
.type target_within_range_min, %function
56+
target_within_range_min:
57+
call target_close
58+
jumpr r31
59+
60+
.skip 0X7ffff4
61+
62+
## Target beyond maximum negative range (needs thunk)
63+
.globl target_beyond_range_min
64+
.type target_beyond_range_min, %function
65+
target_beyond_range_min:
66+
jumpr r31
67+
68+
## Verify thunk generation for targets beyond B22_PCREL range
69+
# CHECK: 000200b4 <__hexagon_thunk_target_within_range_min_from_.text.thunk>:
70+
# CHECK-NEXT: 200b4: { immext(#0x900000)
71+
# CHECK-NEXT: 200b8: jump 0x9200cc }
72+
73+
# CHECK: 000200bc <__hexagon_thunk_target_beyond_range_min_from_.text.thunk>:
74+
# CHECK-NEXT: 200bc: { immext(#0x1100000)
75+
# CHECK-NEXT: 200c0: jump 0x11200c8 }
76+
77+
# CHECK: 000200c4 <__hexagon_thunk_target_multiple_calls_from_.text.thunk>:
78+
# CHECK-NEXT: 200c4: { immext(#0x8fffc0)
79+
# CHECK-NEXT: 200c8: jump 0x9200c0 }
80+
81+
## Verify _start calls - some direct, some via thunks
82+
# CHECK: 000200cc <_start>:
83+
# CHECK-NEXT: 200cc: { call 0x8200ac }
84+
# CHECK-NEXT: 200d0: { call 0x8200b8 }
85+
# CHECK-NEXT: 200d4: { call 0x200b4 }
86+
# CHECK-NEXT: 200d8: { call 0x200bc }
87+
# CHECK-NEXT: 200dc: { call 0x200c4 }
88+
# CHECK-NEXT: 200e0: { call 0x200c4 }
89+
# CHECK-NEXT: 200e4: { call 0x200ec }
90+
91+
# CHECK: 000200ec <target_close>:
92+
# CHECK-NEXT: 200ec: { jumpr r31 }
93+
94+
## Verify targets at maximum positive range (direct calls, no thunks needed)
95+
# CHECK: 008200ac <target_within_range_max>:
96+
# CHECK-NEXT: 8200ac: { jumpr r31 }
97+
98+
# CHECK: 008200b8 <target_beyond_range>:
99+
# CHECK-NEXT: 8200b8: { call 0x8200ac }
100+
# CHECK-NEXT: 8200bc: { jumpr r31 }
101+
102+
# CHECK: 009200c0 <target_multiple_calls>:
103+
# CHECK-NEXT: 9200c0: { jumpr r31 }
104+
105+
## Verify targets in negative section and thunk for calling back to main section
106+
# CHECK: 009200c4 <__hexagon_thunk__from_.text.thunk>:
107+
# CHECK-NEXT: 9200c4: { immext(#0xff700000)
108+
# CHECK-NEXT: 9200c8: jump 0x200cc }
109+
110+
# CHECK: 009200cc <target_within_range_min>:
111+
# CHECK-NEXT: 9200cc: { call 0x9200c4 }
112+
# CHECK-NEXT: 9200d0: { jumpr r31 }
113+
114+
# CHECK: 011200c8 <target_beyond_range_min>:
115+
# CHECK-NEXT: 11200c8: { jumpr r31 }
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# REQUIRES: hexagon
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o
4+
# RUN: ld.lld -shared main.o -o test.so
5+
# RUN: llvm-objdump -d --no-show-raw-insn test.so | FileCheck %s
6+
7+
## Test thunk range scenarios for Hexagon R_HEX_GD_PLT_B22_PCREL relocations.
8+
## Same ±8MB range as regular calls.
9+
10+
#--- main.s
11+
.globl _start
12+
.type _start, @function
13+
_start:
14+
## Setup for TLS Global Dynamic calls
15+
r2 = add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL)
16+
17+
## Test TLS GD PLT calls
18+
r0 = add(r2,##tls_var_close@GDGOT)
19+
call tls_var_close@GDPLT
20+
21+
r0 = add(r2,##tls_var_far@GDGOT)
22+
call tls_var_far@GDPLT
23+
24+
jumpr r31
25+
26+
.skip 0x400000
27+
28+
more_code:
29+
r0 = add(r2,##tls_var_distant@GDGOT)
30+
call tls_var_distant@GDPLT
31+
jumpr r31
32+
33+
## TLS variables in .tdata section
34+
.section .tdata,"awT",@progbits
35+
.globl tls_var_close, tls_var_far, tls_var_distant
36+
.type tls_var_close, @object
37+
.type tls_var_far, @object
38+
.type tls_var_distant, @object
39+
40+
tls_var_close:
41+
.word 0x1234
42+
43+
tls_var_far:
44+
.word 0x5678
45+
46+
tls_var_distant:
47+
.word 0x9abc
48+
49+
# CHECK: Disassembly of section .text:
50+
# CHECK: 000102d4 <_start>:
51+
# CHECK-NEXT: { immext(#0x420100)
52+
# CHECK-NEXT: r2 = add(pc,##0x420130) }
53+
# CHECK-NEXT: { immext(#0xfffeffc0)
54+
# CHECK-NEXT: r0 = add(r2,##-0x10018) }
55+
# CHECK-NEXT: { call 0x410360 }
56+
# CHECK-NEXT: { immext(#0xfffeffc0)
57+
# CHECK-NEXT: r0 = add(r2,##-0x10010) }
58+
# CHECK-NEXT: { call 0x410360 }
59+
# CHECK-NEXT: { jumpr r31 }
60+
61+
# CHECK: 004102f8 <more_code>:
62+
# CHECK-NEXT: { immext(#0xfffeffc0)
63+
# CHECK-NEXT: r0 = add(r2,##-0x10008) }
64+
# CHECK-NEXT: { call 0x410360 }
65+
# CHECK-NEXT: { jumpr r31 }
66+
67+
## Verify PLT entries are created for TLS
68+
# CHECK: Disassembly of section .plt:
69+
# CHECK: 00410310 <.plt>:
70+
# CHECK-NEXT: { immext(#0x200c0)
71+
# CHECK-NEXT: r28 = add(pc,##0x200f4) }
72+
# CHECK-NEXT: { r14 -= add(r28,#0x10)
73+
# CHECK-NEXT: r15 = memw(r28+#0x8)
74+
# CHECK-NEXT: r28 = memw(r28+#0x4) }
75+
# CHECK-NEXT: { r14 = asr(r14,#0x2)
76+
# CHECK-NEXT: jumpr r28 }
77+
# CHECK-NEXT: { trap0(#0xdb) }
78+
79+
# CHECK: 00410340 <tls_var_far@plt>:
80+
# CHECK-NEXT: { immext(#0x200c0)
81+
# CHECK-NEXT: r14 = add(pc,##0x200d8) }
82+
# CHECK-NEXT: { r28 = memw(r14+#0x0) }
83+
# CHECK-NEXT: { jumpr r28 }
84+
85+
# CHECK: 00410350 <tls_var_distant@plt>:
86+
# CHECK-NEXT: { immext(#0x200c0)
87+
# CHECK-NEXT: r14 = add(pc,##0x200cc) }
88+
# CHECK-NEXT: { r28 = memw(r14+#0x0) }
89+
# CHECK-NEXT: { jumpr r28 }
90+
91+
# CHECK: 00410360 <__tls_get_addr@plt>:
92+
# CHECK-NEXT: { immext(#0x200c0)
93+
# CHECK-NEXT: r14 = add(pc,##0x200c0) }
94+
# CHECK-NEXT: { r28 = memw(r14+#0x0) }
95+
# CHECK-NEXT: { jumpr r28 }
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# REQUIRES: hexagon
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf external.s -o external.o
4+
# RUN: ld.lld -shared external.o -soname external.so -o external.so
5+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf main.s -o main.o
6+
# RUN: ld.lld main.o external.so -o test
7+
# RUN: llvm-objdump -d --no-show-raw-insn test | FileCheck %s
8+
9+
## Test thunk range scenarios for Hexagon R_HEX_PLT_B22_PCREL relocations.
10+
## PLT calls use the same ±8MB range as regular calls but go through PLT entries.
11+
## This test verifies thunk generation for PLT calls at range boundaries.
12+
13+
#--- external.s
14+
.globl extern_within_range, extern_beyond_range, extern_close
15+
.type extern_within_range, @function
16+
.type extern_beyond_range, @function
17+
.type extern_close, @function
18+
19+
extern_within_range:
20+
jumpr r31
21+
22+
extern_beyond_range:
23+
jumpr r31
24+
25+
extern_close:
26+
jumpr r31
27+
28+
#--- main.s
29+
.globl _start
30+
.type _start, @function
31+
_start:
32+
## Test PLT calls to external functions at various ranges
33+
call extern_within_range@PLT
34+
call extern_beyond_range@PLT
35+
call extern_close@PLT
36+
jumpr r31
37+
38+
.skip 0x200000
39+
40+
# CHECK: Disassembly of section .text:
41+
# CHECK: 0002021c <_start>:
42+
# CHECK-NEXT: { call 0x220250 }
43+
# CHECK-NEXT: { call 0x220260 }
44+
# CHECK-NEXT: { call 0x220270 }
45+
# CHECK-NEXT: { jumpr r31 }
46+
47+
## Verify PLT header and entries are created with exact addresses
48+
# CHECK: Disassembly of section .plt:
49+
# CHECK: 00220230 <.plt>:
50+
# CHECK-NEXT: { immext(#0x20080)
51+
# CHECK-NEXT: r28 = add(pc,##0x200b8) }
52+
# CHECK-NEXT: { r14 -= add(r28,#0x10)
53+
# CHECK-NEXT: r15 = memw(r28+#0x8)
54+
# CHECK-NEXT: r28 = memw(r28+#0x4) }
55+
# CHECK-NEXT: { r14 = asr(r14,#0x2)
56+
# CHECK-NEXT: jumpr r28 }
57+
# CHECK-NEXT: { trap0(#0xdb) }
58+
59+
# CHECK: 00220250 <extern_within_range@plt>:
60+
# CHECK-NEXT: { immext(#0x20080)
61+
# CHECK-NEXT: r14 = add(pc,##0x200a8) }
62+
# CHECK-NEXT: { r28 = memw(r14+#0x0) }
63+
# CHECK-NEXT: { jumpr r28 }
64+
65+
# CHECK: 00220260 <extern_beyond_range@plt>:
66+
# CHECK-NEXT: { immext(#0x20080)
67+
# CHECK-NEXT: r14 = add(pc,##0x2009c) }
68+
# CHECK-NEXT: { r28 = memw(r14+#0x0) }
69+
# CHECK-NEXT: { jumpr r28 }
70+
71+
# CHECK: 00220270 <extern_close@plt>:
72+
# CHECK-NEXT: { immext(#0x20080)
73+
# CHECK-NEXT: r14 = add(pc,##0x20090) }
74+
# CHECK-NEXT: { r28 = memw(r14+#0x0) }
75+
# CHECK-NEXT: { jumpr r28 }

0 commit comments

Comments
 (0)