aboutsummaryrefslogtreecommitdiff
path: root/emit.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2022-08-29 18:45:52 +0200
committerQuentin Carbonneaux <[email protected]>2022-08-31 21:42:49 +0200
commit8dddb971d923fa19dced39013e6d4a39676e065a (patch)
tree88192ecf3a60de73f06d03dab51dc51f17fb4ab7 /emit.c
parent5490268683c82ad07eac6d2e8296a45702a8381e (diff)
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 (limited to 'emit.c')
-rw-r--r--emit.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/emit.c b/emit.c
new file mode 100644
index 0000000..372ce3d
--- /dev/null
+++ 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);
+}