@@ -43,6 +43,8 @@ class BackendARM64 : CompilerBackend {
4343 bool useLibc;
4444
4545 this () {
46+ addrSize = 8 ;
47+
4648 version (linux ) {
4749 defaultOS = " linux" ;
4850 }
@@ -363,17 +365,20 @@ class BackendARM64 : CompilerBackend {
363365 }
364366 }
365367
366- void PushGlobalValue (Node node, Global var, size_t size = 0 , size_t offset = 0 , bool member = false ) {
368+ void PushGlobalValue (
369+ Node node, Global var, size_t size = 0 , size_t offset = 0 ,
370+ bool member = false , bool deref = false
371+ ) {
367372 if (size == 0 ) {
368- size = var.type.size;
369- }
370-
371- if (var.type.isStruct && ! member) {
372- Error(node.error, " Can't push value of struct" );
373+ size = var.type.Size();
373374 }
374375
375376 LoadAddress(" x9" , format(" __global_%s" , var.name.Sanitise()));
376377
378+ if (deref) {
379+ output ~= " ldr x9, [x9]\n " ;
380+ }
381+
377382 switch (size) {
378383 case 1 : output ~= format(" ldrb w9, [x9, #%d]\n " , offset); break ;
379384 case 2 : output ~= format(" ldrh w9, [x9, #%d]\n " , offset); break ;
@@ -385,22 +390,32 @@ class BackendARM64 : CompilerBackend {
385390 output ~= " str x9, [x19], #8\n " ;
386391 }
387392
388- void PushVariableValue (Node node, Variable var, size_t size = 0 , size_t offset = 0 , bool member = false ) {
393+ void PushVariableValue (
394+ Node node, Variable var, size_t size = 0 , size_t offset = 0 ,
395+ bool member = false , bool deref = false
396+ ) {
389397 if (size == 0 ) {
390- size = var.type.size ;
398+ size = var.type.Size() ;
391399 }
392400
393401 if (var.type.isStruct && ! member) {
394402 Error(node.error, " Can't push value of struct" );
395403 }
396404
397- offset += var.offset;
405+ string base;
406+ if (deref) {
407+ output ~= format(" ldr x9, [x20, #%d]\n " , var.offset);
408+ base = " x9" ;
409+ } else {
410+ offset += var.offset;
411+ base = " x20" ;
412+ }
398413
399414 switch (size) {
400- case 1 : output ~= format(" ldrb w9, [x20 , #%d]\n " , offset); break ;
401- case 2 : output ~= format(" ldrh w9, [x20 , #%d]\n " , offset); break ;
402- case 4 : output ~= format(" ldr w9, [x20 , #%d]\n " , offset); break ;
403- case 8 : output ~= format(" ldr x9, [x20 , #%d]\n " , offset); break ;
415+ case 1 : output ~= format(" ldrb w9, [%s , #%d]\n " , base , offset); break ;
416+ case 2 : output ~= format(" ldrh w9, [%s , #%d]\n " , base , offset); break ;
417+ case 4 : output ~= format(" ldr w9, [%s , #%d]\n " , base , offset); break ;
418+ case 8 : output ~= format(" ldr x9, [%s , #%d]\n " , base , offset); break ;
404419 default : Error (node.error, " Bad variable type size" );
405420 }
406421
@@ -533,20 +548,30 @@ class BackendARM64 : CompilerBackend {
533548 }
534549 }
535550 else if (VariableExists(node.name)) {
536- PushVariableValue(node, GetVariable (node.name));
551+ auto var = GetVariable(node.name);
552+ if (var.type.isStruct && ! var.type.ptr) {
553+ Error(node.error, " Can't push struct value" );
554+ }
555+ PushVariableValue(node, var);
537556 }
538557 else if (GlobalExists(node.name)) {
539- PushGlobalValue(node, GetGlobal (node.name));
558+ auto var = GetGlobal(node.name);
559+ if (var.type.isStruct && ! var.type.ptr) {
560+ Error(node.error, " Can't push struct value" );
561+ }
562+ PushGlobalValue(node, var);
540563 }
541564 else if (IsStructMember(node.name)) {
542565 string name = node.name[0 .. node.name.countUntil(" ." )];
543566 auto structVar = GetStructVariable(node, node.name);
544567
545568 if (GlobalExists(name)) {
546- PushGlobalValue(node, GetGlobal (name), structVar.size, structVar.offset, true );
569+ auto var = GetGlobal(name);
570+ PushGlobalValue(node, var, structVar.size, structVar.offset, true , var.type.ptr);
547571 }
548572 else if (VariableExists(name)) {
549- PushVariableValue(node, GetVariable (name), structVar.size, structVar.offset, true );
573+ auto var = GetVariable(name);
574+ PushVariableValue(node, var, structVar.size, structVar.offset, true , var.type.ptr);
550575 }
551576 }
552577 else if (node.name in consts) {
@@ -1157,41 +1182,50 @@ class BackendARM64 : CompilerBackend {
11571182 variables = [];
11581183 }
11591184
1160- void SetVariable (Node node, Variable var, size_t size = 0 , size_t offset = 0 , bool member = false ) {
1185+ void SetVariable (
1186+ Node node, Variable var, size_t size = 0 , size_t offset = 0 ,
1187+ bool member = false , bool deref = false
1188+ ) {
11611189 if (size == 0 ) {
1162- size = var.type.size ;
1190+ size = var.type.Size() ;
11631191 }
11641192
11651193 output ~= " ldr x9, [x19, #-8]!\n " ;
11661194
1167- if (var.type.isStruct && ! member) {
1168- Error(node.error, " Can't set struct value" );
1195+ string base;
1196+ if (deref) {
1197+ output ~= format(" ldr x10, [x20, #%d]\n " , var.offset);
1198+ base = " x10" ;
1199+ } else {
1200+ offset += var.offset;
1201+ base = " x20" ;
11691202 }
11701203
1171- offset += var.offset;
1172-
11731204 switch (size) {
1174- case 1 : output ~= format(" strb w9, [x20 , #%d]\n " , offset); break ;
1175- case 2 : output ~= format(" strh w9, [x20 , #%d]\n " , offset); break ;
1176- case 4 : output ~= format(" str w9, [x20 , #%d]\n " , offset); break ;
1177- case 8 : output ~= format(" str x9, [x20 , #%d]\n " , offset); break ;
1205+ case 1 : output ~= format(" strb w9, [%s , #%d]\n " , base , offset); break ;
1206+ case 2 : output ~= format(" strh w9, [%s , #%d]\n " , base , offset); break ;
1207+ case 4 : output ~= format(" str w9, [%s , #%d]\n " , base , offset); break ;
1208+ case 8 : output ~= format(" str x9, [%s , #%d]\n " , base , offset); break ;
11781209 default : Error (node.error, " Bad variable type size" );
11791210 }
11801211 }
11811212
1182- void SetGlobal (Node node, Global global, size_t size = 0 , size_t offset = 0 , bool member = false ) {
1213+ void SetGlobal (
1214+ Node node, Global global, size_t size = 0 , size_t offset = 0 ,
1215+ bool member = false , bool deref = false
1216+ ) {
11831217 if (size == 0 ) {
1184- size = global.type.size ;
1218+ size = global.type.Size() ;
11851219 }
11861220
11871221 output ~= " ldr x9, [x19, #-8]!\n " ;
11881222
1189- if (global.type.isStruct && ! member) {
1190- Error(node.error, " Can't set struct value" );
1191- }
1192-
11931223 LoadAddress(" x10" , format(" __global_%s" , global.name.Sanitise()));
11941224
1225+ if (deref) {
1226+ output ~= " ldr x10, [x10]\n " ;
1227+ }
1228+
11951229 switch (size) {
11961230 case 1 : output ~= format(" strb w9, [x10, #%d]\n " , offset); break ;
11971231 case 2 : output ~= format(" strh w9, [x10, #%d]\n " , offset); break ;
@@ -1203,20 +1237,30 @@ class BackendARM64 : CompilerBackend {
12031237
12041238 override void CompileSet (SetNode node) {
12051239 if (VariableExists(node.var)) {
1206- SetVariable(node, GetVariable (node.var));
1240+ auto var = GetVariable(node.var);
1241+ if (var.type.isStruct && ! var.type.ptr) {
1242+ Error(node.error, " Can't set struct value" );
1243+ }
1244+ SetVariable(node, var);
12071245 }
12081246 else if (GlobalExists(node.var)) {
1209- SetGlobal(node, GetGlobal (node.var));
1247+ auto var = GetGlobal(node.var);
1248+ if (var.type.isStruct && ! var.type.ptr) {
1249+ Error(node.error, " Can't set struct value" );
1250+ }
1251+ SetGlobal(node, var);
12101252 }
12111253 else if (IsStructMember(node.var)) {
12121254 string name = node.var[0 .. node.var.countUntil(" ." )];
12131255 auto structVar = GetStructVariable(node, node.var);
12141256
12151257 if (VariableExists(name)) {
1216- SetVariable(node, GetVariable (name), structVar.size, structVar.offset, true );
1258+ auto var = GetVariable(name);
1259+ SetVariable(node, var, structVar.size, structVar.offset, true , var.type.ptr);
12171260 }
12181261 else if (GlobalExists(name)) {
1219- SetGlobal(node, GetGlobal (name), structVar.size, structVar. offset, true );
1262+ auto var = GetGlobal(name);
1263+ SetGlobal(node, var, structVar.size, structVar. offset, true , var.type.ptr);
12201264 }
12211265 }
12221266 else {
0 commit comments