Skip to content

Commit cad9d21

Browse files
committed
[M68k] implement large code model
1 parent c9b6e01 commit cad9d21

File tree

6 files changed

+602
-2
lines changed

6 files changed

+602
-2
lines changed

llvm/lib/Target/M68k/M68kSubtarget.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,24 @@ M68kSubtarget &M68kSubtarget::initializeSubtargetDependencies(
127127
// ---------------------+------------+------------+------------+-------------
128128
// data global big* | pc-rel | @GOTPCREL | absolute | @GOTPCREL
129129
// ---------------------+------------+------------+------------+-------------
130+
// | Large |
131+
// +-------------------------+
132+
// | Static | PIC |
133+
// ---------------------+------------+------------+
134+
// branch | pc-rel | pc-rel |
135+
// ---------------------+------------+------------+
136+
// call global | @PLT | @PLT |
137+
// ---------------------+------------+------------+
138+
// call internal | pc-rel | pc-rel |
139+
// ---------------------+------------+------------+
140+
// data local | absolute | @GOTOFF |
141+
// ---------------------+------------+------------+
142+
// data local big* | absolute | @GOTOFF |
143+
// ---------------------+------------+------------+
144+
// data global | absolute | @GOTPCREL |
145+
// ---------------------+------------+------------+
146+
// data global big* | absolute | @GOTPCREL |
147+
// ---------------------+------------+------------+
130148
//
131149
// * Big data potentially cannot be reached within 16 bit offset and requires
132150
// special handling for old(x00 and x10) CPUs. Normally these symbols go into
@@ -171,6 +189,13 @@ M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
171189
return M68kII::MO_ABSOLUTE_ADDRESS;
172190
}
173191
}
192+
case CodeModel::Large: {
193+
if (isPositionIndependent()) {
194+
return M68kII::MO_GOTOFF;
195+
} else {
196+
return M68kII::MO_ABSOLUTE_ADDRESS;
197+
}
198+
}
174199
}
175200
}
176201

@@ -212,6 +237,12 @@ unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
212237

213238
return M68kII::MO_ABSOLUTE_ADDRESS;
214239
}
240+
case CodeModel::Large: {
241+
if (isPositionIndependent())
242+
return M68kII::MO_GOTPCREL;
243+
244+
return M68kII::MO_ABSOLUTE_ADDRESS;
245+
}
215246
}
216247
}
217248

