emit.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. char bits[16];
  121. int size;
  122. Asmbits *link;
  123. };
  124. static Asmbits *stash;
  125. int
  126. stashbits(void *bits, 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)
  133. if (memcmp(bits, b->bits, size) == 0)
  134. return i;
  135. b = emalloc(sizeof *b);
  136. memcpy(b->bits, bits, size);
  137. b->size = size;
  138. b->link = 0;
  139. *pb = b;
  140. return i;
  141. }
  142. static void
  143. emitfin(FILE *f, char *sec[3])
  144. {
  145. Asmbits *b;
  146. char *p;
  147. int lg, i;
  148. double d;
  149. if (!stash)
  150. return;
  151. fprintf(f, "/* floating point constants */\n");
  152. for (lg=4; lg>=2; lg--)
  153. for (b=stash, i=0; b; b=b->link, i++) {
  154. if (b->size == (1<<lg)) {
  155. fprintf(f,
  156. ".section %s\n"
  157. ".p2align %d\n"
  158. "%sfp%d:",
  159. sec[lg-2], lg, T.asloc, i
  160. );
  161. for (p=b->bits; p<&b->bits[b->size]; p+=4)
  162. fprintf(f, "\n\t.int %"PRId32,
  163. *(int32_t *)p);
  164. if (lg <= 3) {
  165. if (lg == 2)
  166. d = *(float *)b->bits;
  167. else
  168. d = *(double *)b->bits;
  169. fprintf(f, " /* %f */\n\n", d);
  170. } else
  171. fprintf(f, "\n\n");
  172. }
  173. }
  174. while ((b=stash)) {
  175. stash = b->link;
  176. free(b);
  177. }
  178. }
  179. void
  180. elf_emitfin(FILE *f)
  181. {
  182. static char *sec[3] = { ".rodata", ".rodata", ".rodata" };
  183. emitfin(f ,sec);
  184. fprintf(f, ".section .note.GNU-stack,\"\",@progbits\n");
  185. }
  186. void
  187. elf_emitfnfin(char *fn, FILE *f)
  188. {
  189. fprintf(f, ".type %s, @function\n", fn);
  190. fprintf(f, ".size %s, .-%s\n", fn, fn);
  191. }
  192. void
  193. macho_emitfin(FILE *f)
  194. {
  195. static char *sec[3] = {
  196. "__TEXT,__literal4,4byte_literals",
  197. "__TEXT,__literal8,8byte_literals",
  198. ".abort \"unreachable\"",
  199. };
  200. emitfin(f, sec);
  201. }
  202. static uint32_t *file;
  203. static uint nfile;
  204. static uint curfile;
  205. void
  206. emitdbgfile(char *fn, FILE *f)
  207. {
  208. uint32_t id;
  209. uint n;
  210. id = intern(fn);
  211. for (n=0; n<nfile; n++)
  212. if (file[n] == id) {
  213. /* gas requires positive
  214. * file numbers */
  215. curfile = n + 1;
  216. return;
  217. }
  218. if (!file)
  219. file = vnew(0, sizeof *file, PHeap);
  220. vgrow(&file, ++nfile);
  221. file[nfile-1] = id;
  222. curfile = nfile;
  223. fprintf(f, ".file %u %s\n", curfile, fn);
  224. }
  225. void
  226. emitdbgloc(uint line, uint col, FILE *f)
  227. {
  228. if (col != 0)
  229. fprintf(f, "\t.loc %u %u %u\n", curfile, line, col);
  230. else
  231. fprintf(f, "\t.loc %u %u\n", curfile, line);
  232. }