Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge main to exceptions #23

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 69 additions & 35 deletions source/backends/arm64.d
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ class BackendARM64 : CompilerBackend {
version (linux) {
defaultOS = "linux";
}
version (OSX) {
defaultOS = "osx";
}
else {
defaultOS = "bare-metal";
WarnNoInfo("Default operating system, defaulting to bare-metal OS");
Expand Down Expand Up @@ -198,6 +201,11 @@ class BackendARM64 : CompilerBackend {
ret ~= ["Linux", "IO", "File", "Args", "Time", "Heap", "Exit"];
break;
}
case "osx": {
ret ~= ["OSX", "IO", "File", "Args", "Time", "Exit"];
if (useLibc) ret ~= "Heap";
break;
}
default: break;
}

Expand Down Expand Up @@ -233,25 +241,31 @@ class BackendARM64 : CompilerBackend {
}

if (useLibc) {
string[] possiblePaths = [
"/usr/aarch64-linux-gnu/lib/crt1.o",
"/usr/lib/crt1.o",
"/usr/lib64/crt1.o",
];
bool crt1;

foreach (ref path ; possiblePaths) {
if (path.exists) {
crt1 = true;
linkCommand ~= format(" %s", path);
linkCommand ~= format(" %s/crti.o", path.dirName);
linkCommand ~= format(" %s/crtn.o", path.dirName);
break;
if (os == "linux") {
string[] possiblePaths = [
"/usr/aarch64-linux-gnu/lib/crt1.o",
"/usr/lib/crt1.o",
"/usr/lib64/crt1.o",
];
bool crt1;

foreach (ref path ; possiblePaths) {
if (path.exists) {
crt1 = true;
linkCommand ~= format(" %s", path);
linkCommand ~= format(" %s/crti.o", path.dirName);
linkCommand ~= format(" %s/crtn.o", path.dirName);
break;
}
}
}

if (!crt1) {
stderr.writeln("WARNING: Failed to find crt1.o, program may behave incorrectly");
if (!crt1) {
stderr.writeln("WARNING: Failed to find crt1.o, program may behave incorrectly");
}
} else if (os == "osx") {
linkCommand ~= " -lSystem -syslibroot `xcrun --sdk macosx --show-sdk-path`";
} else {
WarnNoInfo("Cannot use libc on operating system '%s'", os);
}
}

Expand Down Expand Up @@ -286,7 +300,7 @@ class BackendARM64 : CompilerBackend {
// call constructors
foreach (name, global ; globals) {
if (global.type.hasInit) {
output ~= format("ldr x9, =__global_%s\n", name.Sanitise());
LoadAddress("x9", format("__global_%s", name.Sanitise()));
output ~= "str x9, [x19], #8\n";
output ~= format("bl __type_init_%s\n", global.type.name.Sanitise());
}
Expand All @@ -302,7 +316,7 @@ class BackendARM64 : CompilerBackend {
}
}
else if (word.type == WordType.Raw) {
output ~= format("bl %s\n", name);
output ~= format("bl %s\n", ExternSymbol(name));
}
else if (word.type == WordType.C) {
assert(0); // TODO: error
Expand All @@ -313,13 +327,16 @@ class BackendARM64 : CompilerBackend {
}

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

output ~= ".text\n";
if (useLibc) {
if (os == "osx") {
output ~= ".global _main\n";
output ~= "_main:\n";
} else if (useLibc) {
output ~= ".global main\n";
output ~= "main:\n";
} else {
Expand Down Expand Up @@ -355,7 +372,7 @@ class BackendARM64 : CompilerBackend {
// call destructors
foreach (name, global ; globals) {
if (global.type.hasDeinit) {
output ~= format("ldr x9, =__global_%s\n", name.Sanitise());
LoadAddress("x9", format("__global_%s", name.Sanitise()));
output ~= "str x9, [x19], #8\n";
output ~= format("bl __type_deinit_%s\n", global.type.name.Sanitise());
}
Expand Down Expand Up @@ -395,6 +412,7 @@ class BackendARM64 : CompilerBackend {
// create arrays
output ~= ".data\n";
foreach (i, ref array ; arrays) {
output ~= ".align 8\n";
if (exportSymbols) {
output ~= format(".global __array_%d\n", i);
}
Expand All @@ -416,6 +434,7 @@ class BackendARM64 : CompilerBackend {
output ~= '\n';

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

output ~= format("bl %s\n", word.symbolName);
output ~= format("bl %s\n", ExternSymbol(word.symbolName));

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

string symbol = format("__global_%s", node.name.Sanitise());
output ~= format("ldr x9, =%s\n", symbol);
LoadAddress("x9", format("__global_%s", node.name.Sanitise()));

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

if (!inScope || node.constant) {
output ~= format("ldr x9, =__array_%d_meta\n", arrays.length - 1);
LoadAddress("x9", format("__array_%d_meta", arrays.length - 1));
output ~= "str x9, [x19], #8\n";
}
else {
// allocate a copy of this array
OffsetLocalsStack(array.Size(), true);
output ~= "mov x9, x20\n";
output ~= format("ldr x10, =__array_%d\n", arrays.length - 1);
LoadAddress("x10", format("__array_%d", arrays.length - 1));
output ~= format("ldr x11, =%d\n", array.Size());
output ~= "1:\n";
output ~= "ldrb w12, [x10], #1\n";
Expand Down Expand Up @@ -1060,7 +1078,7 @@ class BackendARM64 : CompilerBackend {
}

if (word.type != WordType.Callisto) {
output ~= format(".extern %s\n", node.func);
output ~= format(".extern %s\n", ExternSymbol(node.func));
}

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

output ~= format("ldr x9, =%s\n", symbol);
LoadAddress("x9", symbol);
output ~= "str x9, [x19], #8\n";
}
else if (node.func in globals) {
auto var = globals[node.func];

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

string symbol = format("__global_%s", node.var.Sanitise());
output ~= format("ldr x10, =%s\n", symbol);
LoadAddress("x10", format("__global_%s", node.var.Sanitise()));

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

void OffsetLocalsStack(size_t offset, bool sub) {
private void OffsetLocalsStack(size_t offset, bool sub) {
if (offset >= 4096) {
output ~= format("mov x9, #%d\n", offset);
output ~= format("%s x20, x20, x9\n", sub ? "sub" : "add");
} else {
output ~= format("%s x20, x20, #%d\n", sub ? "sub" : "add", offset);
}
}

private void LoadAddress(string reg, string symbol) {
if (os == "osx") {
output ~= format("adrp %s, %s@PAGE\n", reg, symbol);
output ~= format("add %s, %s, %s@PAGEOFF\n", reg, reg, symbol);
} else {
output ~= format("ldr %s, =%s\n", reg, symbol);
}
}

private string ExternSymbol(string name) {
if (os == "osx") {
return "_" ~ name;
} else {
return name;
}
}
}
Loading
Loading