diff options
| author | 2025-11-14 19:23:18 +0100 | |
|---|---|---|
| committer | 2025-11-14 19:23:18 +0100 | |
| commit | 57223ba45c4a88003826d25557a965d208c28639 (patch) | |
| tree | de25a05ed76a8c67aa9eb52e2bf996b8f3922f24 /amd64/sysv.c | |
| parent | a287fe5aeb6b681ab405c0297841dce64ab4b946 (diff) | |
sysv: document vaargs stack layout stuff
Diffstat (limited to 'amd64/sysv.c')
| -rw-r--r-- | amd64/sysv.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/amd64/sysv.c b/amd64/sysv.c index af0ade0..db88692 100644 --- a/amd64/sysv.c +++ b/amd64/sysv.c @@ -140,6 +140,30 @@ abiret(short r[2], uchar cls[2], int *ni, union irtype typ) return ret; } +/* Layout of va_list: + * struct { + * ( 0) unsigned int gp_offset; + * ( 4) unsigned int fp_offset; + * ( 8) void *overflow_arg_area; + * (16) void *reg_save_area; + * } + * Layout of register save area (align 16): + * reg off + * rdi 0 + * rsi 8 + * rdx 16 + * rcx 24 + * r8 32 + * r9 40 + * xmm0 48 + * xmm1 64 + * ... + * in amd64/emit xvaprologue generates the code to save the registers to a stack slot + * there only needs to be one xvaprologue if there's any vastart instrs, and it has to be + * at the beginning of the function (before IR generated by regalloc can touch any registers) + * then vastart can initialize va_list.reg_save_area with a pointer to that + */ + static void vastart(struct function *fn, struct block *blk, int *curi) { @@ -148,9 +172,11 @@ vastart(struct function *fn, struct block *blk, int *curi) struct instr *ins = &instrtab[blk->ins.p[*curi]]; union ref ap = ins->l, src, dst; assert(ins->op == Ovastart); - /* add xvaprologue if not there yet, which must be the first instruction in the function */ - if (fn->entry->ins.n > 0 && instrtab[fn->entry->ins.p[0]].op == Oxvaprologue) { - rsave = mkref(RTMP, fn->entry->ins.p[0]); + /* add xvaprologue if not there yet, which must be the first + * real instruction in the function (following alloca) */ + if (fn->entry->ins.n > 1 && instrtab[fn->entry->ins.p[1]].op == Oxvaprologue) { + rsave = mkref(RTMP, fn->entry->ins.p[0]); /* alloca instruction */ + assert(instrtab[rsave.i].op == Oalloca16); } else { rsave = insertinstr(fn->entry, 0, mkalloca(192, 16)); insertinstr(fn->entry, 1, mkinstr(Oxvaprologue, 0, rsave, .keep=1)); |