| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #include "all.h"
- enum {
- SecText,
- SecData,
- SecBss,
- };
- void
- emitlnk(char *n, Lnk *l, int s, FILE *f)
- {
- static char *sec[2][3] = {
- [0][SecText] = ".text",
- [0][SecData] = ".data",
- [0][SecBss] = ".bss",
- [1][SecText] = ".abort \"unreachable\"",
- [1][SecData] = ".section .tdata,\"awT\"",
- [1][SecBss] = ".section .tbss,\"awT\"",
- };
- char *pfx, *sfx;
- pfx = n[0] == '"' ? "" : T.assym;
- sfx = "";
- if (T.apple && l->thread) {
- l->sec = "__DATA";
- l->secf = "__thread_data,thread_local_regular";
- sfx = "$tlv$init";
- fputs(
- ".section __DATA,__thread_vars,"
- "thread_local_variables\n",
- f
- );
- fprintf(f, "%s%s:\n", pfx, n);
- fprintf(f,
- "\t.quad __tlv_bootstrap\n"
- "\t.quad 0\n"
- "\t.quad %s%s%s\n\n",
- pfx, n, sfx
- );
- }
- if (l->sec) {
- fprintf(f, ".section %s", l->sec);
- if (l->secf)
- fprintf(f, ",%s", l->secf);
- } else
- fputs(sec[l->thread != 0][s], f);
- fputc('\n', f);
- if (l->align)
- fprintf(f, ".balign %d\n", l->align);
- if (l->export)
- fprintf(f, ".globl %s%s\n", pfx, n);
- fprintf(f, "%s%s%s:\n", pfx, n, sfx);
- }
- void
- emitfnlnk(char *n, Lnk *l, FILE *f)
- {
- emitlnk(n, l, SecText, f);
- }
- 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 (d->lnk->common) {
- if (zero == -1)
- die("invalid common data definition");
- p = d->name[0] == '"' ? "" : T.assym;
- fprintf(f, ".comm %s%s,%"PRId64,
- p, d->name, zero);
- if (d->lnk->align)
- fprintf(f, ",%d", d->lnk->align);
- fputc('\n', f);
- }
- else if (zero != -1) {
- emitlnk(d->name, d->lnk, SecBss, 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, SecData, 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",
- ".abort \"unreachable\"",
- };
- emitfin(f, sec);
- }
- static uint32_t *file;
- static uint nfile;
- static uint curfile;
- void
- emitdbgfile(char *fn, FILE *f)
- {
- uint32_t id;
- uint n;
- id = intern(fn);
- for (n=0; n<nfile; n++)
- if (file[n] == id) {
- /* gas requires positive
- * file numbers */
- curfile = n + 1;
- return;
- }
- if (!file)
- file = vnew(0, sizeof *file, PHeap);
- vgrow(&file, ++nfile);
- file[nfile-1] = id;
- curfile = nfile;
- fprintf(f, ".file %u %s\n", curfile, fn);
- }
- void
- emitdbgloc(uint line, uint col, FILE *f)
- {
- if (col != 0)
- fprintf(f, "\t.loc %u %u %u\n", curfile, line, col);
- else
- fprintf(f, "\t.loc %u %u\n", curfile, line);
- }
|