From 7036e19098c295a075f97cbd056fdc43bd490fb2 Mon Sep 17 00:00:00 2001 From: lemon Date: Tue, 23 Dec 2025 11:36:51 +0100 Subject: lower alloca as a separate pass before isel --- ir/dump.c | 3 +++ ir/ir.c | 2 ++ ir/ir.h | 4 ++++ ir/stack.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 ir/stack.c (limited to 'ir') diff --git a/ir/dump.c b/ir/dump.c index a2faf27..f952292 100644 --- a/ir/dump.c +++ b/ir/dump.c @@ -155,6 +155,9 @@ dumpref(enum op o, union ref ref) bfmt(out, "]"); } break; + case RSTACK: + bfmt(out, "[stack %d]", ref.i); + break; default: assert(!"ref"); } } diff --git a/ir/ir.c b/ir/ir.c index 3c76cde..6edc429 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -650,6 +650,8 @@ irfini(struct function *fn) simpl(fn); freearena(fn->passarena); } + lowerstack(fn); + freearena(fn->passarena); if (ccopt.dbg.o) { bfmt(ccopt.dbgout, "<< Before isel >>\n"); irdump(fn); diff --git a/ir/ir.h b/ir/ir.h index dccca0c..4248016 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -62,6 +62,7 @@ enum refkind { RXCON, /* other constants (incl. external symbols) */ RADDR, /* target-specific addressing mode */ RTYPE, /* irtype */ + RSTACK, /* stack base offset */ }; union ref { @@ -325,6 +326,9 @@ void mem2reg(struct function *); /** intrin.c **/ void lowerintrin(struct function *); +/** stack.c **/ +void lowerstack(struct function *); + /** regalloc.c **/ void regalloc(struct function *); diff --git a/ir/stack.c b/ir/stack.c new file mode 100644 index 0000000..2420fdb --- /dev/null +++ b/ir/stack.c @@ -0,0 +1,37 @@ +#include "ir.h" + +void +lowerstack(struct function *fn) +{ + extern int ninstr; + fn->stksiz = 0; + FREQUIRE(FNUSE); + + struct block *blk = fn->entry; + do { + for (int i = 0; i < blk->ins.n; ++i) { + uint alignlog2, siz; + int t = blk->ins.p[i]; + struct instr *ins = &instrtab[t]; + switch (ins->op) { + case Oalloca1: case Oalloca2: case Oalloca4: case Oalloca8: case Oalloca16: + alignlog2 = ins->op - Oalloca1; + assert(ins->l.i > 0); + siz = ins->l.i << alignlog2; + fn->stksiz += siz; + fn->stksiz = alignup(fn->stksiz, 1 << alignlog2); + if (fn->stksiz > (1<<16)-1) error(NULL, "'%s' stack frame too big", fn->name); + *ins = mkinstr(Onop,0,); + replcuses(mkref(RTMP, t), mkref(RSTACK, fn->stksiz)); + continue; + } + } + } while ((blk = blk->lnext) != fn->entry); + + if (ccopt.dbg.s) { + bfmt(ccopt.dbgout, "<< After stack >>\n"); + irdump(fn); + } +} + +/* vim:set ts=3 sw=3 expandtab: */ -- cgit v1.2.3