check that data alignment is in range and a power of two
[qbe.git] / emit.c
blob490628e786ebbfaef314ef93a88c02b18469e252
1 #include "all.h"
3 enum {
4 SecText,
5 SecData,
6 SecBss,
7 };
9 void
10 emitlnk(char *n, Lnk *l, int s, FILE *f)
12 static char *sec[2][3] = {
13 [0][SecText] = ".text",
14 [0][SecData] = ".data",
15 [0][SecBss] = ".bss",
16 [1][SecText] = ".abort \"unreachable\"",
17 [1][SecData] = ".section .tdata,\"awT\"",
18 [1][SecBss] = ".section .tbss,\"awT\"",
20 char *pfx, *sfx;
22 pfx = n[0] == '"' ? "" : T.assym;
23 sfx = "";
24 if (T.apple && l->thread) {
25 l->sec = "__DATA";
26 l->secf = "__thread_data,thread_local_regular";
27 sfx = "$tlv$init";
28 fputs(
29 ".section __DATA,__thread_vars,"
30 "thread_local_variables\n",
33 fprintf(f, "%s%s:\n", pfx, n);
34 fprintf(f,
35 "\t.quad __tlv_bootstrap\n"
36 "\t.quad 0\n"
37 "\t.quad %s%s%s\n\n",
38 pfx, n, sfx
41 if (l->sec) {
42 fprintf(f, ".section %s", l->sec);
43 if (l->secf)
44 fprintf(f, ",%s", l->secf);
45 } else
46 fputs(sec[l->thread != 0][s], f);
47 fputc('\n', f);
48 if (l->align)
49 fprintf(f, ".balign %d\n", l->align);
50 if (l->export)
51 fprintf(f, ".globl %s%s\n", pfx, n);
52 fprintf(f, "%s%s%s:\n", pfx, n, sfx);
55 void
56 emitfnlnk(char *n, Lnk *l, FILE *f)
58 emitlnk(n, l, SecText, f);
61 void
62 emitdat(Dat *d, FILE *f)
64 static char *dtoa[] = {
65 [DB] = "\t.byte",
66 [DH] = "\t.short",
67 [DW] = "\t.int",
68 [DL] = "\t.quad"
70 static int64_t zero;
71 char *p;
73 switch (d->type) {
74 case DStart:
75 zero = 0;
76 break;
77 case DEnd:
78 if (zero != -1) {
79 emitlnk(d->name, d->lnk, SecBss, f);
80 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
82 break;
83 case DZ:
84 if (zero != -1)
85 zero += d->u.num;
86 else
87 fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num);
88 break;
89 default:
90 if (zero != -1) {
91 emitlnk(d->name, d->lnk, SecData, f);
92 if (zero > 0)
93 fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
94 zero = -1;
96 if (d->isstr) {
97 if (d->type != DB)
98 err("strings only supported for 'b' currently");
99 fprintf(f, "\t.ascii %s\n", d->u.str);
101 else if (d->isref) {
102 p = d->u.ref.name[0] == '"' ? "" : T.assym;
103 fprintf(f, "%s %s%s%+"PRId64"\n",
104 dtoa[d->type], p, d->u.ref.name,
105 d->u.ref.off);
107 else {
108 fprintf(f, "%s %"PRId64"\n",
109 dtoa[d->type], d->u.num);
111 break;
115 typedef struct Asmbits Asmbits;
117 struct Asmbits {
118 char bits[16];
119 int size;
120 Asmbits *link;
123 static Asmbits *stash;
126 stashbits(void *bits, int size)
128 Asmbits **pb, *b;
129 int i;
131 assert(size == 4 || size == 8 || size == 16);
132 for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++)
133 if (size <= b->size)
134 if (memcmp(bits, b->bits, size) == 0)
135 return i;
136 b = emalloc(sizeof *b);
137 memcpy(b->bits, bits, size);
138 b->size = size;
139 b->link = 0;
140 *pb = b;
141 return i;
144 static void
145 emitfin(FILE *f, char *sec[3])
147 Asmbits *b;
148 char *p;
149 int lg, i;
150 double d;
152 if (!stash)
153 return;
154 fprintf(f, "/* floating point constants */\n");
155 for (lg=4; lg>=2; lg--)
156 for (b=stash, i=0; b; b=b->link, i++) {
157 if (b->size == (1<<lg)) {
158 fprintf(f,
159 ".section %s\n"
160 ".p2align %d\n"
161 "%sfp%d:",
162 sec[lg-2], lg, T.asloc, i
164 for (p=b->bits; p<&b->bits[b->size]; p+=4)
165 fprintf(f, "\n\t.int %"PRId32,
166 *(int32_t *)p);
167 if (lg <= 3) {
168 if (lg == 2)
169 d = *(float *)b->bits;
170 else
171 d = *(double *)b->bits;
172 fprintf(f, " /* %f */\n\n", d);
173 } else
174 fprintf(f, "\n\n");
177 while ((b=stash)) {
178 stash = b->link;
179 free(b);
183 void
184 elf_emitfin(FILE *f)
186 static char *sec[3] = { ".rodata", ".rodata", ".rodata" };
188 emitfin(f ,sec);
189 fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n");
192 void
193 elf_emitfnfin(char *fn, FILE *f)
195 fprintf(f, ".type %s, @function\n", fn);
196 fprintf(f, ".size %s, .-%s\n", fn, fn);
199 void
200 macho_emitfin(FILE *f)
202 static char *sec[3] = {
203 "__TEXT,__literal4,4byte_literals",
204 "__TEXT,__literal8,8byte_literals",
205 ".abort \"unreachable\"",
208 emitfin(f, sec);
211 static uint32_t *file;
212 static uint nfile;
213 static uint curfile;
215 void
216 emitdbgfile(char *fn, FILE *f)
218 uint32_t id;
219 uint n;
221 id = intern(fn);
222 for (n=0; n<nfile; n++)
223 if (file[n] == id) {
224 /* gas requires positive
225 * file numbers */
226 curfile = n + 1;
227 return;
229 if (!file)
230 file = vnew(0, sizeof *file, PHeap);
231 vgrow(&file, ++nfile);
232 file[nfile-1] = id;
233 curfile = nfile;
234 fprintf(f, ".file %u %s\n", curfile, fn);
237 void
238 emitdbgloc(uint line, uint col, FILE *f)
240 if (col != 0)
241 fprintf(f, "\t.loc %u %u %u\n", curfile, line, col);
242 else
243 fprintf(f, "\t.loc %u %u\n", curfile, line);