qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

commit 8dddb971d923fa19dced39013e6d4a39676e065a
parent 5490268683c82ad07eac6d2e8296a45702a8381e
Author: Quentin Carbonneaux <quentin@c9x.me>
Date:   Mon, 29 Aug 2022 18:45:52 +0200

drop -G flag and add target amd64_apple

apple support is more than assembly syntax
in case of arm64 machines, and apple syntax
is currently useless in all cases but amd64;
rather than having a -G option that only
makes sense with amd64, we add a new target
amd64_apple

Diffstat:
MMakefile | 6++----
Mall.h | 23++++++++++-------------
Mamd64/all.h | 3++-
Mamd64/emit.c | 31++++++++++++++++++++++---------
Mamd64/isel.c | 2+-
Mamd64/targ.c | 42++++++++++++++++++++++++++++--------------
Marm64/emit.c | 24++++++++++++++++--------
Marm64/isel.c | 2+-
Marm64/targ.c | 2++
Aemit.c | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dgas.c | 174-------------------------------------------------------------------------------
Mmain.c | 25++++++-------------------
Mrv64/emit.c | 2+-
Mrv64/isel.c | 2+-
Mrv64/targ.c | 2++
15 files changed, 266 insertions(+), 246 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,7 +5,7 @@ PREFIX = /usr/local BINDIR = $(PREFIX)/bin COMMOBJ = main.o util.o parse.o cfg.o mem.o ssa.o alias.o load.o copy.o \ - fold.o live.o spill.o rega.o gas.o + fold.o live.o spill.o rega.o emit.o AMD64OBJ = amd64/targ.o amd64/sysv.o amd64/isel.o amd64/emit.o ARM64OBJ = arm64/targ.o arm64/abi.o arm64/isel.o arm64/emit.o RV64OBJ = rv64/targ.o rv64/abi.o rv64/isel.o rv64/emit.o @@ -30,11 +30,9 @@ main.o: config.h config.h: @case `uname` in \ *Darwin*) \ - echo "#define Defasm Gasmacho"; \ - echo "#define Deftgt T_amd64_sysv"; \ + echo "#define Deftgt T_amd64_apple"; \ ;; \ *) \ - echo "#define Defasm Gaself"; \ case `uname -m` in \ *aarch64*) \ echo "#define Deftgt T_arm64"; \ diff --git a/all.h b/all.h @@ -55,6 +55,9 @@ struct Target { void (*abi)(Fn *); void (*isel)(Fn *); void (*emitfn)(Fn *, FILE *); + void (*emitfin)(FILE *); + char asloc[4]; + char assym[4]; }; #define BIT(n) ((bits)1 << (n)) @@ -524,16 +527,10 @@ void spill(Fn *); /* rega.c */ void rega(Fn *); -/* gas.c */ -enum Asm { - Gasmacho, - Gaself, -}; -extern char *gasloc; -extern char *gassym; -void gasinit(enum Asm); -void gasemitlnk(char *, Lnk *, char *, FILE *); -void gasemitfntail(char *, FILE *); -void gasemitdat(Dat *, FILE *); -int gasstash(void *, int); -void gasemitfin(FILE *); +/* emit.c */ +void emitlnk(char *, Lnk *, char *, FILE *); +void emitdat(Dat *, FILE *); +int stashbits(void *, int); +void elf_emitfnfin(char *, FILE *); +void elf_emitfin(FILE *); +void macho_emitfin(FILE *); diff --git a/amd64/all.h b/amd64/all.h @@ -67,4 +67,5 @@ void amd64_sysv_abi(Fn *); void amd64_isel(Fn *); /* emit.c */ -void amd64_emitfn(Fn *, FILE *); +void amd64_sysv_emitfn(Fn *, FILE *); +void amd64_apple_emitfn(Fn *, FILE *); diff --git a/amd64/emit.c b/amd64/emit.c @@ -166,7 +166,7 @@ emitcon(Con *con, FILE *f) switch (con->type) { case CAddr: l = str(con->label); - p = con->local ? gasloc : l[0] == '"' ? "" : gassym; + p = con->local ? T.asloc : l[0] == '"' ? "" : T.assym; fprintf(f, "%s%s", p, l); if (con->bits.i) fprintf(f, "%+"PRId64, con->bits.i); @@ -425,8 +425,8 @@ emitins(Ins i, Fn *fn, FILE *f) fprintf(f, "\txorp%c %sfp%d(%%rip), %%%s\n", "xxsd"[i.cls], - gasloc, - gasstash(negmask[i.cls], 16), + T.asloc, + stashbits(negmask[i.cls], 16), regtoa(i.to.val, SLong) ); break; @@ -535,8 +535,8 @@ framesz(Fn *fn) return 4*f + 8*o + 176*fn->vararg; } -void -amd64_emitfn(Fn *fn, FILE *f) +static void +emitfn(Fn *fn, FILE *f) { static char *ctoa[] = { #define X(c, s) [c] = s, @@ -549,7 +549,7 @@ amd64_emitfn(Fn *fn, FILE *f) int *r, c, o, n, lbl; uint64_t fs; - gasemitlnk(fn->name, &fn->lnk, ".text", f); + emitlnk(fn->name, &fn->lnk, ".text", f); fputs("\tpushq %rbp\n\tmovq %rsp, %rbp\n", f); fs = framesz(fn); if (fs) @@ -570,7 +570,7 @@ amd64_emitfn(Fn *fn, FILE *f) for (lbl=0, b=fn->start; b; b=b->link) { if (lbl || b->npred > 1) - fprintf(f, "%sbb%d:\n", gasloc, id0+b->id); + fprintf(f, "%sbb%d:\n", T.asloc, id0+b->id); for (i=b->ins; i!=&b->ins[b->nins]; i++) emitins(*i, fn, f); lbl = 1; @@ -596,7 +596,7 @@ amd64_emitfn(Fn *fn, FILE *f) Jmp: if (b->s1 != b->link) fprintf(f, "\tjmp %sbb%d\n", - gasloc, id0+b->s1->id); + T.asloc, id0+b->s1->id); else lbl = 0; break; @@ -610,7 +610,7 @@ amd64_emitfn(Fn *fn, FILE *f) } else c = cmpneg(c); fprintf(f, "\tj%s %sbb%d\n", ctoa[c], - gasloc, id0+b->s2->id); + T.asloc, id0+b->s2->id); goto Jmp; } die("unhandled jump %d", b->jmp.type); @@ -618,3 +618,16 @@ amd64_emitfn(Fn *fn, FILE *f) } id0 += fn->nblk; } + +void +amd64_sysv_emitfn(Fn *fn, FILE *f) +{ + emitfn(fn, f); + elf_emitfnfin(fn->name, f); +} + +void +amd64_apple_emitfn(Fn *fn, FILE *f) +{ + emitfn(fn, f); +} diff --git a/amd64/isel.c b/amd64/isel.c @@ -79,7 +79,7 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) memset(&a, 0, sizeof a); a.offset.type = CAddr; a.offset.local = 1; - n = gasstash(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4); + n = stashbits(&fn->con[r0.val].bits, KWIDE(k) ? 8 : 4); sprintf(buf, "fp%d", n); a.offset.label = intern(buf); fn->mem[fn->nmem-1] = a; diff --git a/amd64/targ.c b/amd64/targ.c @@ -12,20 +12,34 @@ amd64_memargs(int op) return amd64_op[op].nmem; } +#define AMD64_COMMON \ + .gpr0 = RAX, \ + .ngpr = NGPR, \ + .fpr0 = XMM0, \ + .nfpr = NFPR, \ + .rglob = BIT(RBP) | BIT(RSP), \ + .nrglob = 2, \ + .rsave = amd64_sysv_rsave, \ + .nrsave = {NGPS, NFPS}, \ + .retregs = amd64_sysv_retregs, \ + .argregs = amd64_sysv_argregs, \ + .memargs = amd64_memargs, \ + .abi = amd64_sysv_abi, \ + .isel = amd64_isel, \ + Target T_amd64_sysv = { .name = "amd64_sysv", - .gpr0 = RAX, - .ngpr = NGPR, - .fpr0 = XMM0, - .nfpr = NFPR, - .rglob = BIT(RBP) | BIT(RSP), - .nrglob = 2, - .rsave = amd64_sysv_rsave, - .nrsave = {NGPS, NFPS}, - .retregs = amd64_sysv_retregs, - .argregs = amd64_sysv_argregs, - .memargs = amd64_memargs, - .abi = amd64_sysv_abi, - .isel = amd64_isel, - .emitfn = amd64_emitfn, + .emitfn = amd64_sysv_emitfn, + .emitfin = elf_emitfin, + .asloc = ".L", + AMD64_COMMON +}; + +Target T_amd64_apple = { + .name = "amd64_apple", + .emitfn = amd64_apple_emitfn, + .emitfin = macho_emitfin, + .asloc = "L", + .assym = "_", + AMD64_COMMON }; diff --git a/arm64/emit.c b/arm64/emit.c @@ -245,7 +245,7 @@ emitf(char *s, Ins *i, E *e) static void loadcon(Con *c, int r, int k, FILE *f) { - char *rn, *p, off[32]; + char *rn, *l, *p, off[32]; int64_t n; int w, sh; @@ -258,11 +258,12 @@ loadcon(Con *c, int r, int k, FILE *f) sprintf(off, "+%"PRIi64, n); else off[0] = 0; - p = c->local ? ".L" : ""; + l = str(c->label); + p = c->local ? T.asloc : l[0] == '"' ? "" : T.assym; fprintf(f, "\tadrp\t%s, %s%s%s\n", - rn, p, str(c->label), off); + rn, p, l, off); fprintf(f, "\tadd\t%s, %s, #:lo12:%s%s%s\n", - rn, rn, p, str(c->label), off); + rn, rn, p, l, off); return; } assert(c->type == CBits); @@ -451,7 +452,7 @@ arm64_emitfn(Fn *fn, FILE *out) Ins *i; E *e; - gasemitlnk(fn->name, &fn->lnk, ".text", out); + emitlnk(fn->name, &fn->lnk, ".text", out); e = &(E){.f = out, .fn = fn}; framelayout(e); @@ -500,7 +501,7 @@ arm64_emitfn(Fn *fn, FILE *out) for (lbl=0, b=e->fn->start; b; b=b->link) { if (lbl || b->npred > 1) - fprintf(e->f, ".L%d:\n", id0+b->id); + fprintf(e->f, "%s%d:\n", T.asloc, id0+b->id); for (i=b->ins; i!=&b->ins[b->nins]; i++) emitins(i, e); lbl = 1; @@ -550,7 +551,10 @@ arm64_emitfn(Fn *fn, FILE *out) case Jjmp: Jmp: if (b->s1 != b->link) - fprintf(e->f, "\tb\t.L%d\n", id0+b->s1->id); + fprintf(e->f, + "\tb\t%s%d\n", + T.asloc, id0+b->s1->id + ); else lbl = 0; break; @@ -564,9 +568,13 @@ arm64_emitfn(Fn *fn, FILE *out) b->s2 = t; } else c = cmpneg(c); - fprintf(e->f, "\tb%s\t.L%d\n", ctoa[c], id0+b->s2->id); + fprintf(e->f, + "\tb%s\t%s%d\n", + ctoa[c], T.asloc, id0+b->s2->id + ); goto Jmp; } } id0 += e->fn->nblk; + elf_emitfnfin(e->fn->name, e->f); } diff --git a/arm64/isel.c b/arm64/isel.c @@ -84,7 +84,7 @@ fixarg(Ref *pr, int k, int phi, Fn *fn) emit(Ocopy, k, r1, r0, R); } else { c = &fn->con[r0.val]; - n = gasstash(&c->bits, KWIDE(k) ? 8 : 4); + n = stashbits(&c->bits, KWIDE(k) ? 8 : 4); vgrow(&fn->con, ++fn->ncon); c = &fn->con[fn->ncon-1]; sprintf(buf, "fp%d", n); diff --git a/arm64/targ.c b/arm64/targ.c @@ -41,6 +41,8 @@ Target T_arm64 = { .abi = arm64_abi, .isel = arm64_isel, .emitfn = arm64_emitfn, + .emitfin = elf_emitfin, + .asloc = ".L", }; MAKESURE(globals_are_not_arguments, diff --git a/emit.c b/emit.c @@ -0,0 +1,172 @@ +#include "all.h" + +void +emitlnk(char *n, Lnk *l, char *s, FILE *f) +{ + char *p; + + if (l->sec) { + fprintf(f, ".section %s", l->sec); + if (l->secf) + fprintf(f, ", %s", l->secf); + } else { + fputs(s, f); + } + fputc('\n', f); + if (l->align) + fprintf(f, ".balign %d\n", l->align); + p = n[0] == '"' ? "" : T.assym; + if (l->export) + fprintf(f, ".globl %s%s\n", p, n); + fprintf(f, "%s%s:\n", p, n); +} + +void +emitdat(Dat *d, FILE *f) +{ + static char *dtoa[] = { + [DB] = "\t.byte", + [DH] = "\t.short", + [DW] = "\t.int", + [DL] = "\t.quad" + }; + static int64_t zero; + char *p; + + switch (d->type) { + case DStart: + zero = 0; + break; + case DEnd: + if (zero != -1) { + emitlnk(d->name, d->lnk, ".bss", f); + fprintf(f, "\t.fill %"PRId64",1,0\n", zero); + } + break; + case DZ: + if (zero != -1) + zero += d->u.num; + else + fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num); + break; + default: + if (zero != -1) { + emitlnk(d->name, d->lnk, ".data", f); + if (zero > 0) + fprintf(f, "\t.fill %"PRId64",1,0\n", zero); + zero = -1; + } + if (d->isstr) { + if (d->type != DB) + err("strings only supported for 'b' currently"); + fprintf(f, "\t.ascii %s\n", d->u.str); + } + else if (d->isref) { + p = d->u.ref.name[0] == '"' ? "" : T.assym; + fprintf(f, "%s %s%s%+"PRId64"\n", + dtoa[d->type], p, d->u.ref.name, + d->u.ref.off); + } + else { + fprintf(f, "%s %"PRId64"\n", + dtoa[d->type], d->u.num); + } + break; + } +} + +typedef struct Asmbits Asmbits; + +struct Asmbits { + char bits[16]; + int size; + Asmbits *link; +}; + +static Asmbits *stash; + +int +stashbits(void *bits, int size) +{ + Asmbits **pb, *b; + int i; + + assert(size == 4 || size == 8 || size == 16); + for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++) + if (size <= b->size) + if (memcmp(bits, b->bits, size) == 0) + return i; + b = emalloc(sizeof *b); + memcpy(b->bits, bits, size); + b->size = size; + b->link = 0; + *pb = b; + return i; +} + +static void +emitfin(FILE *f, char *sec[3]) +{ + Asmbits *b; + char *p; + int lg, i; + double d; + + if (!stash) + return; + fprintf(f, "/* floating point constants */\n"); + for (lg=4; lg>=2; lg--) + for (b=stash, i=0; b; b=b->link, i++) { + if (b->size == (1<<lg)) { + fprintf(f, + ".section %s\n" + ".p2align %d\n" + "%sfp%d:", + sec[lg-2], lg, T.asloc, i + ); + for (p=b->bits; p<&b->bits[b->size]; p+=4) + fprintf(f, "\n\t.int %"PRId32, + *(int32_t *)p); + if (lg <= 3) { + if (lg == 2) + d = *(float *)b->bits; + else + d = *(double *)b->bits; + fprintf(f, " /* %f */\n\n", d); + } else + fprintf(f, "\n\n"); + } + } + while ((b=stash)) { + stash = b->link; + free(b); + } +} + +void +elf_emitfin(FILE *f) +{ + static char *sec[3] = { ".rodata", ".rodata", ".rodata" }; + + emitfin(f ,sec); + fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n"); +} + +void +elf_emitfnfin(char *fn, FILE *f) +{ + fprintf(f, ".type %s, @function\n", fn); + fprintf(f, ".size %s, .-%s\n", fn, fn); +} + +void +macho_emitfin(FILE *f) +{ + static char *sec[3] = { + "__TEXT,__literal4,4byte_literals", + "__TEXT,__literal8,8byte_literals", + ".rodata", /* should not happen */ + }; + + emitfin(f, sec); +} diff --git a/gas.c b/gas.c @@ -1,174 +0,0 @@ -#include "all.h" - - -char *gasloc, *gassym; -static int gasasm; - -void -gasinit(enum Asm asmmode) -{ - gasasm = asmmode; - switch (gasasm) { - case Gaself: - gasloc = ".L"; - gassym = ""; - break; - case Gasmacho: - gasloc = "L"; - gassym = "_"; - break; - } -} - -void -gasemitlnk(char *n, Lnk *l, char *s, FILE *f) -{ - char *p; - - if (l->sec) { - fprintf(f, ".section %s", l->sec); - if (l->secf) - fprintf(f, ", %s", l->secf); - } else { - fputs(s, f); - } - fputc('\n', f); - if (l->align) - fprintf(f, ".balign %d\n", l->align); - p = n[0] == '"' ? "" : gassym; - if (l->export) - fprintf(f, ".globl %s%s\n", p, n); - fprintf(f, "%s%s:\n", p, n); -} - -void -gasemitfntail(char *fn, FILE *f) -{ - if (gasasm == Gaself) { - fprintf(f, ".type %s, @function\n", fn); - fprintf(f, ".size %s, .-%s\n", fn, fn); - } -} - -void -gasemitdat(Dat *d, FILE *f) -{ - static char *dtoa[] = { - [DB] = "\t.byte", - [DH] = "\t.short", - [DW] = "\t.int", - [DL] = "\t.quad" - }; - static int64_t zero; - char *p; - - switch (d->type) { - case DStart: - zero = 0; - break; - case DEnd: - if (zero != -1) { - gasemitlnk(d->name, d->lnk, ".bss", f); - fprintf(f, "\t.fill %"PRId64",1,0\n", zero); - } - break; - case DZ: - if (zero != -1) - zero += d->u.num; - else - fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num); - break; - default: - if (zero != -1) { - gasemitlnk(d->name, d->lnk, ".data", f); - if (zero > 0) - fprintf(f, "\t.fill %"PRId64",1,0\n", zero); - zero = -1; - } - if (d->isstr) { - if (d->type != DB) - err("strings only supported for 'b' currently"); - fprintf(f, "\t.ascii %s\n", d->u.str); - } - else if (d->isref) { - p = d->u.ref.name[0] == '"' ? "" : gassym; - fprintf(f, "%s %s%s%+"PRId64"\n", - dtoa[d->type], p, d->u.ref.name, - d->u.ref.off); - } - else { - fprintf(f, "%s %"PRId64"\n", - dtoa[d->type], d->u.num); - } - break; - } -} - -typedef struct Asmbits Asmbits; - -struct Asmbits { - char bits[16]; - int size; - Asmbits *link; -}; - -static Asmbits *stash; - -int -gasstash(void *bits, int size) -{ - Asmbits **pb, *b; - int i; - - assert(size == 4 || size == 8 || size == 16); - for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++) - if (size <= b->size) - if (memcmp(bits, b->bits, size) == 0) - return i; - b = emalloc(sizeof *b); - memcpy(b->bits, bits, size); - b->size = size; - b->link = 0; - *pb = b; - return i; -} - -void -gasemitfin(FILE *f) -{ - Asmbits *b; - char *p; - int sz, i; - double d; - - if (gasasm == Gaself) - fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n\n"); - if (!stash) - return; - fprintf(f, "/* floating point constants */\n.data\n"); - for (sz=16; sz>=4; sz/=2) - for (b=stash, i=0; b; b=b->link, i++) { - if (b->size == sz) { - fprintf(f, - ".balign %d\n" - "%sfp%d:", - sz, gasloc, i - ); - for (p=b->bits; p<&b->bits[sz]; p+=4) - fprintf(f, "\n\t.int %"PRId32, - *(int32_t *)p); - if (sz <= 8) { - if (sz == 4) - d = *(float *)b->bits; - else - d = *(double *)b->bits; - fprintf(f, " /* %f */\n", d); - } else - fprintf(f, "\n"); - } - } - while ((b=stash)) { - stash = b->link; - free(b); - } -} diff --git a/main.c b/main.c @@ -19,11 +19,13 @@ char debug['Z'+1] = { }; extern Target T_amd64_sysv; +extern Target T_amd64_apple; extern Target T_arm64; extern Target T_rv64; static Target *tlist[] = { &T_amd64_sysv, + &T_amd64_apple, &T_arm64, &T_rv64, 0 @@ -40,7 +42,7 @@ data(Dat *d) fputs("/* end data */\n\n", outf); freeall(); } - gasemitdat(d, outf); + emitdat(d, outf); } static void @@ -92,7 +94,6 @@ func(Fn *fn) fn->rpo[n]->link = fn->rpo[n+1]; if (!dbg) { T.emitfn(fn, outf); - gasemitfntail(fn->name, outf); fprintf(outf, "/* end function %s */\n\n", fn->name); } else fprintf(stderr, "\n"); @@ -105,12 +106,11 @@ main(int ac, char *av[]) Target **t; FILE *inf, *hf; char *f, *sep; - int c, asmmode; + int c; - asmmode = Defasm; T = Deftgt; outf = stdout; - while ((c = getopt(ac, av, "hd:o:G:t:")) != -1) + while ((c = getopt(ac, av, "hd:o:t:")) != -1) switch (c) { case 'd': for (; *optarg; optarg++) @@ -144,16 +144,6 @@ main(int ac, char *av[]) } } break; - case 'G': - if (strcmp(optarg, "e") == 0) - asmmode = Gaself; - else if (strcmp(optarg, "m") == 0) - asmmode = Gasmacho; - else { - fprintf(stderr, "unknown gas flavor '%s'\n", optarg); - exit(1); - } - break; case 'h': default: hf = c != 'h' ? stderr : stdout; @@ -168,13 +158,10 @@ main(int ac, char *av[]) fputs(" (default)", hf); } fprintf(hf, "\n"); - fprintf(hf, "\t%-11s generate gas (e) or osx (m) asm\n", "-G {e,m}"); fprintf(hf, "\t%-11s dump debug information\n", "-d <flags>"); exit(c != 'h'); } - gasinit(asmmode); - do { f = av[optind]; if (!f || strcmp(f, "-") == 0) { @@ -192,7 +179,7 @@ main(int ac, char *av[]) } while (++optind < ac); if (!dbg) - gasemitfin(outf); + T.emitfin(outf); exit(0); } diff --git a/rv64/emit.c b/rv64/emit.c @@ -415,7 +415,7 @@ rv64_emitfn(Fn *fn, FILE *f) Blk *b, *s; Ins *i; - gasemitlnk(fn->name, &fn->lnk, ".text", f); + emitlnk(fn->name, &fn->lnk, ".text", f); if (fn->vararg) { /* TODO: only need space for registers diff --git a/rv64/isel.c b/rv64/isel.c @@ -41,7 +41,7 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn) * immediates */ assert(c->type == CBits); - n = gasstash(&c->bits, KWIDE(k) ? 8 : 4); + n = stashbits(&c->bits, KWIDE(k) ? 8 : 4); vgrow(&fn->con, ++fn->ncon); c = &fn->con[fn->ncon-1]; sprintf(buf, "fp%d", n); diff --git a/rv64/targ.c b/rv64/targ.c @@ -47,6 +47,8 @@ Target T_rv64 = { .abi = rv64_abi, .isel = rv64_isel, .emitfn = rv64_emitfn, + .emitfin = elf_emitfin, + .asloc = ".L", }; MAKESURE(rsave_size_ok, sizeof rv64_rsave == (NGPS+NFPS+1) * sizeof(int));