commit 0d35c07dfc7e6b341aadc64a253738b6285b9e6a from: Benjamin Stürz date: Thu Oct 03 14:17:24 2024 UTC irc: allow EX_ALLOCA to take a register argument commit - 4efc4256d0461a3fbc9abdb3443dc7aa73e763c3 commit + 0d35c07dfc7e6b341aadc64a253738b6285b9e6a blob - 8566d7c50703dc2618f31bc44f94e28fa8129567 blob + fbd52308aca953b521e52120d240c43707f30f48 --- cc/irc/irc.c +++ cc/irc/irc.c @@ -335,8 +335,8 @@ struct expr { long i; double f; struct { - int num; - int off; + struct regimm num; + int off; // only valid if ri.is_imm } alloca; struct { int l; @@ -826,10 +826,11 @@ struct expr *e; error ("the result of alloca must be stored in a far or stack pointer"); e->type = EX_ALLOCA; - expect (TK_INT); - e->alloca.num = lval.i; - stalloc (fn, sizeof_dt (dt->inner) * e->alloca.num); - e->alloca.off = fn->stoff; + regimm (&e->alloca.num, &default_dt); + if (e->alloca.num.is_imm) { + stalloc (fn, sizeof_dt (dt->inner) * e->alloca.num.imm); + e->alloca.off = fn->stoff; + } expect (';'); } else if (strcmp (lval.s, "ptradd") == 0) { e->type = EX_PTRADD; @@ -1245,7 +1246,8 @@ struct expr *e; printf ("$%d", e->reg); break; case EX_ALLOCA: - printf ("alloca %d", e->alloca.num); + printf ("alloca "); + print_ri (&e->alloca.num); break; case EX_ADD: printf ("add $%d, ", e->bin.l); @@ -2166,7 +2168,14 @@ struct expr *e; puts ("\tmov dx, ss"); // fallthrough case DT_SPTR: - printf ("\tlea ax, [bp + %d]\n", e->alloca.off); + if (e->alloca.num.is_imm) { + printf ("\tlea ax, [bp + %d]\n", e->alloca.off); + } else { + loadw (NULL, AX, &fn->regs[e->alloca.num.reg]); + cmul ("ax", sizeof_dt (dt->inner)); + puts ("\tsub sp, ax"); + puts ("\tmov ax, sp"); + } break; default: abort (); blob - 1d6a10ae6bf33408ac50b80ade2bedfd35342862 blob + 08dc0947bade90c0785e263d4809546f818db9ad --- cc/irc/test.ir +++ cc/irc/test.ir @@ -225,3 +225,9 @@ fn fcmp (): word { nop; ret 0; } + +fn alloca_reg ($0: word): word { + let $1: ^word = alloca $0; + let $2: word = read $1, 5; + ret $2; +}