qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

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 }