nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit e6f1971177ee88eebb80412c982eb0867c52c477
parent d78ea8f502d9cc135ae097d08e2cc4d0b43e2a28
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Tue, 11 Jan 2022 20:30:20 -0600

x64: only push used registers to the stack before call

Diffstat:
Mir.c | 2+-
Mx64.c | 35++++++++++++++++++++++++++---------
2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/ir.c b/ir.c @@ -19,7 +19,7 @@ extern struct assgns assgns; extern struct toplevel toplevel; #define PUTINS(op, val) ins = (struct instr){(op), (val)} ; bumpinterval(out, &ins, val) ; array_add(out, ins) ; -#define STARTINS(op, val) curi++ ; PUTINS((op), (val)) ; +#define STARTINS(op, val) PUTINS((op), (val)) ; curi++ ; #define NEWTMP tmpi++; interval.active = 0; interval.start = curi + 1; interval.end = curi + 1; array_add((&out->intervals), interval); extern struct target targ; diff --git a/x64.c b/x64.c @@ -567,6 +567,14 @@ pop_r64(char *buf, enum reg reg) return _pushpop_r64(buf, 8, reg); } +static size_t emitsyscall(char *buf, uint8_t paramcount); + +const struct target x64_target = { + .reserved = (1 << RSP) | (1 << RBP) | (1 << R12) | (1 << R13), + .emitsyscall = emitsyscall, + .emitproc = emitproc +}; + #define NEXT ins++; assert(ins <= end); static size_t @@ -608,9 +616,11 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, struct instr *ins = start ? start : proc->data; end = end ? end : &proc->data[proc->len]; + uint16_t active = 0; + uint64_t dest, src, size, count, tmp, label; int64_t offset; - uint64_t localalloc = 0; + uint64_t localalloc = 0, curi = 0; size_t total = 0; if (!start) { @@ -619,6 +629,14 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, } while (ins < end) { + curi++; + for (size_t j = 0; j < proc->intervals.len; j++) { + if ((active & (1 << j)) && proc->intervals.data[j].end == curi - 1) + active &= ~(1 << proc->intervals.data[j].reg); + + if (!(active & (1 << j)) && proc->intervals.data[j].start == curi) + active |= 1 << proc->intervals.data[j].reg; + } switch (ins->op) { // FIXME: we don't handle jumps backward yet case IR_JUMP: @@ -663,6 +681,7 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, total += cmp_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg); NEXT; if (ins->op == IR_CONDJUMP) { + curi++; label = ins->id; NEXT; assert(ins->op == IR_EXTRA); @@ -705,7 +724,9 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, dest = ins->id; for (int i = 0; i < 16; i++) { - total += push_r64(buf ? buf + total : NULL, i); + if (active & (1 << i)) { + total += push_r64(buf ? buf + total : NULL, i); + } } NEXT; @@ -721,7 +742,9 @@ emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, // FIXME: this won't work with non-64-bit things total += add_r64_imm(buf ? buf + total : NULL, RSP, 8*count); for (int i = 15; i >= 0; i--) { - total += pop_r64(buf ? buf + total : NULL, i); + if (active & (1 << i)) { + total += pop_r64(buf ? buf + total : NULL, i); + } } break; case IR_LABEL: @@ -749,9 +772,3 @@ emitproc(char *buf, struct iproc *proc) { return emitblock(buf, proc, NULL, NULL, 0); } - -const struct target x64_target = { - .reserved = (1 << RSP) | (1 << RBP) | (1 << R12) | (1 << R13), - .emitsyscall = emitsyscall, - .emitproc = emitproc -};