@@ -10,6 +10,7 @@ import std.algorithm;
1010import callisto.util;
1111import callisto.error;
1212import callisto.parser;
13+ import callisto.output;
1314import callisto.compiler;
1415import callisto.language;
1516import callisto.preprocessor;
@@ -51,6 +52,12 @@ class BackendX86_64 : CompilerBackend {
5152 bool useFramePtr = true ;
5253
5354 this () {
55+ output = new Output();
56+ output.macros[" QWORD" ] = useGas? " qword ptr" : " qword" ;
57+ output.macros[" DWORD" ] = useGas? " dword ptr" : " dword" ;
58+ output.macros[" WORD" ] = useGas? " word ptr" : " word" ;
59+ output.macros[" BYTE" ] = useGas? " byte ptr" : " byte" ;
60+
5461 addrSize = 8 ;
5562
5663 version (linux ) {
@@ -250,6 +257,10 @@ class BackendX86_64 : CompilerBackend {
250257 useFramePtr = true ;
251258 return true ;
252259 }
260+ case " use-gas" : {
261+ useGas = true ;
262+ return true ;
263+ }
253264 default : return false ;
254265 }
255266 }
@@ -295,19 +306,41 @@ class BackendX86_64 : CompilerBackend {
295306 ErrorNoInfo(" Backend doesn't support operating system '%s'" , os);
296307 }
297308
298- output ~= " section .text\n " ;
309+ if (useGas) {
310+ output ~= " .intel_syntax noprefix\n " ;
311+ output ~= " .section .text\n " ;
312+ }
313+ else {
314+ output ~= " section .text\n " ;
315+ }
299316
300317 if (os == " osx" ) {
318+ if (useGas) {
319+ ErrorNoInfo(" Cannot use GNU Assembler on x86_64 macOS" );
320+ }
321+
301322 output ~= " default rel\n " ;
302323 output ~= " global _main\n " ;
303324 output ~= " _main:\n " ;
304325 }
305326 else if (useLibc) {
306- output ~= " global main\n " ;
327+ if (useGas) {
328+ output ~= " .global main\n " ;
329+ }
330+ else {
331+ output ~= " global main\n " ;
332+ }
333+
307334 output ~= " main:\n " ;
308335 }
309336 else {
310- output ~= " global _start\n " ;
337+ if (useGas) {
338+ output ~= " .global _start\n " ;
339+ }
340+ else {
341+ output ~= " global _start\n " ;
342+ }
343+
311344 output ~= " _start:\n " ;
312345 }
313346
@@ -325,8 +358,8 @@ class BackendX86_64 : CompilerBackend {
325358
326359 // create functions for interop
327360 if (exportSymbols) {
328- output ~= "
329- global cal_push
361+ output ~= format( "
362+ %sglobal cal_push
330363 cal_push:
331364 mov [r15], rdi
332365 add r15, 8
@@ -335,7 +368,7 @@ class BackendX86_64 : CompilerBackend {
335368 sub r15, 8
336369 mov rax, [r15]
337370 ret
338- " ;
371+ " , useGas? " . " : " " ) ;
339372 }
340373 }
341374
@@ -362,8 +395,8 @@ class BackendX86_64 : CompilerBackend {
362395 output ~= " __copy_arrays:\n " ;
363396
364397 foreach (i, ref array ; arrays) {
365- output ~= format(" mov rsi, __array_src_%d\n " , i);
366- output ~= format(" mov rdi, __array_%d\n " , i);
398+ output ~= format(" lea rsi, __array_src_%d\n " , i);
399+ output ~= format(" lea rdi, __array_%d\n " , i);
367400 output ~= format(" mov rcx, %d\n " , array.Size());
368401 output ~= " rep movsb\n " ;
369402 }
@@ -381,21 +414,42 @@ class BackendX86_64 : CompilerBackend {
381414 output ~= " ret\n " ;
382415
383416 // create global variables
384- output ~= " section .bss\n " ;
417+ if (useGas) {
418+ output ~= " .section .bss\n " ;
419+ }
420+ else {
421+ output ~= " section .bss\n " ;
422+ }
385423
386424 foreach (var ; globals) {
387- output ~= format(" __global_%s: resb %d\n " , var.name.Sanitise(), var.Size());
425+ if (useGas) {
426+ output ~= format(
427+ " __global_%s: .skip %d\n " , var.name.Sanitise(), var.Size()
428+ );
429+ }
430+ else {
431+ output ~= format(
432+ " __global_%s: resb %d\n " , var.name.Sanitise(), var.Size()
433+ );
434+ }
388435
389436 if (exportSymbols) {
390- output ~= format(" global __global_%s\n " , var.name.Sanitise());
437+ output ~= format(
438+ " %sglobal __global_%s\n " , useGas? " ." : " " , var.name.Sanitise()
439+ );
391440 }
392441 }
393442
394443 foreach (i, ref array ; arrays) {
395- output ~= format(" __array_%d: resb %d\n " , i, array.Size());
444+ if (useGas) {
445+ output ~= format(" __array_%d: skip %d\n " , i, array.Size());
446+ }
447+ else {
448+ output ~= format(" __array_%d: resb %d\n " , i, array.Size());
449+ }
396450
397451 if (exportSymbols) {
398- output ~= format(" global __array_%d\n " , i);
452+ output ~= format(" %sglobal __array_%d\n " , useGas? " . " : " " , i);
399453 }
400454 }
401455
@@ -405,10 +459,10 @@ class BackendX86_64 : CompilerBackend {
405459 output ~= format(" __array_src_%d: " , i);
406460
407461 switch (array.type.size) {
408- case 1 : output ~= " db " ; break ;
409- case 2 : output ~= " dw " ; break ;
410- case 4 : output ~= " dd " ; break ;
411- case 8 : output ~= " dq " ; break ;
462+ case 1 : output ~= useGas? " .byte " : " db " ; break ;
463+ case 2 : output ~= useGas? " .word " : " dw " ; break ;
464+ case 4 : output ~= useGas? " .long " : " dd " ; break ;
465+ case 8 : output ~= useGas? " .quad " : " dq " ; break ;
412466 default : assert (0 );
413467 }
414468
@@ -420,7 +474,8 @@ class BackendX86_64 : CompilerBackend {
420474
421475 if (array.global) {
422476 output ~= format(
423- " __array_%d_meta: dq %d, %d, __array_%d\n " , i,
477+ " __array_%d_meta: %s %d, %d, __array_%d\n " , i,
478+ useGas? " .quad" : " dq" ,
424479 array.values .length,
425480 array.type.size,
426481 i
@@ -617,7 +672,7 @@ class BackendX86_64 : CompilerBackend {
617672 }
618673
619674 if (crash) {
620- output ~= format(" mov rax, __global_%s\n " , Sanitise(" _cal_exception" ));
675+ output ~= format(" lea rax, __global_%s\n " , Sanitise(" _cal_exception" ));
621676 output ~= " cmp qword [rax], 0\n " ;
622677 output ~= format(" jne __func__%s\n " , Sanitise(" __x86_64_exception" ));
623678 }
@@ -691,7 +746,7 @@ class BackendX86_64 : CompilerBackend {
691746 output ~= " mov [r15], r14\n " ;
692747 }
693748 else {
694- output ~= format(" mov qword [r15], %d\n " , node.value);
749+ output ~= format(" mov qword [r15], qword %d\n " , node.value);
695750 }
696751 output ~= " add r15, 8\n " ;
697752 }
@@ -718,7 +773,7 @@ class BackendX86_64 : CompilerBackend {
718773
719774 if (node.inline) {
720775 if (node.errors) {
721- output ~= format(" mov rax, __global_%s\n " , Sanitise(" _cal_exception" ));
776+ output ~= format(" lea rax, __global_%s\n " , Sanitise(" _cal_exception" ));
722777 output ~= " mov [rax], 0\n " ;
723778 }
724779
@@ -750,7 +805,7 @@ class BackendX86_64 : CompilerBackend {
750805 }
751806
752807 if (node.errors) {
753- output ~= format(" mov rax, __global_%s\n " , Sanitise(" _cal_exception" ));
808+ output ~= format(" lea rax, __global_%s\n " , Sanitise(" _cal_exception" ));
754809 output ~= " mov qword [rax], qword 0\n " ;
755810 }
756811
@@ -1039,15 +1094,15 @@ class BackendX86_64 : CompilerBackend {
10391094 arrays ~= array;
10401095
10411096 if (! inScope || node.constant) {
1042- output ~= format(" mov rax, __array_%d_meta\n " , arrays.length - 1 );
1097+ output ~= format(" lea rax, __array_%d_meta\n " , arrays.length - 1 );
10431098 output ~= " mov qword [r15], rax\n " ;
10441099 output ~= " add r15, 8\n " ;
10451100 }
10461101 else {
10471102 // allocate a copy of this array
10481103 output ~= format(" sub rsp, %d\n " , array.Size());
10491104 output ~= " mov rax, rsp\n " ;
1050- output ~= format(" mov rsi, __array_%d\n " , arrays.length - 1 );
1105+ output ~= format(" lea rsi, __array_%d\n " , arrays.length - 1 );
10511106 output ~= " mov rdi, rax\n " ;
10521107 output ~= format(" mov rcx, %d\n " , array.Size());
10531108 output ~= format(" rep movsb\n " );
@@ -1077,8 +1132,8 @@ class BackendX86_64 : CompilerBackend {
10771132
10781133 output ~= " mov rax, rsp\n " ;
10791134 output ~= format(" sub rsp, %d\n " , 8 * 3 ); // size of Array structure
1080- output ~= format(" mov qword [rsp], %d\n " , array.values .length); // length
1081- output ~= format(" mov qword [rsp + 8], %d\n " , array.type.size); // member size
1135+ output ~= format(" mov qword [rsp], qword %d\n " , array.values .length); // length
1136+ output ~= format(" mov qword [rsp + 8], qword %d\n " , array.type.size); // member size
10821137 output ~= " mov [rsp + 16], rax\n " ; // elements
10831138
10841139 // push metadata address
@@ -1188,7 +1243,7 @@ class BackendX86_64 : CompilerBackend {
11881243 }
11891244
11901245 if (word.type != WordType.Callisto) {
1191- output ~= format(" extern %s\n " , ExternSymbol(node.func));
1246+ output ~= format(" %sextern %s\n " , useGas? " . " : " " , ExternSymbol(node.func));
11921247 }
11931248
11941249 words[funcName] = word;
@@ -1206,7 +1261,7 @@ class BackendX86_64 : CompilerBackend {
12061261 string symbol = word.type == WordType.Callisto?
12071262 format(" __func__%s" , node.func.Sanitise()) : ExternSymbol(node.func);
12081263
1209- output ~= format(" mov rax, %s\n " , symbol);
1264+ output ~= format(" lea rax, %s\n " , symbol);
12101265 output ~= " mov [r15], rax\n " ;
12111266 output ~= " add r15, 8\n " ;
12121267 }
@@ -1505,7 +1560,7 @@ class BackendX86_64 : CompilerBackend {
15051560
15061561 ++ blockCounter;
15071562
1508- output ~= format(" mov rax, __global_%s\n " , Sanitise(" _cal_exception" ));
1563+ output ~= format(" lea rax, __global_%s\n " , Sanitise(" _cal_exception" ));
15091564 output ~= " cmp qword [rax], 0\n " ;
15101565 output ~= format(" je __catch_%d_end\n " , blockCounter);
15111566
@@ -1547,7 +1602,7 @@ class BackendX86_64 : CompilerBackend {
15471602 }
15481603
15491604 // set exception error
1550- output ~= format(" mov rbx, __global_%s\n " , Sanitise(" _cal_exception" ));
1605+ output ~= format(" lea rbx, __global_%s\n " , Sanitise(" _cal_exception" ));
15511606 output ~= " mov rax, 0xFFFFFFFFFFFFFFFF\n " ;
15521607 output ~= " mov [rbx], rax\n " ;
15531608
0 commit comments