llvm/lib/Target/M68k/M68kTargetMachine.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ CodeModel::Model getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
8787
bool JIT) {
8888
if (!CM) {
8989
return CodeModel::Small;
90-
} else if (CM == CodeModel::Large) {
91-
llvm_unreachable("Large code model is not supported");
9290
} else if (CM == CodeModel::Kernel) {
9391
llvm_unreachable("Kernel code model is not implemented yet");
9492
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -O2 -mtriple=m68k -verify-machineinstrs \
3+
; RUN: -code-model=large -relocation-model=pic \
4+
; RUN: | FileCheck %s
5+
6+
@ptr = external global ptr
7+
@dst = external global i32
8+
@src = external global i32
9+
10+
define void @test0() nounwind {
11+
; CHECK-LABEL: test0:
12+
; CHECK: ; %bb.0: ; %entry
13+
; CHECK-NEXT: move.l (dst@GOTPCREL,%pc), %a0
14+
; CHECK-NEXT: move.l (ptr@GOTPCREL,%pc), %a1
15+
; CHECK-NEXT: move.l %a0, (%a1)
16+
; CHECK-NEXT: move.l (src@GOTPCREL,%pc), %a1
17+
; CHECK-NEXT: move.l (%a1), (%a0)
18+
; CHECK-NEXT: rts
19+
entry:
20+
store ptr @dst, ptr @ptr
21+
%tmp.s = load i32, ptr @src
22+
store i32 %tmp.s, ptr @dst
23+
ret void
24+
}
25+
26+
@ptr2 = global ptr null
27+
@dst2 = global i32 0
28+
@src2 = global i32 0
29+
30+
define void @test1() nounwind {
31+
; CHECK-LABEL: test1:
32+
; CHECK: ; %bb.0: ; %entry
33+
; CHECK-NEXT: move.l (dst2@GOTPCREL,%pc), %a0
34+
; CHECK-NEXT: move.l (ptr2@GOTPCREL,%pc), %a1
35+
; CHECK-NEXT: move.l %a0, (%a1)
36+
; CHECK-NEXT: move.l (src2@GOTPCREL,%pc), %a1
37+
; CHECK-NEXT: move.l (%a1), (%a0)
38+
; CHECK-NEXT: rts
39+
entry:
40+
store ptr @dst2, ptr @ptr2
41+
%tmp.s = load i32, ptr @src2
42+
store i32 %tmp.s, ptr @dst2
43+
ret void
44+
}
45+
46+
declare ptr @malloc(i32)
47+
48+
define void @test2() nounwind {
49+
; CHECK-LABEL: test2:
50+
; CHECK: ; %bb.0: ; %entry
51+
; CHECK-NEXT: suba.l #4, %sp
52+
; CHECK-NEXT: move.l #40, (%sp)
53+
; CHECK-NEXT: jsr (malloc@PLT,%pc)
54+
; CHECK-NEXT: adda.l #4, %sp
55+
; CHECK-NEXT: rts
56+
entry:
57+
%ptr = call ptr @malloc(i32 40)
58+
ret void
59+
}
60+
61+
@pfoo = external global ptr
62+
declare ptr @afoo(...)
63+
64+
define void @test3() nounwind {
65+
; CHECK-LABEL: test3:
66+
; CHECK: ; %bb.0: ; %entry
67+
; CHECK-NEXT: suba.l #4, %sp
68+
; CHECK-NEXT: jsr (afoo@PLT,%pc)
69+
; CHECK-NEXT: move.l (pfoo@GOTPCREL,%pc), %a1
70+
; CHECK-NEXT: move.l %a0, (%a1)
71+
; CHECK-NEXT: jsr (%a0)
72+
; CHECK-NEXT: adda.l #4, %sp
73+
; CHECK-NEXT: rts
74+
entry:
75+
%tmp = call ptr(...) @afoo()
76+
store ptr %tmp, ptr @pfoo
77+
%tmp1 = load ptr, ptr @pfoo
78+
call void(...) %tmp1()
79+
ret void
80+
}
81+
82+
declare void @foo(...)
83+
84+
define void @test4() nounwind {
85+
; CHECK-LABEL: test4:
86+
; CHECK: ; %bb.0: ; %entry
87+
; CHECK-NEXT: suba.l #4, %sp
88+
; CHECK-NEXT: jsr (foo@PLT,%pc)
89+
; CHECK-NEXT: adda.l #4, %sp
90+
; CHECK-NEXT: rts
91+
entry:
92+
call void(...) @foo()
93+
ret void
94+
}
95+
96+
@ptr6 = internal global ptr null
97+
@dst6 = internal global i32 0
98+
@src6 = internal global i32 0
99+
100+
define void @test5() nounwind {
101+
; CHECK-LABEL: test5:
102+
; CHECK: ; %bb.0: ; %entry
103+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
104+
; CHECK-NEXT: move.l %a0, %a1
105+
; CHECK-NEXT: adda.l #dst6@GOTOFF, %a1
106+
; CHECK-NEXT: move.l #ptr6@GOTOFF, %d0
107+
; CHECK-NEXT: move.l %a1, (0,%a0,%d0)
108+
; CHECK-NEXT: move.l #src6@GOTOFF, %d0
109+
; CHECK-NEXT: move.l #dst6@GOTOFF, %d1
110+
; CHECK-NEXT: move.l (0,%a0,%d0), (0,%a0,%d1)
111+
; CHECK-NEXT: rts
112+
entry:
113+
store ptr @dst6, ptr @ptr6
114+
%tmp.s = load i32, ptr @src6
115+
store i32 %tmp.s, ptr @dst6
116+
ret void
117+
}
118+
119+
define void @test7(i32 %n.u) nounwind {
120+
; CHECK-LABEL: test7:
121+
; CHECK: ; %bb.0: ; %entry
122+
; CHECK-NEXT: move.l (4,%sp), %d0
123+
; CHECK-NEXT: add.l #-1, %d0
124+
; CHECK-NEXT: move.l %d0, %d1
125+
; CHECK-NEXT: sub.l #12, %d1
126+
; CHECK-NEXT: bhi .LBB6_12
127+
; CHECK-NEXT: ; %bb.1: ; %entry
128+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
129+
; CHECK-NEXT: lsl.l #2, %d0
130+
; CHECK-NEXT: adda.l #.LJTI6_0@GOTOFF, %a0
131+
; CHECK-NEXT: move.l %a0, %d1
132+
; CHECK-NEXT: add.l (0,%a0,%d0), %d1
133+
; CHECK-NEXT: move.l %d1, %a0
134+
; CHECK-NEXT: jmp (%a0)
135+
; CHECK-NEXT: .LBB6_12: ; %bb2
136+
; CHECK-NEXT: bra foo6@PLT ; TAILCALL
137+
; CHECK-NEXT: .LBB6_3: ; %bb5
138+
; CHECK-NEXT: bra foo5@PLT ; TAILCALL
139+
; CHECK-NEXT: .LBB6_5: ; %bb1
140+
; CHECK-NEXT: bra foo2@PLT ; TAILCALL
141+
; CHECK-NEXT: .LBB6_2: ; %bb
142+
; CHECK-NEXT: bra foo1@PLT ; TAILCALL
143+
; CHECK-NEXT: .LBB6_9: ; %bb4
144+
; CHECK-NEXT: bra foo4@PLT ; TAILCALL
145+
; CHECK-NEXT: .LBB6_8: ; %bb3
146+
; CHECK-NEXT: bra foo3@PLT ; TAILCALL
147+
entry:
148+
switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ]
149+
bb:
150+
tail call void(...) @foo1()
151+
ret void
152+
bb1:
153+
tail call void(...) @foo2()
154+
ret void
155+
bb2:
156+
tail call void(...) @foo6()
157+
ret void
158+
bb3:
159+
tail call void(...) @foo3()
160+
ret void
161+
bb4:
162+
tail call void(...) @foo4()
163+
ret void
164+
bb5:
165+
tail call void(...) @foo5()
166+
ret void
167+
bb6:
168+
tail call void(...) @foo1()
169+
ret void
170+
bb7:
171+
tail call void(...) @foo2()
172+
ret void
173+
bb8:
174+
tail call void(...) @foo6()
175+
ret void
176+
bb9:
177+
tail call void(...) @foo3()
178+
ret void
179+
bb10:
180+
tail call void(...) @foo4()
181+
ret void
182+
bb11:
183+
tail call void(...) @foo5()
184+
ret void
185+
bb12:
186+
tail call void(...) @foo6()
187+
ret void
188+
}
189+
190+
declare void @foo1(...)
191+
declare void @foo2(...)
192+
declare void @foo6(...)
193+
declare void @foo3(...)
194+
declare void @foo4(...)
195+
declare void @foo5(...)
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
; RUN: llc < %s -O2 -mtriple=m68k -verify-machineinstrs \
2+
; RUN: -code-model=large -relocation-model=pic \
3+
; RUN: | FileCheck %s
4+
5+
; External Linkage
6+
@a = global i32 0, align 4
7+
8+
define i32 @my_access_global_a() #0 {
9+
; CHECK-LABEL: my_access_global_a:
10+
; CHECK: .cfi_startproc
11+
; CHECK-NEXT: ; %bb.0: ; %entry
12+
; CHECK-NEXT: move.l (a@GOTPCREL,%pc), %a0
13+
; CHECK-NEXT: move.l (%a0), %d0
14+
; CHECK-NEXT: rts
15+
entry:
16+
%0 = load i32, ptr @a, align 4
17+
ret i32 %0
18+
}
19+
20+
; WeakAny Linkage
21+
@b = weak global i32 0, align 4
22+
23+
define i32 @my_access_global_b() #0 {
24+
; CHECK-LABEL: my_access_global_b:
25+
; CHECK: .cfi_startproc
26+
; CHECK-NEXT: ; %bb.0: ; %entry
27+
; CHECK-NEXT: move.l (b@GOTPCREL,%pc), %a0
28+
; CHECK-NEXT: move.l (%a0), %d0
29+
; CHECK-NEXT: rts
30+
entry:
31+
%0 = load i32, ptr @b, align 4
32+
ret i32 %0
33+
}
34+
35+
; Internal Linkage
36+
@c = internal global i32 0, align 4
37+
38+
define i32 @my_access_global_c() #0 {
39+
; CHECK-LABEL: my_access_global_c:
40+
; CHECK: .cfi_startproc
41+
; CHECK-NEXT: ; %bb.0: ; %entry
42+
; CHECK-NEXT: lea (_GLOBAL_OFFSET_TABLE_@GOTPCREL,%pc), %a0
43+
; CHECK-NEXT: move.l #c@GOTOFF, %d0
44+
; CHECK-NEXT: move.l (0,%a0,%d0), %d0
45+
; CHECK-NEXT: rts
46+
entry:
47+
%0 = load i32, ptr @c, align 4
48+
ret i32 %0
49+
}
50+
51+
; External Linkage, only declaration.
52+
@d = external global i32, align 4
53+
54+
define i32 @my_access_global_load_d() #0 {
55+
; CHECK-LABEL: my_access_global_load_d:
56+
; CHECK: .cfi_startproc
57+
; CHECK-NEXT: ; %bb.0: ; %entry
58+
; CHECK-NEXT: move.l (d@GOTPCREL,%pc), %a0
59+
; CHECK-NEXT: move.l (%a0), %d0
60+
; CHECK-NEXT: rts
61+
entry:
62+
%0 = load i32, ptr @d, align 4
63+
ret i32 %0
64+
}
65+
66+
; External Linkage, only declaration, store a value.
67+
define i32 @my_access_global_store_d() #0 {
68+
; CHECK-LABEL: my_access_global_store_d:
69+
; CHECK: .cfi_startproc
70+
; CHECK-NEXT: ; %bb.0: ; %entry
71+
; CHECK-NEXT: move.l (d@GOTPCREL,%pc), %a0
72+
; CHECK-NEXT: move.l #2, (%a0)
73+
; CHECK-NEXT: moveq #0, %d0
74+
; CHECK-NEXT: rts
75+
entry:
76+
store i32 2, ptr @d, align 4
77+
ret i32 0
78+
}
79+
80+
; External Linkage, function pointer access.
81+
declare i32 @access_fp(ptr)
82+
declare i32 @foo()
83+
84+
define i32 @my_access_fp_foo() #0 {
85+
; CHECK-LABEL: my_access_fp_foo:
86+
; CHECK: .cfi_startproc
87+
; CHECK-NEXT: ; %bb.0: ; %entry
88+
; CHECK-NEXT: suba.l #4, %sp
89+
; CHECK-NEXT: .cfi_def_cfa_offset -8
90+
; CHECK-NEXT: move.l (foo@GOTPCREL,%pc), (%sp)
91+
; CHECK-NEXT: jsr (access_fp@PLT,%pc)
92+
; CHECK-NEXT: adda.l #4, %sp
93+
; CHECK-NEXT: rts
94+
entry:
95+
%call = call i32 @access_fp(ptr @foo)
96+
ret i32 %call
97+
}
98+
99+
; LinkOnceODR Linkage, function pointer access.
100+
101+
$bar = comdat any
102+
103+
define linkonce_odr i32 @bar() comdat {
104+
; CHECK-LABEL: bar:
105+
; CHECK: .cfi_startproc
106+
; CHECK-NEXT: ; %bb.0: ; %entry
107+
; CHECK-NEXT: moveq #0, %d0
108+
; CHECK-NEXT: rts
109+
entry:
110+
ret i32 0
111+
}
112+
113+
define i32 @my_access_fp_bar() #0 {
114+
; CHECK-LABEL: my_access_fp_bar:
115+
; CHECK: .cfi_startproc
116+
; CHECK-NEXT: ; %bb.0: ; %entry
117+
; CHECK-NEXT: suba.l #4, %sp
118+
; CHECK-NEXT: .cfi_def_cfa_offset -8
119+
; CHECK-NEXT: move.l (bar@GOTPCREL,%pc), (%sp)
120+
; CHECK-NEXT: jsr (access_fp@PLT,%pc)
121+
; CHECK-NEXT: adda.l #4, %sp
122+
; CHECK-NEXT: rts
123+
entry:
124+
%call = call i32 @access_fp(ptr @bar)
125+
ret i32 %call
126+
}
127+
128+
!llvm.module.flags = !{!0, !1}
129+
!0 = !{i32 1, !"PIC Level", i32 1}
130+
!1 = !{i32 1, !"PIE Level", i32 1}

0 commit comments

Comments
 (0)