@@ -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