int build_code(Dst_DECL) { int ret = 0; size_t codesz = 0; uint8_t* code = NULL; int nglob = GLOB_MAX; void **glob = (void **)malloc(nglob*sizeof(void *)); memset(glob, 0, nglob*sizeof(void *)); dasm_init(Dst, DASM_MAXSECTION); dasm_setupglobal(Dst, glob, nglob); dasm_setup(Dst, build_actionlist); (void)create_backend(Dst); /* Finalize */ (void)dasm_checkstep(Dst, -1); /* sanity check */ if((ret = dasm_link(Dst, &codesz))) return ret; code = (uint8_t *)pa_malloc(codesz, true); if((ret = dasm_encode(Dst, (void *)code))) return ret; //write_raw("debug.out", code, codesz); dasm_gen_func fp = (dasm_gen_func)code; ret = fp(); printf("generated function return value = %d\n",ret); dasm_free(Dst); free(glob); free(code); return 0; }
static jitcompiler *newjitcompiler(mgroup *group) { jitcompiler *jc = malloc(sizeof(jitcompiler)); jc->group = group; jc->pclabel_count = 0; jc->lastlabelofs = -1; upb_inttable_init(&jc->pclabels, UPB_CTYPE_UINT32); upb_inttable_init(&jc->pcdefined, UPB_CTYPE_BOOL); upb_inttable_init(&jc->asmlabels, UPB_CTYPE_PTR); jc->globals = malloc(UPB_JIT_GLOBAL__MAX * sizeof(*jc->globals)); dasm_init(jc, 1); dasm_setupglobal(jc, jc->globals, UPB_JIT_GLOBAL__MAX); dasm_setup(jc, upb_jit_actionlist); return jc; }
/* Build the machine code. */ static int build_code(BuildCtx *ctx) { int status; int i; /* Initialize DynASM structures. */ ctx->nglob = GLOB__MAX; ctx->glob = (void **)malloc(ctx->nglob*sizeof(void *)); memset(ctx->glob, 0, ctx->nglob*sizeof(void *)); ctx->nreloc = 0; ctx->globnames = globnames; ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *)); ctx->nrelocsym = 0; for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1; ctx->dasm_ident = DASM_IDENT; ctx->dasm_arch = DASM_ARCH; dasm_init(Dst, DASM_MAXSECTION); dasm_setupglobal(Dst, ctx->glob, ctx->nglob); dasm_setup(Dst, build_actionlist); /* Call arch-specific backend to emit the code. */ ctx->npc = build_backend(ctx); /* Finalize the code. */ (void)dasm_checkstep(Dst, -1); if ((status = dasm_link(Dst, &ctx->codesz))) return status; ctx->code = (uint8_t *)malloc(ctx->codesz); if ((status = dasm_encode(Dst, (void *)ctx->code))) return status; /* Allocate symbol table and bytecode offsets. */ ctx->beginsym = sym_decorate(ctx, "", LABEL_PREFIX "vm_asm_begin"); ctx->sym = (BuildSym *)malloc((ctx->npc+ctx->nglob+1)*sizeof(BuildSym)); ctx->nsym = 0; ctx->bc_ofs = (int32_t *)malloc(ctx->npc*sizeof(int32_t)); /* Collect the opcodes (PC labels). */ for (i = 0; i < ctx->npc; i++) { int32_t ofs = dasm_getpclabel(Dst, i); if (ofs < 0) return 0x22000000|i; ctx->bc_ofs[i] = ofs; if ((LJ_HASJIT || !(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP || i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP)) && (LJ_HASFFI || i != BC_KCDATA)) sym_insert(ctx, ofs, LABEL_PREFIX_BC, bc_names[i]); } /* Collect the globals (named labels). */ for (i = 0; i < ctx->nglob; i++) { const char *gl = globnames[i]; int len = (int)strlen(gl); if (!ctx->glob[i]) { fprintf(stderr, "Error: undefined global %s\n", gl); exit(2); } /* Skip the _Z symbols. */ if (!(len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z')) sym_insert(ctx, (int32_t)((uint8_t *)(ctx->glob[i]) - ctx->code), LABEL_PREFIX, globnames[i]); } /* Close the address range. */ sym_insert(ctx, (int32_t)ctx->codesz, "", ""); ctx->nsym--; dasm_free(Dst); return 0; }
static bfprogram bf_compile(const char* program) { unsigned int loops[MAX_NESTING]; int nloops = 0; int n; // int nskip = 0; // uchar* tape_begin = state->tape; // uchar* ptr = state->tape; // uchar* tape_end = state->tape + TAPE_SIZE - 1; dasm_State* d; unsigned int npc = 8; unsigned int nextpc = 0; //|.arch a64 #if DASM_VERSION != 10300 #error "Version mismatch between DynASM and included encoding engine" #endif //|.section code #define DASM_SECTION_CODE 0 #define DASM_MAXSECTION 1 dasm_init(&d, DASM_MAXSECTION); //|.globals bf_ enum { bf_main, bf__MAX }; void* labels[bf__MAX]; dasm_setupglobal(&d, labels, bf__MAX); //|.actionlist bf_actions static const unsigned int bf_actions[87] = { 0x00010000, 0x00060014, 0xd10103ff, 0xa90053f3, 0xa9015bf5, 0xa90263f7, 0xf9001bfe, 0xaa0003f4, 0xf9400293, 0x00090d8a, 0xaa1303f5, 0x90000017, 0x000f0001, 0x8b170276, 0x00000000, 0x90000017, 0x000f0001, 0x8b170273, 0xeb16027f, 0x54000009, 0x00053001, 0x90000017, 0x000f0001, 0xcb170273, 0x0006000b, 0x00000000, 0x90000017, 0x000f0001, 0xcb170273, 0xeb15027f, 0x54000002, 0x00053001, 0x90000017, 0x000f0001, 0x8b170273, 0x0006000b, 0x00000000, 0x39400277, 0x00020000, 0x00000018, 0x000f0000, 0x0b1802f7, 0x39000277, 0x00000000, 0x39400277, 0x00020000, 0x00000018, 0x000f0000, 0x4b1802f7, 0x39000277, 0x00000000, 0xaa1403e0, 0xf9400297, 0x00090d8a, 0xd63f02e0, 0x39000260, 0x00000000, 0x39400261, 0xaa1403e0, 0xf9400297, 0x00090d8a, 0xd63f02e0, 0x00000000, 0x00020000, 0x00000017, 0x000f0000, 0x39000277, 0x00000000, 0x39400277, 0x710002ff, 0x54000000, 0x00073000, 0x00080000, 0x00000000, 0x39400277, 0x710002ff, 0x54000001, 0x00073000, 0x00080000, 0x00000000, 0xa94053f3, 0xa9415bf5, 0xa94263f7, 0xf9401bfe, 0x910103ff, 0xd65f03c0, 0x00000000 }; dasm_setup(&d, bf_actions); dasm_growpc(&d, npc); //|.define aPtr, x19 //|.define aState, x20 //|.define aTapeBegin, x21 //|.define aTapeEnd, x22 //|.define TMP, x23 //|.define TMP1, x24 //|.define TMPw, w23 //|.define TMP1w, w24 //|.define cArg1w, w0 //|.define cArg2w, w1 //|.define cRetw, w0 //|.define cArg1, x0 //|.define cArg2, x1 //|.define cRet, x0 //|.macro prologue //| sub sp, sp, #0x40 //| stp aPtr, aState, [sp] //| stp aTapeBegin, aTapeEnd, [sp, #0x10] //| stp TMP, TMP1, [sp, #0x20] //| str lr, [sp, #0x30] //| mov aState, cArg1 //|.endmacro //|.macro epilogue //| ldp aPtr, aState, [sp] //| ldp aTapeBegin, aTapeEnd, [sp, #0x10] //| ldp TMP, TMP1, [sp, #0x20] //| ldr lr, [sp, #0x30] //| add sp, sp, #0x40 //| ret //|.endmacro const char* p = program; //|.type bfstate, bf_state_t, aState #define Dt1(_V) (int)(ptrdiff_t)&(((bf_state_t *)0)_V) dasm_State** Dst = &d; //|.code dasm_put(Dst, 0); //|->main: //| prologue //| ldr aPtr, bfstate->tape //| mov aTapeBegin, aPtr //| mov TMP, #TAPE_SIZE - 1 //| add aTapeEnd, aPtr, TMP dasm_put(Dst, 1, (long)(Dt1(->tape)), (long)(TAPE_SIZE - 1)); while (1) { switch (*p++) { case '>': for (n=1; *p == '>'; n++, p++); // ptr += n; // while (ptr > tape_end) // ptr -= TAPE_SIZE; //| mov TMP, #(n%TAPE_SIZE) //| add aPtr, aPtr, TMP //| cmp aPtr, aTapeEnd //| b.ls >1 //| mov TMP, #TAPE_SIZE //| sub aPtr, aPtr, TMP //|1: dasm_put(Dst, 15, (long)((n%TAPE_SIZE)), (long)(TAPE_SIZE)); break; case '<': for (n=1; *p == '<'; n++, p++); //ptr -= n; //while (ptr < tape_begin) // ptr += TAPE_SIZE; //| mov TMP, #(n%TAPE_SIZE) //| sub aPtr, aPtr, TMP //| cmp aPtr, aTapeBegin //| b.hs >1 //| mov TMP, #TAPE_SIZE //| add aPtr, aPtr, TMP //|1: dasm_put(Dst, 26, (long)((n%TAPE_SIZE)), (long)(TAPE_SIZE)); break; case '+': for (n=1; *p == '+'; n++, p++); //*ptr += n; //| ldrb TMPw, [aPtr] //| mov TMP1w, #n //| add TMPw, TMPw, TMP1w //| strb TMPw, [aPtr] dasm_put(Dst, 37, (long)(n)); break; case '-': for (n=1; *p == '-'; n++, p++); //*ptr -= n; //| ldrb TMPw, [aPtr] //| mov TMP1w, #n //| sub TMPw, TMPw, TMP1w //| strb TMPw, [aPtr] dasm_put(Dst, 44, (long)(n)); break; case ',': //*ptr = state->get_ch(state); //| mov cArg1, aState //| ldr TMP, bfstate->get_ch //| blr TMP //| strb cRetw, [aPtr] dasm_put(Dst, 51, (long)(Dt1(->get_ch))); break; case '.': //state->put_ch(state, *ptr); //| ldrb cArg2w, [aPtr] //| mov cArg1, aState //| ldr TMP, bfstate->put_ch //| blr TMP dasm_put(Dst, 57, (long)(Dt1(->put_ch))); break; case '[': if (nloops == MAX_NESTING) bad_program("Nesting too deep"); //if (*ptr) { // loops[nloops++] = p; // break; //} //nskip = 1; //while (nskip > 0) { // switch (*p++) { // case '[': nskip++; break; // case ']': nskip--; break; // case '\0': // bad_program("end of file when there's open '['"); // break; // //ignore all other instruction. // } //} if (p[0] == '-' && p[1] == ']') { p += 2; //| mov TMPw, #0 //| strb TMPw, [aPtr] dasm_put(Dst, 63, (long)(0)); } else { if (nextpc == npc) { npc *= 2; dasm_growpc(&d, npc); } //| ldrb TMPw, [aPtr] //| cmp TMPw, #0 //| b.eq =>nextpc + 1 //|=>nextpc: dasm_put(Dst, 68, (long)(nextpc + 1), (long)(nextpc)); loops[nloops++] = nextpc; nextpc += 2; } break; case ']': if (nloops <= 0) bad_program("] has no matched ["); //if (*ptr) { // p = loops[nloops-1]; //} else { // nloops --; //} --nloops; //| ldrb TMPw, [aPtr] //| cmp TMPw, #0 //| b.ne =>loops[nloops] //|=>loops[nloops]+1: dasm_put(Dst, 74, (long)(loops[nloops]), (long)(loops[nloops]+1)); break; case '\0': if (nloops > 0) bad_program("end of file where there's open '['"); // return; //| epilogue dasm_put(Dst, 80); link_and_encode(&d); dasm_free(&d); return (bfprogram)labels[bf_main]; //ignore all other instruction. } } }
static void _new_env(dasm_State **state, const void *actionlist){ dasm_init(state, 1); dasm_setupglobal(Dst, labels, SPROTO_CODE__MAX); dasm_setup(state, actionlist); maxpc = 0; }
SRE_API sre_int_t sre_vm_thompson_jit_compile(sre_pool_t *pool, sre_program_t *prog, sre_vm_thompson_code_t **pcode) { #if (SRE_TARGET != SRE_ARCH_X64) return SRE_DECLINED; #else int status; size_t codesz; size_t size; unsigned char *mem; dasm_State *dasm; void **glob; unsigned nglobs = SRE_VM_THOMPSON_GLOB__MAX; sre_vm_thompson_code_t *code; glob = sre_pcalloc(pool, nglobs * sizeof(void *)); if (glob == NULL) { return SRE_ERROR; } dasm_init(&dasm, 1); dasm_setupglobal(&dasm, glob, nglobs); dasm_setup(&dasm, sre_vm_thompson_jit_actions); dd("thread size: %d", (int) sizeof(sre_vm_thompson_thread_t)); if (sre_vm_thompson_jit_do_compile(&dasm, pool, prog) != SRE_OK) { dasm_free(&dasm); return SRE_ERROR; } status = dasm_link(&dasm, &codesz); if (status != DASM_S_OK) { dasm_free(&dasm); return SRE_ERROR; } size = codesz + sizeof(sre_vm_thompson_code_t); dd("size: %d, codesiz: %d", (int) size, (int) codesz); mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); if (mem == MAP_FAILED) { perror("mmap"); dasm_free(&dasm); return SRE_ERROR; } code = (sre_vm_thompson_code_t *) mem; code->size = size; code->handler = (sre_vm_thompson_exec_pt) (mem + sizeof(sre_vm_thompson_code_t)); *pcode = code; dasm_encode(&dasm, code->handler); #if (DDEBUG) { int i; int len; FILE *f; const char *gl; /* * write generated machine code to a temporary file. * wiew with objdump or ndisasm */ f = fopen("/tmp/thompson-jit.bin", "wb"); fwrite(code->handler, codesz, 1, f); fclose(f); f = fopen("/tmp/thompson-jit.txt", "w"); fprintf(f, "code section: start=%p len=%lu\n", code->handler, (unsigned long) codesz); fprintf(f, "global names:\n"); for (i = 0; i < nglobs; i++) { gl = sre_vm_thompson_jit_global_names[i]; len = (int) strlen(gl); if (!glob[i]) { continue; } /* Skip the _Z symbols. */ if (!(len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z')) { fprintf(f, " %s => %p\n", gl, glob[i]); } } fprintf(f, "\npc labels:\n"); for (i = 0; i < dasm->pcsize; i++) { int32_t ofs = dasm_getpclabel(&dasm, i); if (ofs >= 0) { fprintf(f, " %d => %ld\n", i, (long) ofs); } } fclose(f); } #endif dasm_free(&dasm); if (mprotect(mem, size, PROT_EXEC | PROT_READ) != 0) { (void) munmap(code, code->size); return SRE_ERROR; } dd("code start addr: %p", code->handler); return SRE_OK; #endif /* SRE_TARGET == SRE_ARCH_X64 */ }