emit.c (4470B)
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 = d->lnk->common ? -1 : 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); 81 } 82 break; 83 case DZ: 84 if (zero != -1) 85 zero += d->u.num; 86 else if (d->lnk->common) 87 fprintf(f, "\t.comm %s,%"PRId64"\n", d->name, d->u.num); 88 else 89 fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num); 90 break; 91 default: 92 if (zero != -1) { 93 emitlnk(d->name, d->lnk, SecData, f); 94 if (zero > 0) 95 fprintf(f, "\t.fill %"PRId64",1,0\n", zero); 96 zero = -1; 97 } 98 if (d->isstr) { 99 if (d->type != DB) 100 err("strings only supported for 'b' currently"); 101 fprintf(f, "\t.ascii %s\n", d->u.str); 102 } 103 else if (d->isref) { 104 p = d->u.ref.name[0] == '"' ? "" : T.assym; 105 fprintf(f, "%s %s%s%+"PRId64"\n", 106 dtoa[d->type], p, d->u.ref.name, 107 d->u.ref.off); 108 } 109 else { 110 fprintf(f, "%s %"PRId64"\n", 111 dtoa[d->type], d->u.num); 112 } 113 break; 114 } 115 } 116 117 typedef struct Asmbits Asmbits; 118 119 struct Asmbits { 120 char bits[16]; 121 int size; 122 Asmbits *link; 123 }; 124 125 static Asmbits *stash; 126 127 int 128 stashbits(void *bits, int size) 129 { 130 Asmbits **pb, *b; 131 int i; 132 133 assert(size == 4 || size == 8 || size == 16); 134 for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++) 135 if (size <= b->size) 136 if (memcmp(bits, b->bits, size) == 0) 137 return i; 138 b = emalloc(sizeof *b); 139 memcpy(b->bits, bits, size); 140 b->size = size; 141 b->link = 0; 142 *pb = b; 143 return i; 144 } 145 146 static void 147 emitfin(FILE *f, char *sec[3]) 148 { 149 Asmbits *b; 150 char *p; 151 int lg, i; 152 double d; 153 154 if (!stash) 155 return; 156 fprintf(f, "/* floating point constants */\n"); 157 for (lg=4; lg>=2; lg--) 158 for (b=stash, i=0; b; b=b->link, i++) { 159 if (b->size == (1<<lg)) { 160 fprintf(f, 161 ".section %s\n" 162 ".p2align %d\n" 163 "%sfp%d:", 164 sec[lg-2], lg, T.asloc, i 165 ); 166 for (p=b->bits; p<&b->bits[b->size]; p+=4) 167 fprintf(f, "\n\t.int %"PRId32, 168 *(int32_t *)p); 169 if (lg <= 3) { 170 if (lg == 2) 171 d = *(float *)b->bits; 172 else 173 d = *(double *)b->bits; 174 fprintf(f, " /* %f */\n\n", d); 175 } else 176 fprintf(f, "\n\n"); 177 } 178 } 179 while ((b=stash)) { 180 stash = b->link; 181 free(b); 182 } 183 } 184 185 void 186 elf_emitfin(FILE *f) 187 { 188 static char *sec[3] = { ".rodata", ".rodata", ".rodata" }; 189 190 emitfin(f ,sec); 191 fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n"); 192 } 193 194 void 195 elf_emitfnfin(char *fn, FILE *f) 196 { 197 fprintf(f, ".type %s, @function\n", fn); 198 fprintf(f, ".size %s, .-%s\n", fn, fn); 199 } 200 201 void 202 macho_emitfin(FILE *f) 203 { 204 static char *sec[3] = { 205 "__TEXT,__literal4,4byte_literals", 206 "__TEXT,__literal8,8byte_literals", 207 ".abort \"unreachable\"", 208 }; 209 210 emitfin(f, sec); 211 } 212 213 static uint32_t *file; 214 static uint nfile; 215 static uint curfile; 216 217 void 218 emitdbgfile(char *fn, FILE *f) 219 { 220 uint32_t id; 221 uint n; 222 223 id = intern(fn); 224 for (n=0; n<nfile; n++) 225 if (file[n] == id) { 226 /* gas requires positive 227 * file numbers */ 228 curfile = n + 1; 229 return; 230 } 231 if (!file) 232 file = vnew(0, sizeof *file, PHeap); 233 vgrow(&file, ++nfile); 234 file[nfile-1] = id; 235 curfile = nfile; 236 fprintf(f, ".file %u %s\n", curfile, fn); 237 } 238 239 void 240 emitdbgloc(uint loc, FILE *f) 241 { 242 fprintf(f, "\t.loc %u %u\n", curfile, loc); 243 }