compiler_x64_hosted.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #if defined(__APPLE__) && defined(__MACH__)
  2. #define MAP_ANONYMOUS MAP_ANON
  3. #endif
  4. //#define DEBUG
  5. #include <sys/mman.h> // mprotect
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. Cell* execute_jitted(void* binary) {
  10. return (Cell*)((funcptr)binary)(0);
  11. }
  12. int compile_for_platform(Cell* expr, Cell** res) {
  13. jit_out = fopen("/tmp/jit_out.s","w");
  14. jit_init();
  15. register void* sp asm ("sp");
  16. Frame* empty_frame = malloc(sizeof(Frame)); // FIXME leak
  17. empty_frame->f=NULL;
  18. empty_frame->sp=0;
  19. empty_frame->locals=0;
  20. empty_frame->stack_end=sp;
  21. empty_frame->parent_frame=NULL;
  22. Cell* success = compile_expr(expr, empty_frame, prototype_any);
  23. jit_ret();
  24. char* defsym = "anon";
  25. if (!success) {
  26. printf("<compile_expr failed: %p>\r\n",success);
  27. }
  28. if (success) {
  29. int codesz = 1024;
  30. fclose(jit_out);
  31. struct stat src_stat;
  32. stat("/tmp/jit_out.s", &src_stat);
  33. off_t generated_sz = src_stat.st_size;
  34. if (expr && expr->tag == TAG_CONS && car(expr)->tag == TAG_SYM) {
  35. if (!strcmp(car(expr)->ar.addr,"def")) {
  36. defsym = car(cdr(expr))->ar.addr;
  37. char cpcmd[256];
  38. printf("compiled def %s\r\n",defsym);
  39. snprintf(cpcmd,255,"cp /tmp/jit_out.s /tmp/jit_out_%s.s",defsym);
  40. system(cpcmd);
  41. }
  42. }
  43. #ifdef DEBUG
  44. FILE* asm_f = fopen("/tmp/jit_out.s","r");
  45. char* jit_asm = malloc(generated_sz+1);
  46. memset(jit_asm,0,generated_sz+1);
  47. int read = fread(jit_asm,1,generated_sz,asm_f);
  48. fclose(asm_f);
  49. printf("read: %d\n",read);
  50. printf("\nJIT ---------------------\n%s\n-------------------------\n\n",jit_asm);
  51. free(jit_asm);
  52. #endif
  53. // prefix with arm-none-eabi- on ARM -mlittle-endian
  54. system("as -L /tmp/jit_out.s -o /tmp/jit_out.o");
  55. #if defined(__APPLE__) && defined(__MACH__)
  56. system("gobjcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin");
  57. #else
  58. system("objcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin");
  59. #endif
  60. stat("/tmp/jit_out.bin", &src_stat);
  61. generated_sz = src_stat.st_size;
  62. while (generated_sz>codesz) {
  63. codesz*=2;
  64. printf ("<compiler: doubling code block size to %d>\r\n",codesz);
  65. }
  66. FILE* binary_f = fopen("/tmp/jit_out.bin","r");
  67. uint32_t* jit_binary = mmap(0, codesz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  68. int bytes_read = fread(jit_binary,1,codesz,binary_f);
  69. fclose(binary_f);
  70. #ifdef DEBUG
  71. printf("<assembled bytes: %d at: %p (%s)>\n",bytes_read,jit_binary,defsym);
  72. char cmd[256];
  73. sprintf(cmd,"cp /tmp/jit_out.o /tmp/jit_%p_%s.o",jit_binary,defsym);
  74. system(cmd);
  75. sprintf(cmd,"cp /tmp/jit_out.s /tmp/jit_%p_%s.s",jit_binary,defsym);
  76. system(cmd);
  77. #endif
  78. if (bytes_read>codesz) {
  79. printf("<error: max assembly size of %d exhausted. aborting>\n",codesz);
  80. munmap(jit_binary,codesz);
  81. return 0;
  82. }
  83. // read symbols for linking lambdas
  84. #if defined(__APPLE__) && defined(__MACH__)
  85. system("gnm /tmp/jit_out.o > /tmp/jit_out.syms 2> /dev/null");
  86. #else
  87. system("nm /tmp/jit_out.o > /tmp/jit_out.syms");
  88. #endif
  89. FILE* link_f = fopen("/tmp/jit_out.syms","r");
  90. if (link_f) {
  91. char* link_line=malloc(128);
  92. while(fgets(link_line, 128, link_f)) {
  93. if (strlen(link_line)>22) {
  94. char ida=link_line[19];
  95. char idb=link_line[20];
  96. char idc=link_line[21];
  97. //printf("link_line: %s %c %c %c\n",link_line,ida,idb,idc);
  98. if (ida=='L' && idc=='_') {
  99. Cell* lambda = (Cell*)strtoul(&link_line[24], NULL, 16);
  100. if (idb=='0') {
  101. // function entrypoint
  102. uint64_t offset = strtoul(link_line, NULL, 16);
  103. void* binary = ((uint8_t*)jit_binary) + offset;
  104. //printf("function %p entrypoint: %p (+%ld)\n",lambda,binary,offset);
  105. if (lambda->tag == TAG_LAMBDA) {
  106. lambda->dr.next = binary;
  107. } else {
  108. printf("fatal error: no lambda found at %p!\n",lambda);
  109. }
  110. }
  111. else if (idb=='1') {
  112. // function exit
  113. //unsigned long long offset = strtoul(link_line, NULL, 16);
  114. //printf("function exit point: %p\n",offset);
  115. }
  116. }
  117. }
  118. }
  119. free(link_line);
  120. }
  121. int mp_res = mprotect(jit_binary, codesz, PROT_EXEC|PROT_READ);
  122. if (!mp_res) {
  123. *res = execute_jitted(jit_binary);
  124. } else {
  125. printf("<mprotect result: %d\n>",mp_res);
  126. *res = NULL;
  127. success = 0;
  128. }
  129. }
  130. return !!success;
  131. }