emit.c 4.7 KB

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