int compile_for_platform(Cell* expr, Cell** res) { jit_out = fopen("/tmp/jit_out.s","w"); jit_init(); register void* sp asm ("sp"); Frame empty_frame = {NULL, 0, 0, sp}; int success = compile_expr(expr, &empty_frame, TAG_ANY); jit_ret(); if (!success) { printf("<compile_expr failed: %d>\r\n",success); } if (success) { int codesz = 1024; fclose(jit_out); struct stat src_stat; stat("/tmp/jit_out.s", &src_stat); off_t generated_sz = src_stat.st_size; FILE* asm_f = fopen("/tmp/jit_out.s","r"); uint32_t* jit_asm = malloc(generated_sz); memset(jit_asm,0,generated_sz); fread(jit_asm,1,generated_sz,asm_f); fclose(asm_f); #ifdef DEBUG printf("\nJIT ---------------------\n%s-------------------------\n\n",jit_asm); #endif free(jit_asm); // prefix with arm-none-eabi- on ARM -mlittle-endian system("as -L /tmp/jit_out.s -o /tmp/jit_out.o"); #if defined(__APPLE__) && defined(__MACH__) system("gobjcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin"); #else system("objcopy /tmp/jit_out.o -O binary /tmp/jit_out.bin"); #endif stat("/tmp/jit_out.bin", &src_stat); generated_sz = src_stat.st_size; while (generated_sz>codesz) { codesz*=2; printf ("<compiler: doubling code block size to %d>\r\n",codesz); } FILE* binary_f = fopen("/tmp/jit_out.bin","r"); uint32_t* jit_binary = mmap(0, codesz, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); int bytes_read = fread(jit_binary,1,codesz,binary_f); fclose(binary_f); #ifdef DEBUG printf("<assembled bytes: %d at: %p>\n",bytes_read,jit_binary); char cmd[256]; sprintf(cmd,"cp /tmp/jit_out.o /tmp/jit_%p.o",jit_binary); system(cmd); sprintf(cmd,"cp /tmp/jit_out.s /tmp/jit_%p.s",jit_binary); system(cmd); #endif if (bytes_read>codesz) { printf("<error: max assembly size of %d exhausted. aborting>\n",codesz); munmap(jit_binary,codesz); return 0; } // read symbols for linking lambdas #if defined(__APPLE__) && defined(__MACH__) system("gnm /tmp/jit_out.o > /tmp/jit_out.syms 2> /dev/null"); #else system("nm /tmp/jit_out.o > /tmp/jit_out.syms"); #endif FILE* link_f = fopen("/tmp/jit_out.syms","r"); if (link_f) { char* link_line=malloc(128); while(fgets(link_line, 128, link_f)) { if (strlen(link_line)>22) { char ida=link_line[19]; char idb=link_line[20]; char idc=link_line[21]; //printf("link_line: %s %c %c %c\n",link_line,ida,idb,idc); if (ida=='L' && idc=='_') { Cell* lambda = (Cell*)strtoul(&link_line[24], NULL, 16); if (idb=='0') { // function entrypoint // TODO: 64/32 bit unsigned long long offset = strtoul(link_line, NULL, 16); void* binary = ((uint8_t*)jit_binary) + offset; //printf("function %p entrypoint: %p (+%ld)\n",lambda,binary,offset); if (lambda->tag == TAG_LAMBDA) { lambda->dr.next = binary; } else { printf("fatal error: no lambda found at %p!\n",lambda); } } else if (idb=='1') { // function exit unsigned long long offset = strtoul(link_line, NULL, 16); //printf("function exit point: %p\n",offset); } } } } free(link_line); } int mp_res = mprotect(jit_binary, codesz, PROT_EXEC|PROT_READ); if (!mp_res) { *res = execute_jitted(jit_binary); success = 1; } else { printf("<mprotect result: %d\n>",mp_res); *res = NULL; success = 0; } } return success; }
jit_initializer() { jit_init(); }