Skip to content

Commit fdc431a

Browse files
committed
merge
2 parents ccf040e + 2088051 commit fdc431a

File tree

2 files changed

+125
-68
lines changed

2 files changed

+125
-68
lines changed

source/backends/arm64.d

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ class BackendARM64 : CompilerBackend {
9797
version (linux) {
9898
defaultOS = "linux";
9999
}
100+
version (OSX) {
101+
defaultOS = "osx";
102+
}
100103
else {
101104
defaultOS = "bare-metal";
102105
WarnNoInfo("Default operating system, defaulting to bare-metal OS");
@@ -201,6 +204,11 @@ class BackendARM64 : CompilerBackend {
201204
ret ~= ["Linux", "IO", "File", "Args", "Time", "Heap", "Exit"];
202205
break;
203206
}
207+
case "osx": {
208+
ret ~= ["OSX", "IO", "File", "Args", "Time", "Exit"];
209+
if (useLibc) ret ~= "Heap";
210+
break;
211+
}
204212
default: break;
205213
}
206214

@@ -241,25 +249,31 @@ class BackendARM64 : CompilerBackend {
241249
}
242250

243251
if (useLibc) {
244-
string[] possiblePaths = [
245-
"/usr/aarch64-linux-gnu/lib/crt1.o",
246-
"/usr/lib/crt1.o",
247-
"/usr/lib64/crt1.o",
248-
];
249-
bool crt1;
250-
251-
foreach (ref path ; possiblePaths) {
252-
if (path.exists) {
253-
crt1 = true;
254-
linkCommand ~= format(" %s", path);
255-
linkCommand ~= format(" %s/crti.o", path.dirName);
256-
linkCommand ~= format(" %s/crtn.o", path.dirName);
257-
break;
252+
if (os == "linux") {
253+
string[] possiblePaths = [
254+
"/usr/aarch64-linux-gnu/lib/crt1.o",
255+
"/usr/lib/crt1.o",
256+
"/usr/lib64/crt1.o",
257+
];
258+
bool crt1;
259+
260+
foreach (ref path ; possiblePaths) {
261+
if (path.exists) {
262+
crt1 = true;
263+
linkCommand ~= format(" %s", path);
264+
linkCommand ~= format(" %s/crti.o", path.dirName);
265+
linkCommand ~= format(" %s/crtn.o", path.dirName);
266+
break;
267+
}
258268
}
259-
}
260269

261-
if (!crt1) {
262-
stderr.writeln("WARNING: Failed to find crt1.o, program may behave incorrectly");
270+
if (!crt1) {
271+
stderr.writeln("WARNING: Failed to find crt1.o, program may behave incorrectly");
272+
}
273+
} else if (os == "osx") {
274+
linkCommand ~= " -lSystem -syslibroot `xcrun --sdk macosx --show-sdk-path`";
275+
} else {
276+
WarnNoInfo("Cannot use libc on operating system '%s'", os);
263277
}
264278
}
265279

@@ -294,7 +308,7 @@ class BackendARM64 : CompilerBackend {
294308
// call constructors
295309
foreach (name, global ; globals) {
296310
if (global.type.hasInit) {
297-
output ~= format("ldr x9, =__global_%s\n", name.Sanitise());
311+
LoadAddress("x9", format("__global_%s", name.Sanitise()));
298312
output ~= "str x9, [x19], #8\n";
299313
output ~= format("bl __type_init_%s\n", global.type.name.Sanitise());
300314
}
@@ -310,7 +324,7 @@ class BackendARM64 : CompilerBackend {
310324
}
311325
}
312326
else if (word.type == WordType.Raw) {
313-
output ~= format("bl %s\n", name);
327+
output ~= format("bl %s\n", ExternSymbol(name));
314328
}
315329
else if (word.type == WordType.C) {
316330
assert(0); // TODO: error
@@ -321,13 +335,16 @@ class BackendARM64 : CompilerBackend {
321335
}
322336

323337
override void Init() {
324-
string[] oses = ["linux", "bare-metal"];
338+
string[] oses = ["linux", "osx", "bare-metal"];
325339
if (!oses.canFind(os)) {
326340
ErrorNoInfo("Backend doesn't support operating system '%s'", os);
327341
}
328342

329343
output ~= ".text\n";
330-
if (useLibc) {
344+
if (os == "osx") {
345+
output ~= ".global _main\n";
346+
output ~= "_main:\n";
347+
} else if (useLibc) {
331348
output ~= ".global main\n";
332349
output ~= "main:\n";
333350
} else {
@@ -363,7 +380,7 @@ class BackendARM64 : CompilerBackend {
363380
// call destructors
364381
foreach (name, global ; globals) {
365382
if (global.type.hasDeinit) {
366-
output ~= format("ldr x9, =__global_%s\n", name.Sanitise());
383+
LoadAddress("x9", format("__global_%s", name.Sanitise()));
367384
output ~= "str x9, [x19], #8\n";
368385
output ~= format("bl __type_deinit_%s\n", global.type.name.Sanitise());
369386
}
@@ -403,6 +420,7 @@ class BackendARM64 : CompilerBackend {
403420
// create arrays
404421
output ~= ".data\n";
405422
foreach (i, ref array ; arrays) {
423+
output ~= ".align 8\n";
406424
if (exportSymbols) {
407425
output ~= format(".global __array_%d\n", i);
408426
}
@@ -424,6 +442,7 @@ class BackendARM64 : CompilerBackend {
424442
output ~= '\n';
425443

426444
if (array.global) {
445+
output ~= ".align 8\n";
427446
output ~= format(
428447
"__array_%d_meta: .8byte %d, %d, __array_%d\n", i,
429448
array.values.length,
@@ -445,7 +464,7 @@ class BackendARM64 : CompilerBackend {
445464
}
446465
else {
447466
if (word.type == WordType.Raw) {
448-
output ~= format("bl %s\n", node.name);
467+
output ~= format("bl %s\n", ExternSymbol(node.name));
449468
}
450469
else if (word.type == WordType.C) {
451470
// TODO: support more of the calling convention (especially structs)
@@ -459,7 +478,7 @@ class BackendARM64 : CompilerBackend {
459478
output ~= format("ldr x%d, [x19, #-8]!\n", reg);
460479
}
461480

462-
output ~= format("bl %s\n", word.symbolName);
481+
output ~= format("bl %s\n", ExternSymbol(word.symbolName));
463482

464483
if (!word.isVoid) {
465484
output ~= "str x0, [x19], #8\n";
@@ -520,8 +539,7 @@ class BackendARM64 : CompilerBackend {
520539
Error(node.error, "Can't push value of struct");
521540
}
522541

523-
string symbol = format("__global_%s", node.name.Sanitise());
524-
output ~= format("ldr x9, =%s\n", symbol);
542+
LoadAddress("x9", format("__global_%s", node.name.Sanitise()));
525543

526544
switch (var.type.size) {
527545
case 1: output ~= "ldrb w9, [x9]\n"; break;
@@ -848,14 +866,14 @@ class BackendARM64 : CompilerBackend {
848866
arrays ~= array;
849867

850868
if (!inScope || node.constant) {
851-
output ~= format("ldr x9, =__array_%d_meta\n", arrays.length - 1);
869+
LoadAddress("x9", format("__array_%d_meta", arrays.length - 1));
852870
output ~= "str x9, [x19], #8\n";
853871
}
854872
else {
855873
// allocate a copy of this array
856874
OffsetLocalsStack(array.Size(), true);
857875
output ~= "mov x9, x20\n";
858-
output ~= format("ldr x10, =__array_%d\n", arrays.length - 1);
876+
LoadAddress("x10", format("__array_%d", arrays.length - 1));
859877
output ~= format("ldr x11, =%d\n", array.Size());
860878
output ~= "1:\n";
861879
output ~= "ldrb w12, [x10], #1\n";
@@ -1110,7 +1128,7 @@ class BackendARM64 : CompilerBackend {
11101128
}
11111129

11121130
if (word.type != WordType.Callisto) {
1113-
output ~= format(".extern %s\n", node.func);
1131+
output ~= format(".extern %s\n", ExternSymbol(node.func));
11141132
}
11151133

11161134
words[funcName] = word;
@@ -1125,15 +1143,15 @@ class BackendARM64 : CompilerBackend {
11251143
if (node.func in words) {
11261144
auto word = words[node.func];
11271145
string symbol = word.type == WordType.Callisto?
1128-
format("__func__%s", node.func.Sanitise()) : node.func;
1146+
format("__func__%s", node.func.Sanitise()) : ExternSymbol(node.func);
11291147

1130-
output ~= format("ldr x9, =%s\n", symbol);
1148+
LoadAddress("x9", symbol);
11311149
output ~= "str x9, [x19], #8\n";
11321150
}
11331151
else if (node.func in globals) {
11341152
auto var = globals[node.func];
11351153

1136-
output ~= format("ldr x9, =__global_%s\n", node.func.Sanitise());
1154+
LoadAddress("x9", format("__global_%s", node.func.Sanitise()));
11371155
output ~= "str x9, [x19], #8\n";
11381156
}
11391157
else if (VariableExists(node.func)) {
@@ -1234,8 +1252,7 @@ class BackendARM64 : CompilerBackend {
12341252
Error(node.error, "Can't set struct value");
12351253
}
12361254

1237-
string symbol = format("__global_%s", node.var.Sanitise());
1238-
output ~= format("ldr x10, =%s\n", symbol);
1255+
LoadAddress("x10", format("__global_%s", node.var.Sanitise()));
12391256

12401257
switch (global.type.size) {
12411258
case 1: output ~= "strb w9, [x10]\n"; break;
@@ -1250,7 +1267,7 @@ class BackendARM64 : CompilerBackend {
12501267
}
12511268
}
12521269

1253-
void OffsetLocalsStack(size_t offset, bool sub) {
1270+
private void OffsetLocalsStack(size_t offset, bool sub) {
12541271
if (offset >= 4096) {
12551272
output ~= format("mov x9, #%d\n", offset);
12561273
output ~= format("%s x20, x20, x9\n", sub ? "sub" : "add");
@@ -1259,7 +1276,6 @@ class BackendARM64 : CompilerBackend {
12591276
}
12601277
}
12611278

1262-
12631279
override void CompileTryCatch(TryCatchNode node) {
12641280
if (node.func !in words) {
12651281
Error(node.error, "Function '%s' doesn't exist", node.func);
@@ -1344,4 +1360,23 @@ class BackendARM64 : CompilerBackend {
13441360

13451361
CompileReturn(node);
13461362
}
1363+
1364+
private void LoadAddress(string reg, string symbol) {
1365+
if (os == "osx") {
1366+
output ~= format("adrp %s, %s@PAGE\n", reg, symbol);
1367+
output ~= format("add %s, %s, %s@PAGEOFF\n", reg, reg, symbol);
1368+
}
1369+
else {
1370+
output ~= format("ldr %s, =%s\n", reg, symbol);
1371+
}
1372+
}
1373+
1374+
private string ExternSymbol(string name) {
1375+
if (os == "osx") {
1376+
return "_" ~ name;
1377+
}
1378+
else {
1379+
return name;
1380+
}
1381+
}
13471382
}

0 commit comments

Comments
 (0)