Mercurial
view third_party/luajit/src/host/buildvm_asm.c @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | 94705b5986b3 |
| children |
line wrap: on
line source
/* ** LuaJIT VM builder: Assembler source code emitter. ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h */ #include "buildvm.h" #include "lj_bc.h" /* ------------------------------------------------------------------------ */ #if LJ_TARGET_X86ORX64 /* Emit bytes piecewise as assembler text. */ static void emit_asm_bytes(BuildCtx *ctx, uint8_t *p, int n) { int i; for (i = 0; i < n; i++) { if ((i & 15) == 0) fprintf(ctx->fp, "\t.byte %d", p[i]); else fprintf(ctx->fp, ",%d", p[i]); if ((i & 15) == 15) putc('\n', ctx->fp); } if ((n & 15) != 0) putc('\n', ctx->fp); } /* Emit relocation */ static void emit_asm_reloc(BuildCtx *ctx, int type, const char *sym) { switch (ctx->mode) { case BUILD_elfasm: if (type) fprintf(ctx->fp, "\t.long %s-.-4\n", sym); else fprintf(ctx->fp, "\t.long %s\n", sym); break; case BUILD_coffasm: fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", sym); if (type) fprintf(ctx->fp, "\t.long %s-.-4\n", sym); else fprintf(ctx->fp, "\t.long %s\n", sym); break; default: /* BUILD_machasm for relative relocations handled below. */ fprintf(ctx->fp, "\t.long %s\n", sym); break; } } static const char *const jccnames[] = { "jo", "jno", "jb", "jnb", "jz", "jnz", "jbe", "ja", "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg" }; /* Emit x86/x64 text relocations. */ static void emit_asm_reloc_text(BuildCtx *ctx, uint8_t *cp, int n, const char *sym) { const char *opname = NULL; if (--n < 0) goto err; if (cp[n] == 0xe8) { opname = "call"; } else if (cp[n] == 0xe9) { opname = "jmp"; } else if (cp[n] >= 0x80 && cp[n] <= 0x8f && n > 0 && cp[n-1] == 0x0f) { opname = jccnames[cp[n]-0x80]; n--; } else { err: fprintf(stderr, "Error: unsupported opcode for %s symbol relocation.\n", sym); exit(1); } emit_asm_bytes(ctx, cp, n); if (strncmp(sym+(*sym == '_'), LABEL_PREFIX, sizeof(LABEL_PREFIX)-1)) { /* Various fixups for external symbols outside of our binary. */ if (ctx->mode == BUILD_elfasm) { if (LJ_32) fprintf(ctx->fp, "#if __PIC__\n\t%s lj_wrap_%s\n#else\n", opname, sym); fprintf(ctx->fp, "\t%s %s@PLT\n", opname, sym); if (LJ_32) fprintf(ctx->fp, "#endif\n"); return; } else if (LJ_32 && ctx->mode == BUILD_machasm) { fprintf(ctx->fp, "\t%s L%s$stub\n", opname, sym); return; } } fprintf(ctx->fp, "\t%s %s\n", opname, sym); } #else /* Emit words piecewise as assembler text. */ static void emit_asm_words(BuildCtx *ctx, uint8_t *p, int n) { int i; for (i = 0; i < n; i += 4) { uint32_t ins = *(uint32_t *)(p+i); #if LJ_TARGET_ARM64 && LJ_BE ins = lj_bswap(ins); /* ARM64 instructions are always little-endian. */ #endif if ((i & 15) == 0) fprintf(ctx->fp, "\t.long 0x%08x", ins); else fprintf(ctx->fp, ",0x%08x", ins); if ((i & 15) == 12) putc('\n', ctx->fp); } if ((n & 15) != 0) putc('\n', ctx->fp); } /* Emit relocation as part of an instruction. */ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n, const char *sym) { uint32_t ins; emit_asm_words(ctx, p, n-4); ins = *(uint32_t *)(p+n-4); #if LJ_TARGET_ARM if ((ins & 0xff000000u) == 0xfa000000u) { fprintf(ctx->fp, "\tblx %s\n", sym); } else if ((ins & 0x0e000000u) == 0x0a000000u) { fprintf(ctx->fp, "\t%s%.2s %s\n", (ins & 0x01000000u) ? "bl" : "b", &"eqnecsccmiplvsvchilsgeltgtle"[2*(ins >> 28)], sym); } else { fprintf(stderr, "Error: unsupported opcode %08x for %s symbol relocation.\n", ins, sym); exit(1); } #elif LJ_TARGET_ARM64 if ((ins >> 26) == 0x25u) { fprintf(ctx->fp, "\tbl %s\n", sym); } else { fprintf(stderr, "Error: unsupported opcode %08x for %s symbol relocation.\n", ins, sym); exit(1); } #elif LJ_TARGET_PPC #if LJ_TARGET_PS3 #define TOCPREFIX "." #else #define TOCPREFIX "" #endif if ((ins >> 26) == 16) { fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n", (ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym); } else if ((ins >> 26) == 18) { fprintf(ctx->fp, "\t%s " TOCPREFIX "%s\n", (ins & 1) ? "bl" : "b", sym); } else { fprintf(stderr, "Error: unsupported opcode %08x for %s symbol relocation.\n", ins, sym); exit(1); } #elif LJ_TARGET_MIPS fprintf(stderr, "Error: unsupported opcode %08x for %s symbol relocation.\n", ins, sym); exit(1); #else #error "missing relocation support for this architecture" #endif } #endif #if LJ_TARGET_ARM #define ELFASM_PX "%%" #else #define ELFASM_PX "@" #endif /* Emit an assembler label. */ static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc) { switch (ctx->mode) { case BUILD_elfasm: #if LJ_TARGET_PS3 if (!strncmp(name, "lj_vm_", 6) && strcmp(name, ctx->beginsym) && !strstr(name, "hook")) { fprintf(ctx->fp, "\n\t.globl %s\n" "\t.section \".opd\",\"aw\"\n" "%s:\n" "\t.long .%s,.TOC.@tocbase32\n" "\t.size %s,8\n" "\t.previous\n" "\t.globl .%s\n" "\t.hidden .%s\n" "\t.type .%s, " ELFASM_PX "function\n" "\t.size .%s, %d\n" ".%s:\n", name, name, name, name, name, name, name, name, size, name); break; } #endif fprintf(ctx->fp, "\n\t.globl %s\n" "\t.hidden %s\n" "\t.type %s, " ELFASM_PX "%s\n" "\t.size %s, %d\n" "%s:\n", name, name, name, isfunc ? "function" : "object", name, size, name); break; case BUILD_coffasm: fprintf(ctx->fp, "\n\t.globl %s\n", name); if (isfunc) fprintf(ctx->fp, "\t.def %s; .scl 3; .type 32; .endef\n", name); fprintf(ctx->fp, "%s:\n", name); break; case BUILD_machasm: fprintf(ctx->fp, "\n\t.private_extern %s\n" "\t.no_dead_strip %s\n" "%s:\n", name, name, name); break; default: break; } } /* Emit alignment. */ static void emit_asm_align(BuildCtx *ctx, int bits) { switch (ctx->mode) { case BUILD_elfasm: case BUILD_coffasm: fprintf(ctx->fp, "\t.p2align %d\n", bits); break; case BUILD_machasm: fprintf(ctx->fp, "\t.align %d\n", bits); break; default: break; } } /* ------------------------------------------------------------------------ */ /* Emit assembler source code. */ void emit_asm(BuildCtx *ctx) { int i, rel; fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch); fprintf(ctx->fp, "\t.text\n"); #if LJ_TARGET_MIPS32 && !LJ_ABI_SOFTFP fprintf(ctx->fp, "\t.module fp=32\n"); #endif #if LJ_TARGET_MIPS fprintf(ctx->fp, "\t.set nomips16\n\t.abicalls\n\t.set noreorder\n\t.set nomacro\n"); #endif emit_asm_align(ctx, 4); #if LJ_TARGET_PS3 emit_asm_label(ctx, ctx->beginsym, ctx->codesz, 0); #else emit_asm_label(ctx, ctx->beginsym, 0, 0); #endif if (ctx->mode != BUILD_machasm) fprintf(ctx->fp, ".Lbegin:\n"); #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND /* This should really be moved into buildvm_arm.dasc. */ #if LJ_ARCH_HASFPU fprintf(ctx->fp, ".fnstart\n" ".save {r5, r6, r7, r8, r9, r10, r11, lr}\n" ".vsave {d8-d15}\n" ".save {r4}\n" ".pad #28\n"); #else fprintf(ctx->fp, ".fnstart\n" ".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n" ".pad #28\n"); #endif #endif for (i = rel = 0; i < ctx->nsym; i++) { int32_t ofs = ctx->sym[i].ofs; int32_t next = ctx->sym[i+1].ofs; #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND && LJ_HASFFI if (!strcmp(ctx->sym[i].name, "lj_vm_ffi_call")) fprintf(ctx->fp, ".globl lj_err_unwind_arm\n" ".personality lj_err_unwind_arm\n" ".fnend\n" ".fnstart\n" ".save {r4, r5, r11, lr}\n" ".setfp r11, sp\n"); #endif emit_asm_label(ctx, ctx->sym[i].name, next - ofs, 1); while (rel < ctx->nreloc && ctx->reloc[rel].ofs <= next) { BuildReloc *r = &ctx->reloc[rel]; int n = r->ofs - ofs; #if LJ_TARGET_X86ORX64 if (r->type != 0 && (ctx->mode == BUILD_elfasm || ctx->mode == BUILD_machasm)) { emit_asm_reloc_text(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); } else { emit_asm_bytes(ctx, ctx->code+ofs, n); emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]); } ofs += n+4; #else emit_asm_wordreloc(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]); ofs += n; #endif rel++; } #if LJ_TARGET_X86ORX64 emit_asm_bytes(ctx, ctx->code+ofs, next-ofs); #else emit_asm_words(ctx, ctx->code+ofs, next-ofs); #endif } #if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND fprintf(ctx->fp, #if !LJ_HASFFI ".globl lj_err_unwind_arm\n" ".personality lj_err_unwind_arm\n" #endif ".fnend\n"); #endif fprintf(ctx->fp, "\n"); switch (ctx->mode) { case BUILD_elfasm: #if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA) fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); #endif #if LJ_TARGET_PPC && !LJ_TARGET_PS3 && !LJ_ABI_SOFTFP /* Hard-float ABI. */ fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); #endif /* fallthrough */ case BUILD_coffasm: fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident); break; case BUILD_machasm: fprintf(ctx->fp, "\t.cstring\n" "\t.ascii \"%s\\0\"\n", ctx->dasm_ident); break; default: break; } fprintf(ctx->fp, "\n"); }