@@ -10,6 +10,7 @@ import std.algorithm;
10
10
import callisto.util;
11
11
import callisto.error;
12
12
import callisto.parser;
13
+ import callisto.output;
13
14
import callisto.compiler;
14
15
import callisto.language;
15
16
import callisto.preprocessor;
@@ -51,6 +52,12 @@ class BackendX86_64 : CompilerBackend {
51
52
bool useFramePtr = true ;
52
53
53
54
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
+
54
61
addrSize = 8 ;
55
62
56
63
version (linux ) {
@@ -250,6 +257,10 @@ class BackendX86_64 : CompilerBackend {
250
257
useFramePtr = true ;
251
258
return true ;
252
259
}
260
+ case " use-gas" : {
261
+ useGas = true ;
262
+ return true ;
263
+ }
253
264
default : return false ;
254
265
}
255
266
}
@@ -295,19 +306,41 @@ class BackendX86_64 : CompilerBackend {
295
306
ErrorNoInfo(" Backend doesn't support operating system '%s'" , os);
296
307
}
297
308
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
+ }
299
316
300
317
if (os == " osx" ) {
318
+ if (useGas) {
319
+ ErrorNoInfo(" Cannot use GNU Assembler on x86_64 macOS" );
320
+ }
321
+
301
322
output ~= " default rel\n " ;
302
323
output ~= " global _main\n " ;
303
324
output ~= " _main:\n " ;
304
325
}
305
326
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
+
307
334
output ~= " main:\n " ;
308
335
}
309
336
else {
310
- output ~= " global _start\n " ;
337
+ if (useGas) {
338
+ output ~= " .global _start\n " ;
339
+ }
340
+ else {
341
+ output ~= " global _start\n " ;
342
+ }
343
+
311
344
output ~= " _start:\n " ;
312
345
}
313
346
@@ -325,8 +358,8 @@ class BackendX86_64 : CompilerBackend {
325
358
326
359
// create functions for interop
327
360
if (exportSymbols) {
328
- output ~= "
329
- global cal_push
361
+ output ~= format( "
362
+ %sglobal cal_push
330
363
cal_push:
331
364
mov [r15], rdi
332
365
add r15, 8
@@ -335,7 +368,7 @@ class BackendX86_64 : CompilerBackend {
335
368
sub r15, 8
336
369
mov rax, [r15]
337
370
ret
338
- " ;
371
+ " , useGas? " . " : " " ) ;
339
372
}
340
373
}
341
374
@@ -362,8 +395,8 @@ class BackendX86_64 : CompilerBackend {
362
395
output ~= " __copy_arrays:\n " ;
363
396
364
397
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);
367
400
output ~= format(" mov rcx, %d\n " , array.Size());
368
401
output ~= " rep movsb\n " ;
369
402
}
@@ -381,21 +414,42 @@ class BackendX86_64 : CompilerBackend {
381
414
output ~= " ret\n " ;
382
415
383
416
// 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
+ }
385
423
386
424
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
+ }
388
435
389
436
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
+ );
391
440
}
392
441
}
393
442
394
443
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
+ }
396
450
397
451
if (exportSymbols) {
398
- output ~= format(" global __array_%d\n " , i);
452
+ output ~= format(" %sglobal __array_%d\n " , useGas? " . " : " " , i);
399
453
}
400
454
}
401
455
@@ -405,10 +459,10 @@ class BackendX86_64 : CompilerBackend {
405
459
output ~= format(" __array_src_%d: " , i);
406
460
407
461
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 ;
412
466
default : assert (0 );
413
467
}
414
468
@@ -420,7 +474,8 @@ class BackendX86_64 : CompilerBackend {
420
474
421
475
if (array.global) {
422
476
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" ,
424
479
array.values .length,
425
480
array.type.size,
426
481
i
@@ -617,7 +672,7 @@ class BackendX86_64 : CompilerBackend {
617
672
}
618
673
619
674
if (crash) {
620
- output ~= format(" mov rax, __global_%s\n " , Sanitise(" _cal_exception" ));
675
+ output ~= format(" lea rax, __global_%s\n " , Sanitise(" _cal_exception" ));
621
676
output ~= " cmp qword [rax], 0\n " ;
622
677
output ~= format(" jne __func__%s\n " , Sanitise(" __x86_64_exception" ));
623
678
}
@@ -691,7 +746,7 @@ class BackendX86_64 : CompilerBackend {
691
746
output ~= " mov [r15], r14\n " ;
692
747
}
693
748
else {
694
- output ~= format(" mov qword [r15], %d\n " , node.value);
749
+ output ~= format(" mov qword [r15], qword %d\n " , node.value);
695
750
}
696
751
output ~= " add r15, 8\n " ;
697
752
}
@@ -718,7 +773,7 @@ class BackendX86_64 : CompilerBackend {
718
773
719
774
if (node.inline) {
720
775
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" ));
722
777
output ~= " mov [rax], 0\n " ;
723
778
}
724
779
@@ -750,7 +805,7 @@ class BackendX86_64 : CompilerBackend {
750
805
}
751
806
752
807
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" ));
754
809
output ~= " mov qword [rax], qword 0\n " ;
755
810
}
756
811
@@ -1039,15 +1094,15 @@ class BackendX86_64 : CompilerBackend {
1039
1094
arrays ~= array;
1040
1095
1041
1096
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 );
1043
1098
output ~= " mov qword [r15], rax\n " ;
1044
1099
output ~= " add r15, 8\n " ;
1045
1100
}
1046
1101
else {
1047
1102
// allocate a copy of this array
1048
1103
output ~= format(" sub rsp, %d\n " , array.Size());
1049
1104
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 );
1051
1106
output ~= " mov rdi, rax\n " ;
1052
1107
output ~= format(" mov rcx, %d\n " , array.Size());
1053
1108
output ~= format(" rep movsb\n " );
@@ -1077,8 +1132,8 @@ class BackendX86_64 : CompilerBackend {
1077
1132
1078
1133
output ~= " mov rax, rsp\n " ;
1079
1134
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
1082
1137
output ~= " mov [rsp + 16], rax\n " ; // elements
1083
1138
1084
1139
// push metadata address
@@ -1188,7 +1243,7 @@ class BackendX86_64 : CompilerBackend {
1188
1243
}
1189
1244
1190
1245
if (word.type != WordType.Callisto) {
1191
- output ~= format(" extern %s\n " , ExternSymbol(node.func));
1246
+ output ~= format(" %sextern %s\n " , useGas? " . " : " " , ExternSymbol(node.func));
1192
1247
}
1193
1248
1194
1249
words[funcName] = word;
@@ -1206,7 +1261,7 @@ class BackendX86_64 : CompilerBackend {
1206
1261
string symbol = word.type == WordType.Callisto?
1207
1262
format(" __func__%s" , node.func.Sanitise()) : ExternSymbol(node.func);
1208
1263
1209
- output ~= format(" mov rax, %s\n " , symbol);
1264
+ output ~= format(" lea rax, %s\n " , symbol);
1210
1265
output ~= " mov [r15], rax\n " ;
1211
1266
output ~= " add r15, 8\n " ;
1212
1267
}
@@ -1505,7 +1560,7 @@ class BackendX86_64 : CompilerBackend {
1505
1560
1506
1561
++ blockCounter;
1507
1562
1508
- output ~= format(" mov rax, __global_%s\n " , Sanitise(" _cal_exception" ));
1563
+ output ~= format(" lea rax, __global_%s\n " , Sanitise(" _cal_exception" ));
1509
1564
output ~= " cmp qword [rax], 0\n " ;
1510
1565
output ~= format(" je __catch_%d_end\n " , blockCounter);
1511
1566
@@ -1547,7 +1602,7 @@ class BackendX86_64 : CompilerBackend {
1547
1602
}
1548
1603
1549
1604
// 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" ));
1551
1606
output ~= " mov rax, 0xFFFFFFFFFFFFFFFF\n " ;
1552
1607
output ~= " mov [rbx], rax\n " ;
1553
1608
0 commit comments