@@ -223,6 +223,9 @@ fn arm64_max_int(a int, b int) int {
223223fn (mut g Gen) gen_pre_pass () {
224224 mut data_offset := u64 (0 )
225225 for gi in 0 .. g.m.globals.len {
226+ if g.m.globals[gi].linkage == .external {
227+ continue
228+ }
226229 data_offset = (data_offset + 7 ) & ~ u64 (7 )
227230 g.macho.add_symbol ('_' + g.m.globals[gi].name, data_offset, true , 3 )
228231 size := g.m.type_size (g.m.globals[gi].typ)
@@ -233,6 +236,9 @@ fn (mut g Gen) gen_pre_pass() {
233236// gen_post_pass emits post pass output for arm64.
234237fn (mut g Gen) gen_post_pass () {
235238 for gi in 0 .. g.m.globals.len {
239+ if g.m.globals[gi].linkage == .external {
240+ continue
241+ }
236242 for g.macho.data_data.len % 8 != 0 {
237243 g.macho.data_data << 0
238244 }
@@ -479,7 +485,7 @@ fn (mut g Gen) emit_zero_aggregate(ptr_reg int, typ_id ssa.TypeID, max_size int)
479485 }
480486 n_words := (size + 7 ) / 8
481487 for wi in 0 .. n_words {
482- g.emit32 ( asm_str_imm ( xzr, Reg (ptr_reg), u32 (wi)) )
488+ g.emit_store_reg_offset ( xzr, Reg (ptr_reg), wi * 8 )
483489 }
484490}
485491
@@ -650,29 +656,27 @@ fn (mut g Gen) gen_instr(val_id int) {
650656 g.emit32 (asm_str (Reg (8 ), Reg (ptr_reg)))
651657 g.emit32 (asm_str_imm (Reg (10 ), Reg (ptr_reg), 1 ))
652658 } else {
659+ ptr_reg := g.load_val (ptr_id, 9 )
660+ dest_type := g.ptr_elem_type (ptr_id)
661+ if g.is_zero_const (src_id) && g.is_aggregate_type (dest_type) {
662+ g.emit_zero_aggregate (ptr_reg, dest_type, g.aggregate_store_size (ptr_id,
663+ dest_type))
664+ return
665+ }
653666 src_size := g.m.type_size (src_val.typ)
654667 if src_size > 8 && g.is_value_aggregate_type (src_val.typ) {
655668 if src_off := g.stack_slot (src_id) {
656- ptr_reg := g.load_val (ptr_id, 9 )
657669 copy_size := g.aggregate_store_size (ptr_id, src_val.typ)
658670 n_words := (copy_size + 7 ) / 8
659671 for wi in 0 .. n_words {
660672 g.emit_load_fp (8 , src_off + wi * 8 )
661- g.emit32 ( asm_str_imm ( Reg (8 ), Reg (ptr_reg), u32 (wi)) )
673+ g.emit_store_reg_offset ( Reg (8 ), Reg (ptr_reg), wi * 8 )
662674 }
663675 } else {
664676 src_reg := g.load_val (src_id, 8 )
665- ptr_reg := g.load_val (ptr_id, 9 )
666677 g.emit32 (asm_str (Reg (src_reg), Reg (ptr_reg)))
667678 }
668679 } else {
669- ptr_reg := g.load_val (ptr_id, 9 )
670- dest_type := g.ptr_elem_type (ptr_id)
671- if g.is_zero_const (src_id) && g.is_aggregate_type (dest_type) {
672- g.emit_zero_aggregate (ptr_reg, dest_type, g.aggregate_store_size (ptr_id,
673- dest_type))
674- return
675- }
676680 src_reg := g.load_val (src_id, 8 )
677681 store_typ := if int (dest_type) > 0 { dest_type } else { src_val.typ }
678682 g.emit_store_typed (src_reg, ptr_reg, store_typ)
@@ -723,7 +727,7 @@ fn (mut g Gen) gen_instr(val_id int) {
723727 copy_words := (copy_size + 7 ) / 8
724728 total_words := (result_size + 7 ) / 8
725729 for wi in 0 .. copy_words {
726- g.emit32 ( asm_ldr_imm ( Reg (8 ), Reg (ptr_reg), u32 (wi)) )
730+ g.emit_load_reg_offset ( Reg (8 ), Reg (ptr_reg), wi * 8 )
727731 g.emit_store_fp (8 , off + wi * 8 )
728732 }
729733 if copy_words < total_words {
@@ -992,18 +996,18 @@ fn (mut g Gen) gen_instr(val_id int) {
992996 if off := g.stack_slot (ret_id) {
993997 for wi in 0 .. n_words {
994998 g.emit_load_fp (8 , off + wi * 8 )
995- g.emit32 ( asm_str_imm ( Reg (8 ), Reg (9 ), u32 (wi)) )
999+ g.emit_store_reg_offset ( Reg (8 ), Reg (9 ), wi * 8 )
9961000 }
9971001 } else {
9981002 g.emit_mov_imm (8 , 0 )
9991003 for wi in 0 .. n_words {
1000- g.emit32 ( asm_str_imm ( Reg (8 ), Reg (9 ), u32 (wi)) )
1004+ g.emit_store_reg_offset ( Reg (8 ), Reg (9 ), wi * 8 )
10011005 }
10021006 }
10031007 } else {
10041008 g.emit_mov_imm (8 , 0 )
10051009 for wi in 0 .. n_words {
1006- g.emit32 ( asm_str_imm ( Reg (8 ), Reg (9 ), u32 (wi)) )
1010+ g.emit_store_reg_offset ( Reg (8 ), Reg (9 ), wi * 8 )
10071011 }
10081012 }
10091013 if g.stack_size > 0 {
@@ -1434,7 +1438,7 @@ fn (mut g Gen) emit_copy_ptr_to_fp(src_ptr_reg int, dst_off int, size int) {
14341438 n_words := (size + 7 ) / 8
14351439 tmp_reg := if src_ptr_reg == 8 { 10 } else { 8 }
14361440 for wi in 0 .. n_words {
1437- g.emit32 ( asm_ldr_imm ( Reg (tmp_reg), Reg (src_ptr_reg), u32 (wi)) )
1441+ g.emit_load_reg_offset ( Reg (tmp_reg), Reg (src_ptr_reg), wi * 8 )
14381442 g.emit_store_fp (tmp_reg, dst_off + wi * 8 )
14391443 }
14401444}
@@ -1564,12 +1568,28 @@ fn (mut g Gen) emit_global_addr(reg int, name string) {
15641568 } else {
15651569 sym_idx = g.macho.add_undefined (sym_name)
15661570 }
1571+ if g.is_external_global (name) {
1572+ g.macho.add_reloc (g.macho.text_data.len, sym_idx, arm64_ reloc_got_load_page21 , true )
1573+ g.emit32 (asm_adrp (Reg (reg)))
1574+ g.macho.add_reloc (g.macho.text_data.len, sym_idx, arm64_ reloc_got_load_pageoff12 , false )
1575+ g.emit32 (asm_ldr_pageoff (Reg (reg)))
1576+ return
1577+ }
15671578 g.macho.add_reloc (g.macho.text_data.len, sym_idx, arm64_ reloc_page21 , true )
15681579 g.emit32 (asm_adrp (Reg (reg)))
15691580 g.macho.add_reloc (g.macho.text_data.len, sym_idx, arm64_ reloc_pageoff12 , false )
15701581 g.emit32 (asm_add_pageoff (Reg (reg)))
15711582}
15721583
1584+ fn (g &Gen) is_external_global (name string ) bool {
1585+ for global in g.m.globals {
1586+ if global.name == name {
1587+ return global.linkage == .external
1588+ }
1589+ }
1590+ return false
1591+ }
1592+
15731593// find_global_idx_by_name resolves find global idx by name information for arm64.
15741594fn (g &Gen) find_global_idx_by_name (name string ) int {
15751595 for i, global in g.m.globals {
@@ -1760,19 +1780,13 @@ fn (mut g Gen) emit_store_fp(reg int, offset int) {
17601780 g.emit32 (asm_add_reg (Reg (11 ), fp, Reg (11 )))
17611781 g.emit32 (asm_str (Reg (reg), Reg (11 )))
17621782 } else {
1763- g.emit32 ( asm_str_imm ( Reg (reg), fp, u32 ( offset / 8 )) )
1783+ g.emit_store_reg_offset ( Reg (reg), fp, offset)
17641784 }
17651785}
17661786
17671787// emit_store_sp emits emit store sp output for arm64.
17681788fn (mut g Gen) emit_store_sp (reg int , offset int ) {
1769- if offset > = 0 && offset < 32768 && offset % 8 == 0 {
1770- g.emit32 (asm_str_imm (Reg (reg), sp, u32 (offset / 8 )))
1771- } else {
1772- g.emit_mov_imm (11 , i64 (offset))
1773- g.emit32 (asm_add_reg (Reg (11 ), sp, Reg (11 )))
1774- g.emit32 (asm_str (Reg (reg), Reg (11 )))
1775- }
1789+ g.emit_store_reg_offset (Reg (reg), sp, offset)
17761790}
17771791
17781792// emit_load_fp emits emit load fp output for arm64.
@@ -1784,8 +1798,42 @@ fn (mut g Gen) emit_load_fp(reg int, offset int) {
17841798 g.emit32 (asm_add_reg (Reg (11 ), fp, Reg (11 )))
17851799 g.emit32 (asm_ldr (Reg (reg), Reg (11 )))
17861800 } else {
1787- g.emit32 (asm_ldr_imm (Reg (reg), fp, u32 (offset / 8 )))
1801+ g.emit_load_reg_offset (Reg (reg), fp, offset)
1802+ }
1803+ }
1804+
1805+ fn (mut g Gen) emit_store_reg_offset (src Reg, base Reg, offset int ) {
1806+ if offset > = 0 && offset < 32768 && offset % 8 == 0 {
1807+ g.emit32 (asm_str_imm (src, base, u32 (offset / 8 )))
1808+ return
1809+ }
1810+ scratch := if int (src) != 11 && int (base) != 11 {
1811+ Reg (11 )
1812+ } else if int (src) != 12 && int (base) != 12 {
1813+ Reg (12 )
1814+ } else {
1815+ Reg (13 )
1816+ }
1817+ g.emit_mov_imm (int (scratch), i64 (offset))
1818+ g.emit32 (asm_add_reg (scratch, base, scratch))
1819+ g.emit32 (asm_str (src, scratch))
1820+ }
1821+
1822+ fn (mut g Gen) emit_load_reg_offset (dst Reg, base Reg, offset int ) {
1823+ if offset > = 0 && offset < 32768 && offset % 8 == 0 {
1824+ g.emit32 (asm_ldr_imm (dst, base, u32 (offset / 8 )))
1825+ return
1826+ }
1827+ scratch := if int (dst) != 11 && int (base) != 11 {
1828+ Reg (11 )
1829+ } else if int (dst) != 12 && int (base) != 12 {
1830+ Reg (12 )
1831+ } else {
1832+ Reg (13 )
17881833 }
1834+ g.emit_mov_imm (int (scratch), i64 (offset))
1835+ g.emit32 (asm_add_reg (scratch, base, scratch))
1836+ g.emit32 (asm_ldr (dst, scratch))
17891837}
17901838
17911839// emit_lea_fp emits emit lea fp output for arm64.
0 commit comments