Skip to content

Commit 2088051

Browse files
authored
Merge pull request #22 from soxfox42/arm64-mac
arm64 macOS support + extended x86_64 macOS support
2 parents a5634ab + e4cd02a commit 2088051

File tree

3 files changed

+123
-68
lines changed

3 files changed

+123
-68
lines changed

source/backends/arm64.d

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ class BackendARM64 : CompilerBackend {
9696
version (linux) {
9797
defaultOS = "linux";
9898
}
99+
version (OSX) {
100+
defaultOS = "osx";
101+
}
99102
else {
100103
defaultOS = "bare-metal";
101104
WarnNoInfo("Default operating system, defaulting to bare-metal OS");
@@ -198,6 +201,11 @@ class BackendARM64 : CompilerBackend {
198201
ret ~= ["Linux", "IO", "File", "Args", "Time", "Heap", "Exit"];
199202
break;
200203
}
204+
case "osx": {
205+
ret ~= ["OSX", "IO", "File", "Args", "Time", "Exit"];
206+
if (useLibc) ret ~= "Heap";
207+
break;
208+
}
201209
default: break;
202210
}
203211

@@ -233,25 +241,31 @@ class BackendARM64 : CompilerBackend {
233241
}
234242

235243
if (useLibc) {
236-
string[] possiblePaths = [
237-
"/usr/aarch64-linux-gnu/lib/crt1.o",
238-
"/usr/lib/crt1.o",
239-
"/usr/lib64/crt1.o",
240-
];
241-
bool crt1;
242-
243-
foreach (ref path ; possiblePaths) {
244-
if (path.exists) {
245-
crt1 = true;
246-
linkCommand ~= format(" %s", path);
247-
linkCommand ~= format(" %s/crti.o", path.dirName);
248-
linkCommand ~= format(" %s/crtn.o", path.dirName);
249-
break;
244+
if (os == "linux") {
245+
string[] possiblePaths = [
246+
"/usr/aarch64-linux-gnu/lib/crt1.o",
247+
"/usr/lib/crt1.o",
248+
"/usr/lib64/crt1.o",
249+
];
250+
bool crt1;
251+
252+
foreach (ref path ; possiblePaths) {
253+
if (path.exists) {
254+
crt1 = true;
255+
linkCommand ~= format(" %s", path);
256+
linkCommand ~= format(" %s/crti.o", path.dirName);
257+
linkCommand ~= format(" %s/crtn.o", path.dirName);
258+
break;
259+
}
250260
}
251-
}
252261

253-
if (!crt1) {
254-
stderr.writeln("WARNING: Failed to find crt1.o, program may behave incorrectly");
262+
if (!crt1) {
263+
stderr.writeln("WARNING: Failed to find crt1.o, program may behave incorrectly");
264+
}
265+
} else if (os == "osx") {
266+
linkCommand ~= " -lSystem -syslibroot `xcrun --sdk macosx --show-sdk-path`";
267+
} else {
268+
WarnNoInfo("Cannot use libc on operating system '%s'", os);
255269
}
256270
}
257271

@@ -286,7 +300,7 @@ class BackendARM64 : CompilerBackend {
286300
// call constructors
287301
foreach (name, global ; globals) {
288302
if (global.type.hasInit) {
289-
output ~= format("ldr x9, =__global_%s\n", name.Sanitise());
303+
LoadAddress("x9", format("__global_%s", name.Sanitise()));
290304
output ~= "str x9, [x19], #8\n";
291305
output ~= format("bl __type_init_%s\n", global.type.name.Sanitise());
292306
}
@@ -302,7 +316,7 @@ class BackendARM64 : CompilerBackend {
302316
}
303317
}
304318
else if (word.type == WordType.Raw) {
305-
output ~= format("bl %s\n", name);
319+
output ~= format("bl %s\n", ExternSymbol(name));
306320
}
307321
else if (word.type == WordType.C) {
308322
assert(0); // TODO: error
@@ -313,13 +327,16 @@ class BackendARM64 : CompilerBackend {
313327
}
314328

315329
override void Init() {
316-
string[] oses = ["linux", "bare-metal"];
330+
string[] oses = ["linux", "osx", "bare-metal"];
317331
if (!oses.canFind(os)) {
318332
ErrorNoInfo("Backend doesn't support operating system '%s'", os);
319333
}
320334

321335
output ~= ".text\n";
322-
if (useLibc) {
336+
if (os == "osx") {
337+
output ~= ".global _main\n";
338+
output ~= "_main:\n";
339+
} else if (useLibc) {
323340
output ~= ".global main\n";
324341
output ~= "main:\n";
325342
} else {
@@ -355,7 +372,7 @@ class BackendARM64 : CompilerBackend {
355372
// call destructors
356373
foreach (name, global ; globals) {
357374
if (global.type.hasDeinit) {
358-
output ~= format("ldr x9, =__global_%s\n", name.Sanitise());
375+
LoadAddress("x9", format("__global_%s", name.Sanitise()));
359376
output ~= "str x9, [x19], #8\n";
360377
output ~= format("bl __type_deinit_%s\n", global.type.name.Sanitise());
361378
}
@@ -395,6 +412,7 @@ class BackendARM64 : CompilerBackend {
395412
// create arrays
396413
output ~= ".data\n";
397414
foreach (i, ref array ; arrays) {
415+
output ~= ".align 8\n";
398416
if (exportSymbols) {
399417
output ~= format(".global __array_%d\n", i);
400418
}
@@ -416,6 +434,7 @@ class BackendARM64 : CompilerBackend {
416434
output ~= '\n';
417435

418436
if (array.global) {
437+
output ~= ".align 8\n";
419438
output ~= format(
420439
"__array_%d_meta: .8byte %d, %d, __array_%d\n", i,
421440
array.values.length,
@@ -437,7 +456,7 @@ class BackendARM64 : CompilerBackend {
437456
}
438457
else {
439458
if (word.type == WordType.Raw) {
440-
output ~= format("bl %s\n", node.name);
459+
output ~= format("bl %s\n", ExternSymbol(node.name));
441460
}
442461
else if (word.type == WordType.C) {
443462
// TODO: support more of the calling convention (especially structs)
@@ -451,7 +470,7 @@ class BackendARM64 : CompilerBackend {
451470
output ~= format("ldr x%d, [x19, #-8]!\n", reg);
452471
}
453472

454-
output ~= format("bl %s\n", word.symbolName);
473+
output ~= format("bl %s\n", ExternSymbol(word.symbolName));
455474

456475
if (!word.isVoid) {
457476
output ~= "str x0, [x19], #8\n";
@@ -486,8 +505,7 @@ class BackendARM64 : CompilerBackend {
486505
Error(node.error, "Can't push value of struct");
487506
}
488507

489-
string symbol = format("__global_%s", node.name.Sanitise());
490-
output ~= format("ldr x9, =%s\n", symbol);
508+
LoadAddress("x9", format("__global_%s", node.name.Sanitise()));
491509

492510
switch (var.type.size) {
493511
case 1: output ~= "ldrb w9, [x9]\n"; break;
@@ -798,14 +816,14 @@ class BackendARM64 : CompilerBackend {
798816
arrays ~= array;
799817

800818
if (!inScope || node.constant) {
801-
output ~= format("ldr x9, =__array_%d_meta\n", arrays.length - 1);
819+
LoadAddress("x9", format("__array_%d_meta", arrays.length - 1));
802820
output ~= "str x9, [x19], #8\n";
803821
}
804822
else {
805823
// allocate a copy of this array
806824
OffsetLocalsStack(array.Size(), true);
807825
output ~= "mov x9, x20\n";
808-
output ~= format("ldr x10, =__array_%d\n", arrays.length - 1);
826+
LoadAddress("x10", format("__array_%d", arrays.length - 1));
809827
output ~= format("ldr x11, =%d\n", array.Size());
810828
output ~= "1:\n";
811829
output ~= "ldrb w12, [x10], #1\n";
@@ -1060,7 +1078,7 @@ class BackendARM64 : CompilerBackend {
10601078
}
10611079

10621080
if (word.type != WordType.Callisto) {
1063-
output ~= format(".extern %s\n", node.func);
1081+
output ~= format(".extern %s\n", ExternSymbol(node.func));
10641082
}
10651083

10661084
words[funcName] = word;
@@ -1075,15 +1093,15 @@ class BackendARM64 : CompilerBackend {
10751093
if (node.func in words) {
10761094
auto word = words[node.func];
10771095
string symbol = word.type == WordType.Callisto?
1078-
format("__func__%s", node.func.Sanitise()) : node.func;
1096+
format("__func__%s", node.func.Sanitise()) : ExternSymbol(node.func);
10791097

1080-
output ~= format("ldr x9, =%s\n", symbol);
1098+
LoadAddress("x9", symbol);
10811099
output ~= "str x9, [x19], #8\n";
10821100
}
10831101
else if (node.func in globals) {
10841102
auto var = globals[node.func];
10851103

1086-
output ~= format("ldr x9, =__global_%s\n", node.func.Sanitise());
1104+
LoadAddress("x9", format("__global_%s", node.func.Sanitise()));
10871105
output ~= "str x9, [x19], #8\n";
10881106
}
10891107
else if (VariableExists(node.func)) {
@@ -1184,8 +1202,7 @@ class BackendARM64 : CompilerBackend {
11841202
Error(node.error, "Can't set struct value");
11851203
}
11861204

1187-
string symbol = format("__global_%s", node.var.Sanitise());
1188-
output ~= format("ldr x10, =%s\n", symbol);
1205+
LoadAddress("x10", format("__global_%s", node.var.Sanitise()));
11891206

11901207
switch (global.type.size) {
11911208
case 1: output ~= "strb w9, [x10]\n"; break;
@@ -1200,12 +1217,29 @@ class BackendARM64 : CompilerBackend {
12001217
}
12011218
}
12021219

1203-
void OffsetLocalsStack(size_t offset, bool sub) {
1220+
private void OffsetLocalsStack(size_t offset, bool sub) {
12041221
if (offset >= 4096) {
12051222
output ~= format("mov x9, #%d\n", offset);
12061223
output ~= format("%s x20, x20, x9\n", sub ? "sub" : "add");
12071224
} else {
12081225
output ~= format("%s x20, x20, #%d\n", sub ? "sub" : "add", offset);
12091226
}
12101227
}
1228+
1229+
private void LoadAddress(string reg, string symbol) {
1230+
if (os == "osx") {
1231+
output ~= format("adrp %s, %s@PAGE\n", reg, symbol);
1232+
output ~= format("add %s, %s, %s@PAGEOFF\n", reg, reg, symbol);
1233+
} else {
1234+
output ~= format("ldr %s, =%s\n", reg, symbol);
1235+
}
1236+
}
1237+
1238+
private string ExternSymbol(string name) {
1239+
if (os == "osx") {
1240+
return "_" ~ name;
1241+
} else {
1242+
return name;
1243+
}
1244+
}
12111245
}

0 commit comments

Comments
 (0)