static int getpclabel(jitcompiler *jc, const void *target) { return dasm_getpclabel(jc, pclabel(jc, target)); }
/* 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; }
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 */ }