compiler_x64_hosted.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //#define DEBUG
  2. Cell* execute_jitted(void* binary) {
  3. return (Cell*)((funcptr)binary)(0);
  4. }
  5. int compile_for_platform(Cell* expr, Cell** res) {
  6. int codesz = 8192;
  7. jit_out = fopen("/tmp/jit_out.s","w");
  8. jit_init();
  9. register void* sp asm ("sp"); // FIXME maybe unportable
  10. Frame empty_frame = {NULL, 0, 0, sp};
  11. int success = compile_expr(expr, &empty_frame, TAG_ANY);
  12. jit_ret();
  13. if (success) {
  14. fclose(jit_out);
  15. FILE* asm_f = fopen("/tmp/jit_out.s","r");
  16. uint32_t* jit_asm = malloc(64000);
  17. memset(jit_asm, 0, 64000);
  18. fread(jit_asm,1,63999,asm_f);
  19. fclose(asm_f);
  20. #ifdef DEBUG
  21. printf("\nJIT ---------------------\n%s-------------------------\n\n",jit_asm);
  22. #endif
  23. free(jit_asm);
  24. // prefix with arm-none-eabi- on ARM -mlittle-endian
  25. system("as /tmp/jit_out.s -o /tmp/jit_out.o");
  26. system("objcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin");
  27. FILE* binary_f = fopen("/tmp/jit_out.bin","r");
  28. uint32_t* jit_binary = mmap(0, codesz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  29. int bytes_read = fread(jit_binary,1,codesz,binary_f);
  30. fclose(binary_f);
  31. #ifdef DEBUG
  32. printf("<assembled bytes: %d at: %p>\n",bytes_read,jit_binary);
  33. char cmd[256];
  34. sprintf(cmd,"cp /tmp/jit_out.o /tmp/jit_%p.o",jit_binary);
  35. system(cmd);
  36. sprintf(cmd,"cp /tmp/jit_out.s /tmp/jit_%p.s",jit_binary);
  37. system(cmd);
  38. #endif
  39. if (bytes_read>codesz) {
  40. printf("<error: max assembly size of %d exhausted. aborting>\n",codesz);
  41. munmap(jit_binary,codesz);
  42. return 0;
  43. }
  44. // read symbols for linking lambdas
  45. system("nm /tmp/jit_out.o > /tmp/jit_out.syms");
  46. FILE* link_f = fopen("/tmp/jit_out.syms","r");
  47. if (link_f) {
  48. char link_line[128];
  49. while(fgets(link_line, sizeof(link_line), link_f)) {
  50. if (strlen(link_line)>22) {
  51. char ida=link_line[19];
  52. char idb=link_line[20];
  53. char idc=link_line[21];
  54. //printf("link_line: %s %c %c %c\n",link_line,ida,idb,idc);
  55. if (ida=='f' && idc=='_') {
  56. Cell* lambda = (Cell*)strtoul(&link_line[24], NULL, 16);
  57. if (idb=='0') {
  58. // function entrypoint
  59. // TODO: 64/32 bit
  60. unsigned long long offset = strtoul(link_line, NULL, 16);
  61. void* binary = ((uint8_t*)jit_binary) + offset;
  62. //printf("function %p entrypoint: %p (+%ld)\n",lambda,binary,offset);
  63. if (lambda->tag == TAG_LAMBDA) {
  64. lambda->next = binary;
  65. } else {
  66. printf("fatal error: no lambda found at %p!\n",lambda);
  67. }
  68. }
  69. else if (idb=='1') {
  70. // function exit
  71. unsigned long long offset = strtoul(link_line, NULL, 16);
  72. //printf("function exit point: %p\n",offset);
  73. }
  74. }
  75. }
  76. }
  77. }
  78. int mp_res = mprotect(jit_binary, codesz, PROT_EXEC|PROT_READ);
  79. if (!mp_res) {
  80. *res = execute_jitted(jit_binary);
  81. success = 1;
  82. } else {
  83. printf("<mprotect result: %d\n>",mp_res);
  84. *res = NULL;
  85. success = 0;
  86. }
  87. }
  88. return success;
  89. }