aboutsummaryrefslogtreecommitdiffhomepage
path: root/ir
diff options
context:
space:
mode:
author lemon<lsof@mailbox.org>2025-12-23 11:36:51 +0100
committer lemon<lsof@mailbox.org>2025-12-23 11:39:45 +0100
commit7036e19098c295a075f97cbd056fdc43bd490fb2 (patch)
tree8e03e29ab8f5645b0b7c71c7663e608b17de0573 /ir
parent56cf12a2aca36fabf3c3918947a88cbc4a605bb2 (diff)
lower alloca as a separate pass before isel
Diffstat (limited to 'ir')
-rw-r--r--ir/dump.c3
-rw-r--r--ir/ir.c2
-rw-r--r--ir/ir.h4
-rw-r--r--ir/stack.c37
4 files changed, 46 insertions, 0 deletions
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: */