refine width of parsb/ub/sh/uh ops
[qbe.git] / emit.c
blob372ce3de050087ef27a00b97214a687002768fcb
1 #include "all.h"
3 void
4 emitlnk(char *n, Lnk *l, char *s, FILE *f)
6 char *p;
8 if (l->sec) {
9 fprintf(f, ".section %s", l->sec);
10 if (l->secf)
11 fprintf(f, ", %s", l->secf);
12 } else {
13 fputs(s, f);
15 fputc('\n', f);
16 if (l->align)
17 fprintf(f, ".balign %d\n", l->align);
18 p = n[0] == '"' ? "" : T.assym;
19 if (l->export)
20 fprintf(f, ".globl %s%s\n", p, n);
21 fprintf(f, "%s%s:\n", p, n);
24 void
25 emitdat(Dat *d, FILE *f)
27 static char *dtoa[] = {
28 [DB] = "\t.byte",
29 [DH] = "\t.short",
30 [DW] = "\t.int",
31 [DL] = "\t.quad"
33 static int64_t zero;
34 char *p;
36 switch (d->type) {
37 case DStart:
38 zero = 0;
39 break;
40 case DEnd:
41 if (zero != -1) {
42 emitlnk(d->name, d->lnk, ".bss", f);
43 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
45 break;
46 case DZ:
47 if (zero != -1)
48 zero += d->u.num;
49 else
50 fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num);
51 break;
52 default:
53 if (zero != -1) {
54 emitlnk(d->name, d->lnk, ".data", f);
55 if (zero > 0)
56 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
57 zero = -1;
59 if (d->isstr) {
60 if (d->type != DB)
61 err("strings only supported for 'b' currently");
62 fprintf(f, "\t.ascii %s\n", d->u.str);
64 else if (d->isref) {
65 p = d->u.ref.name[0] == '"' ? "" : T.assym;
66 fprintf(f, "%s %s%s%+"PRId64"\n",
67 dtoa[d->type], p, d->u.ref.name,
68 d->u.ref.off);
70 else {
71 fprintf(f, "%s %"PRId64"\n",
72 dtoa[d->type], d->u.num);
74 break;
78 typedef struct Asmbits Asmbits;
80 struct Asmbits {
81 char bits[16];
82 int size;
83 Asmbits *link;
86 static Asmbits *stash;
88 int
89 stashbits(void *bits, int size)
91 Asmbits **pb, *b;
92 int i;
94 assert(size == 4 || size == 8 || size == 16);
95 for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++)
96 if (size <= b->size)
97 if (memcmp(bits, b->bits, size) == 0)
98 return i;
99 b = emalloc(sizeof *b);
100 memcpy(b->bits, bits, size);
101 b->size = size;
102 b->link = 0;
103 *pb = b;
104 return i;
107 static void
108 emitfin(FILE *f, char *sec[3])
110 Asmbits *b;
111 char *p;
112 int lg, i;
113 double d;
115 if (!stash)
116 return;
117 fprintf(f, "/* floating point constants */\n");
118 for (lg=4; lg>=2; lg--)
119 for (b=stash, i=0; b; b=b->link, i++) {
120 if (b->size == (1<<lg)) {
121 fprintf(f,
122 ".section %s\n"
123 ".p2align %d\n"
124 "%sfp%d:",
125 sec[lg-2], lg, T.asloc, i
127 for (p=b->bits; p<&b->bits[b->size]; p+=4)
128 fprintf(f, "\n\t.int %"PRId32,
129 *(int32_t *)p);
130 if (lg <= 3) {
131 if (lg == 2)
132 d = *(float *)b->bits;
133 else
134 d = *(double *)b->bits;
135 fprintf(f, " /* %f */\n\n", d);
136 } else
137 fprintf(f, "\n\n");
140 while ((b=stash)) {
141 stash = b->link;
142 free(b);
146 void
147 elf_emitfin(FILE *f)
149 static char *sec[3] = { ".rodata", ".rodata", ".rodata" };
151 emitfin(f ,sec);
152 fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n");
155 void
156 elf_emitfnfin(char *fn, FILE *f)
158 fprintf(f, ".type %s, @function\n", fn);
159 fprintf(f, ".size %s, .-%s\n", fn, fn);
162 void
163 macho_emitfin(FILE *f)
165 static char *sec[3] = {
166 "__TEXT,__literal4,4byte_literals",
167 "__TEXT,__literal8,8byte_literals",
168 ".rodata", /* should not happen */
171 emitfin(f, sec);