emit.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "all.h"
  2. enum {
  3. SecText,
  4. SecData,
  5. SecBss,
  6. };
  7. void
  8. emitlnk(char *n, Lnk *l, int s, FILE *f)
  9. {
  10. static char *sec[2][3] = {
  11. [0][SecText] = ".text",
  12. [0][SecData] = ".data",
  13. [0][SecBss] = ".bss",
  14. [1][SecText] = ".abort \"unreachable\"",
  15. [1][SecData] = ".section .tdata,\"awT\"",
  16. [1][SecBss] = ".section .tbss,\"awT\"",
  17. };
  18. char *pfx, *sfx;
  19. pfx = n[0] == '"' ? "" : T.assym;
  20. sfx = "";
  21. if (T.apple && l->thread) {
  22. l->sec = "__DATA";
  23. l->secf = "__thread_data,thread_local_regular";
  24. sfx = "$tlv$init";
  25. fputs(
  26. ".section __DATA,__thread_vars,"
  27. "thread_local_variables\n",
  28. f
  29. );
  30. fprintf(f, "%s%s:\n", pfx, n);
  31. fprintf(f,
  32. "\t.quad __tlv_bootstrap\n"
  33. "\t.quad 0\n"
  34. "\t.quad %s%s%s\n\n",
  35. pfx, n, sfx
  36. );
  37. }
  38. if (l->sec) {
  39. fprintf(f, ".section %s", l->sec);
  40. if (l->secf)
  41. fprintf(f, ",%s", l->secf);
  42. } else
  43. fputs(sec[l->thread != 0][s], f);
  44. fputc('\n', f);
  45. if (l->align)
  46. fprintf(f, ".balign %d\n", l->align);
  47. if (l->export)
  48. fprintf(f, ".globl %s%s\n", pfx, n);
  49. fprintf(f, "%s%s%s:\n", pfx, n, sfx);
  50. }
  51. void
  52. emitfnlnk(char *n, Lnk *l, FILE *f)
  53. {
  54. emitlnk(n, l, SecText, f);
  55. }
  56. void
  57. emitdat(Dat *d, FILE *f)
  58. {
  59. static struct {
  60. char decl[8];
  61. int64_t mask;
  62. } di[] = {
  63. [DB] = {"\t.byte", 0xffL},
  64. [DH] = {"\t.short", 0xffffL},
  65. [DW] = {"\t.int", 0xffffffffL},
  66. [DL] = {"\t.quad", -1L},
  67. };
  68. static int64_t zero;
  69. char *p;
  70. switch (d->type) {
  71. case DStart:
  72. zero = 0;
  73. break;
  74. case DEnd:
  75. if (d->lnk->common) {
  76. if (zero == -1)
  77. die("invalid common data definition");
  78. p = d->name[0] == '"' ? "" : T.assym;
  79. fprintf(f, ".comm %s%s,%"PRId64,
  80. p, d->name, zero);
  81. if (d->lnk->align)
  82. fprintf(f, ",%d", d->lnk->align);
  83. fputc('\n', f);
  84. }
  85. else if (zero != -1) {
  86. emitlnk(d->name, d->lnk, SecBss, f);
  87. fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
  88. }
  89. break;
  90. case DZ:
  91. if (zero != -1)
  92. zero += d->u.num;
  93. else
  94. fprintf(f, "\t.fill %"PRId64",1,0\n", d->u.num);
  95. break;
  96. default:
  97. if (zero != -1) {
  98. emitlnk(d->name, d->lnk, SecData, f);
  99. if (zero > 0)
  100. fprintf(f, "\t.fill %"PRId64",1,0\n", zero);
  101. zero = -1;
  102. }
  103. if (d->isstr) {
  104. if (d->type != DB)
  105. err("strings only supported for 'b' currently");
  106. fprintf(f, "\t.ascii %s\n", d->u.str);
  107. }
  108. else if (d->isref) {
  109. p = d->u.ref.name[0] == '"' ? "" : T.assym;
  110. fprintf(f, "%s %s%s%+"PRId64"\n",
  111. di[d->type].decl, p, d->u.ref.name,
  112. d->u.ref.off);
  113. }
  114. else {
  115. fprintf(f, "%s %"PRId64"\n",
  116. di[d->type].decl,
  117. d->u.num & di[d->type].mask);
  118. }
  119. break;
  120. }
  121. }
  122. typedef struct Asmbits Asmbits;
  123. struct Asmbits {
  124. bits n;
  125. int size;
  126. Asmbits *link;
  127. };
  128. static Asmbits *stash;
  129. int
  130. stashbits(bits n, int size)
  131. {
  132. Asmbits **pb, *b;
  133. int i;
  134. assert(size == 4 || size == 8 || size == 16);
  135. for (pb=&stash, i=0; (b=*pb); pb=&b->link, i++)
  136. if (size <= b->size && b->n == n)
  137. return i;
  138. b = emalloc(sizeof *b);
  139. b->n = n;
  140. b->size = size;
  141. b->link = 0;
  142. *pb = b;
  143. return i;
  144. }
  145. static void
  146. emitfin(FILE *f, char *sec[3])
  147. {
  148. Asmbits *b;
  149. int lg, i;
  150. union { int32_t i; float f; } u;
  151. if (!stash)
  152. return;
  153. fprintf(f, "/* floating point constants */\n");
  154. for (lg=4; lg>=2; lg--)
  155. for (b=stash, i=0; b; b=b->link, i++) {
  156. if (b->size == (1<<lg)) {
  157. fprintf(f,
  158. ".section %s\n"
  159. ".p2align %d\n"
  160. "%sfp%d:",
  161. sec[lg-2], lg, T.asloc, i
  162. );
  163. if (lg == 4)
  164. fprintf(f,
  165. "\n\t.quad %"PRId64
  166. "\n\t.quad 0\n\n",
  167. (int64_t)b->n);
  168. else if (lg == 3)
  169. fprintf(f,
  170. "\n\t.quad %"PRId64
  171. " /* %f */\n\n",
  172. (int64_t)b->n,
  173. *(double *)&b->n);
  174. else if (lg == 2) {
  175. u.i = b->n;
  176. fprintf(f,
  177. "\n\t.int %"PRId32
  178. " /* %f */\n\n",
  179. u.i, (double)u.f);
  180. }
  181. }
  182. }
  183. while ((b=stash)) {
  184. stash = b->link;
  185. free(b);
  186. }
  187. }
  188. void
  189. elf_emitfin(FILE *f)
  190. {
  191. static char *sec[3] = { ".rodata", ".rodata", ".rodata" };
  192. emitfin(f ,sec);
  193. fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n");
  194. }
  195. void
  196. elf_emitfnfin(char *fn, FILE *f)
  197. {
  198. fprintf(f, ".type %s, @function\n", fn);
  199. fprintf(f, ".size %s, .-%s\n", fn, fn);
  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. emitfin(f, sec);
  210. }
  211. void
  212. pe_emitfin(FILE *f)
  213. {
  214. static char *sec[3] = { ".rodata", ".rodata", ".rodata" };
  215. emitfin(f, sec);
  216. }
  217. static uint32_t *file;
  218. static uint nfile;
  219. static uint curfile;
  220. void
  221. emitdbgfile(char *fn, FILE *f)
  222. {
  223. uint32_t id;
  224. uint n;
  225. id = intern(fn);
  226. for (n=0; n<nfile; n++)
  227. if (file[n] == id) {
  228. /* gas requires positive
  229. * file numbers */
  230. curfile = n + 1;
  231. return;
  232. }
  233. if (!file)
  234. file = vnew(0, sizeof *file, PHeap);
  235. vgrow(&file, ++nfile);
  236. file[nfile-1] = id;
  237. curfile = nfile;
  238. fprintf(f, ".file %u %s\n", curfile, fn);
  239. }
  240. void
  241. emitdbgloc(uint line, uint col, FILE *f)
  242. {
  243. if (col != 0)
  244. fprintf(f, "\t.loc %u %u %u\n", curfile, line, col);
  245. else
  246. fprintf(f, "\t.loc %u %u\n", curfile, line);
  247. }