Skip to content

Commit 5190b18

Browse files
committed
Fix Arm calling convention by storing arguments to stack
1 parent 9e359d2 commit 5190b18

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

src/globals.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,31 @@ func_t *add_func(char *func_name, bool synthesize)
947947
hashmap_put(FUNC_MAP, func_name, func);
948948
/* Use interned string for function name */
949949
strcpy(func->return_def.var_name, intern_string(func_name));
950-
func->stack_size = 4;
950+
/* Prepare space for function arguments and global pointer.
951+
*
952+
* For Arm architecture, the first four arguments are passed to r0 ~ r3,
953+
* and any additional arguments are passed to the stack.
954+
*
955+
* +-------------+ <-- sp + 20
956+
* | (val of ip) |
957+
* +-------------+ <-- sp + 16
958+
* | arg 8 |
959+
* +-------------+ <-- sp + 12
960+
* | arg 7 |
961+
* +-------------+ <-- sp + 8
962+
* | arg 6 |
963+
* +-------------+ <-- sp + 4
964+
* | arg 5 |
965+
* +-------------+ <-- sp
966+
*
967+
* However, register r12 (ip) holds the global pointer that points to
968+
* global stack, but this register may be changed after an external call.
969+
*
970+
* Therefore, the current strategy is preparing additional space for ip,
971+
* saves its orignal value to stack before an external call, and restore
972+
* it from the stack after the external function returns.
973+
* */
974+
func->stack_size = 20;
951975

952976
if (synthesize)
953977
return func;

src/reg-alloc.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,12 +768,40 @@ void reg_alloc(void)
768768
if (!callee_func->num_params)
769769
spill_alive(bb, insn);
770770

771-
if (dynlink)
771+
if (dynlink) {
772772
callee_func->is_used = true;
773+
if (!callee_func->bbs) {
774+
int ofs = 0;
775+
if (args > 4) {
776+
/* Store args to stack for Arm output */
777+
for (int i = 4; i < args; i++) {
778+
ir = bb_add_ph2_ir(bb, OP_store);
779+
ir->src0 = i;
780+
ir->src1 = ofs;
781+
ofs += 4;
782+
}
783+
}
784+
/* FIXME:
785+
* use a better way to preserve global pointer */
786+
ir = bb_add_ph2_ir(bb, OP_store);
787+
ir->src0 = 12;
788+
ir->src1 = 16;
789+
}
790+
}
773791

774792
ir = bb_add_ph2_ir(bb, OP_call);
775793
strcpy(ir->func_name, insn->str);
776794

795+
if (dynlink) {
796+
if (!callee_func->bbs) {
797+
/* FIXME:
798+
* use a better way to restore global pointer */
799+
ir = bb_add_ph2_ir(bb, OP_load);
800+
ir->dest = 12;
801+
ir->src0 = 16;
802+
}
803+
}
804+
777805
is_pushing_args = false;
778806
args = 0;
779807

0 commit comments

Comments
 (0)