compiler_x64_hosted.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. #if defined(__APPLE__) && defined(__MACH__)
  55. system("clang -no-integrated-as -c /tmp/jit_out.s -o /tmp/jit_out.o -Xassembler -L");
  56. system("gobjcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin");
  57. #else
  58. system("as -L /tmp/jit_out.s -o /tmp/jit_out.o");
  59. system("objcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin");
  60. #endif
  61. stat("/tmp/jit_out.bin", &src_stat);
  62. generated_sz = src_stat.st_size;
  63. while (generated_sz>codesz) {
  64. codesz*=2;
  65. printf ("<compiler: doubling code block size to %d>\r\n",codesz);
  66. }
  67. FILE* binary_f = fopen("/tmp/jit_out.bin","r");
  68. uint32_t* jit_binary = mmap(0, codesz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  69. int bytes_read = fread(jit_binary,1,codesz,binary_f);
  70. fclose(binary_f);
  71. #ifdef DEBUG
  72. printf("<assembled bytes: %d at: %p (%s)>\n",bytes_read,jit_binary,defsym);
  73. char cmd[256];
  74. sprintf(cmd,"cp /tmp/jit_out.o /tmp/jit_%p_%s.o",jit_binary,defsym);
  75. system(cmd);
  76. sprintf(cmd,"cp /tmp/jit_out.s /tmp/jit_%p_%s.s",jit_binary,defsym);
  77. system(cmd);
  78. #endif
  79. if (bytes_read>codesz) {
  80. printf("<error: max assembly size of %d exhausted. aborting>\n",codesz);
  81. munmap(jit_binary,codesz);
  82. return 0;
  83. }
  84. // read symbols for linking lambdas
  85. #if defined(__APPLE__) && defined(__MACH__)
  86. system("gnm /tmp/jit_out.o > /tmp/jit_out.syms 2> /dev/null");
  87. #else
  88. system("nm /tmp/jit_out.o > /tmp/jit_out.syms");
  89. #endif
  90. FILE* link_f = fopen("/tmp/jit_out.syms","r");
  91. if (link_f) {
  92. char* link_line=malloc(128);
  93. while(fgets(link_line, 128, link_f)) {
  94. if (strlen(link_line)>22) {
  95. char ida=link_line[19];
  96. char idb=link_line[20];
  97. char idc=link_line[21];
  98. //printf("link_line: %s %c %c %c\n",link_line,ida,idb,idc);
  99. if (ida=='L' && idc=='_') {
  100. Cell* lambda = (Cell*)strtoul(&link_line[24], NULL, 16);
  101. if (idb=='0') {
  102. // function entrypoint
  103. uint64_t offset = strtoul(link_line, NULL, 16);
  104. void* binary = ((uint8_t*)jit_binary) + offset;
  105. //printf("function %p entrypoint: %p (+%ld)\n",lambda,binary,offset);
  106. if (lambda->tag == TAG_LAMBDA) {
  107. lambda->dr.next = binary;
  108. } else {
  109. printf("fatal error: no lambda found at %p!\n",lambda);
  110. }
  111. }
  112. else if (idb=='1') {
  113. // function exit
  114. //unsigned long long offset = strtoul(link_line, NULL, 16);
  115. //printf("function exit point: %p\n",offset);
  116. }
  117. }
  118. }
  119. }
  120. free(link_line);
  121. }
  122. int mp_res = mprotect(jit_binary, codesz, PROT_EXEC|PROT_READ);
  123. if (!mp_res) {
  124. *res = execute_jitted(jit_binary);
  125. } else {
  126. printf("<mprotect result: %d\n>",mp_res);
  127. *res = NULL;
  128. success = 0;
  129. }
  130. }
  131. return !!success;
  132. }