qbe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }