emit.c (4724B)
1 #include "all.h" 2 3 enum { 4 SecText, 5 SecData, 6 SecBss, 7 }; 8 9 void 10 emitlnk(char *n, Lnk *l, int s, FILE *f) 11 { 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\"", 19 }; 20 char *pfx, *sfx; 21 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", 31 f 32 ); 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 39 ); 40 } 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); 53 } 54 55 void 56 emitfnlnk(char *n, Lnk *l, FILE *f) 57 { 58 emitlnk(n, l, SecText, f); 59 } 60 61 void 62 emitdat(Dat *d, FILE *f) 63 { 64 static char *dtoa[] = { 65 [DB] = "\t.byte", 66 [DH] = "\t.short", 67 [DW] = "\t.int", 68 [DL] = "\t.quad" 69 }; 70 static int64_t zero; 71 char *p; 72 73 switch (d->type) { 74 case DStart: 75 zero = 0; 76 break; 77 case DEnd: 78 if (d->lnk->common) { 79 if (zero == -1) 80 die("invalid common data definition"); 81 p = d->name[0] == '"' ? "" : T.assym; 82 fprintf(f, ".comm %s%s,%"PRId64, 83 p, d->name, zero); 84 if (d->lnk->align) 85 fprintf(f, ",%d", d->lnk->align); 86 fputc('\n', f); 87 } 88 else if (zero != -1) { 89 emitlnk(d->name, d->lnk, SecBss, f); 90 fprintf(f, "\t.fill %"PRId64",1,0\n", zero); 91 } 92 break; 93 case DZ: 94 if (zero != -1) 95 zero += d->u.num; 96 else 97 fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num); 98 break; 99 default: 100 if (zero != -1) { 101 emitlnk(d->name, d->lnk, SecData, f); 102 if (zero > 0) 103 fprintf(f, "\t.fill %"PRId64",1,0\n", zero); 104 zero = -1; 105 } 106 if (d->isstr) { 107 if (d->type != DB) 108 err("strings only supported for 'b' currently"); 109 fprintf(f, "\t.ascii %s\n", d->u.str); 110 } 111 else if (d->isref) { 112 p = d->u.ref.name[0] == '"' ? "" : T.assym; 113 fprintf(f, "%s %s%s%+"PRId64"\n", 114 dtoa[d->type], p, d->u.ref.name, 115 d->u.ref.off); 116 } 117 else { 118 fprintf(f, "%s %"PRId64"\n", 119 dtoa[d->type], d->u.num); 120 } 121 break; 122 } 123 } 124 125 typedef struct Asmbits Asmbits; 126 127 struct Asmbits { 128 char bits[16]; 129 int size; 130 Asmbits *link; 131 }; 132 133 static Asmbits *stash; 134 135 int 136 stashbits(void *bits, int size) 137 { 138 Asmbits **pb, *b; 139 int i; 140 141 assert(size == 4 || size == 8 || size == 16); 142 for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++) 143 if (size <= b->size) 144 if (memcmp(bits, b->bits, size) == 0) 145 return i; 146 b = emalloc(sizeof *b); 147 memcpy(b->bits, bits, size); 148 b->size = size; 149 b->link = 0; 150 *pb = b; 151 return i; 152 } 153 154 static void 155 emitfin(FILE *f, char *sec[3]) 156 { 157 Asmbits *b; 158 char *p; 159 int lg, i; 160 double d; 161 162 if (!stash) 163 return; 164 fprintf(f, "/* floating point constants */\n"); 165 for (lg=4; lg>=2; lg--) 166 for (b=stash, i=0; b; b=b->link, i++) { 167 if (b->size == (1<<lg)) { 168 fprintf(f, 169 ".section %s\n" 170 ".p2align %d\n" 171 "%sfp%d:", 172 sec[lg-2], lg, T.asloc, i 173 ); 174 for (p=b->bits; p<&b->bits[b->size]; p+=4) 175 fprintf(f, "\n\t.int %"PRId32, 176 *(int32_t *)p); 177 if (lg <= 3) { 178 if (lg == 2) 179 d = *(float *)b->bits; 180 else 181 d = *(double *)b->bits; 182 fprintf(f, " /* %f */\n\n", d); 183 } else 184 fprintf(f, "\n\n"); 185 } 186 } 187 while ((b=stash)) { 188 stash = b->link; 189 free(b); 190 } 191 } 192 193 void 194 elf_emitfin(FILE *f) 195 { 196 static char *sec[3] = { ".rodata", ".rodata", ".rodata" }; 197 198 emitfin(f ,sec); 199 fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n"); 200 } 201 202 void 203 elf_emitfnfin(char *fn, FILE *f) 204 { 205 fprintf(f, ".type %s, @function\n", fn); 206 fprintf(f, ".size %s, .-%s\n", fn, fn); 207 } 208 209 void 210 macho_emitfin(FILE *f) 211 { 212 static char *sec[3] = { 213 "__TEXT,__literal4,4byte_literals", 214 "__TEXT,__literal8,8byte_literals", 215 ".abort \"unreachable\"", 216 }; 217 218 emitfin(f, sec); 219 } 220 221 static uint32_t *file; 222 static uint nfile; 223 static uint curfile; 224 225 void 226 emitdbgfile(char *fn, FILE *f) 227 { 228 uint32_t id; 229 uint n; 230 231 id = intern(fn); 232 for (n=0; n<nfile; n++) 233 if (file[n] == id) { 234 /* gas requires positive 235 * file numbers */ 236 curfile = n + 1; 237 return; 238 } 239 if (!file) 240 file = vnew(0, sizeof *file, PHeap); 241 vgrow(&file, ++nfile); 242 file[nfile-1] = id; 243 curfile = nfile; 244 fprintf(f, ".file %u %s\n", curfile, fn); 245 } 246 247 void 248 emitdbgloc(uint line, uint col, FILE *f) 249 { 250 if (col != 0) 251 fprintf(f, "\t.loc %u %u %u\n", curfile, line, col); 252 else 253 fprintf(f, "\t.loc %u %u\n", curfile, line); 254 }