nx_x86_64.nx
buildroot/runtime/nx_x86_64.nx
about
nx_x86_64.nx -- x86_64 Linux SysV asm emitter (foundation; session 1).
Pure NishiLang port of nxc2/x86_64.c. Lives outside the C side per
cardinal feedback-no-nxc2-c-extension-only-nishilang-forward. This
file is the FOUNDATION layer; sessions 2-N fill in the per-opcode
IR-to-asm dispatch and wire into nx_nxc.nx as --target x86_64.
Session 1 scope (this file):
* x86_64 register name table (SysV ABI)
* function prologue / epilogue (pushq rbp / movq rsp,rbp / subq)
* .text / .rodata section directives
* label emission
* literal constant load (movabsq $imm, %reg)
* register-to-register move (movq %src, %dst)
* RIP-relative address load (leaq label(%rip), %reg)
* add / sub register-to-register (addq / subq)
* syscall (the most useful primitive -- emits the 'syscall' insn)
* .asciz string literal emission with byte-escape
Sessions 2-N (deferred):
* IR-instruction dispatch (binop / cmp / branch / call / load /
store / GEP / phi / return / tail_call / inline_asm)
* stack-machine slot layout per nx_x86_64.c
* regalloc integration (linear-scan with SysV-preserved regs)
* AVX2 SIMD (vmovdqu / vpaddd / vpsubd / vpmullq for i32x8 etc.)
* full nx_nxc.nx wiring as --target x86_64 dispatch
Output format: AT&T syntax (movabsq / addq / .quad), Linux SysV ABI,
PIC-aware (leaq label(%rip)). Byte-compatible with `gcc` / `as`.
genealogy_id: nxc2_x86_64_c_2026 + sysv_x86_64_abi_v0_99_6
lineage_id: nx_x86_64_foundation_v1
nx_safety_envelope:
intended_use: "Foundation emit library for x86_64 Linux SysV
assembly text. Per-primitive functions that
write to a shared OutBuf. Session 1 of N for
the full IR-driven backend."
sil_target: SIL3 (codegen correctness; silent
miscompilation is worse than crash)
dependencies 2 imports · 9 importers
imports: nx_syscalls.nxnx_outbuf.nx
imported by: nx_compile_x86.nxnx_x86_64_arith_test.nxnx_x86_64_branch_test.nxnx_x86_64_call_test.nxnx_x86_64_ctx.nxnx_x86_64_ctx_test.nxnx_x86_64_loadstore_test.nxnx_x86_64_module_test.nxnx_x86_64_test.nx
structs
| none |
consts
| 67 | const NX_X64_N_ARG_REGS: i64 = 6 |
| 352 | const NX_X64_SYS_READ: i64 = 0 |
| 353 | const NX_X64_SYS_WRITE: i64 = 1 |
| 354 | const NX_X64_SYS_OPEN: i64 = 2 |
| 355 | const NX_X64_SYS_CLOSE: i64 = 3 |
| 356 | const NX_X64_SYS_MMAP: i64 = 9 |
| 357 | const NX_X64_SYS_EXIT: i64 = 60 |
| 358 | const NX_X64_SYS_EXIT_GROUP: i64 = 231 // terminates ALL tasks; _start uses this (threaded runtime, 2026-07-07) |
| 600 | const NX_X64_CC_EQ: i64 = 0 |
| 601 | const NX_X64_CC_NE: i64 = 1 |
| 602 | const NX_X64_CC_LT_S: i64 = 2 |
| 603 | const NX_X64_CC_LE_S: i64 = 3 |
| 604 | const NX_X64_CC_GT_S: i64 = 4 |
| 605 | const NX_X64_CC_GE_S: i64 = 5 |
| 606 | const NX_X64_CC_LT_U: i64 = 6 |
| 607 | const NX_X64_CC_LE_U: i64 = 7 |
| 608 | const NX_X64_CC_GT_U: i64 = 8 |
| 609 | const NX_X64_CC_GE_U: i64 = 9 |
functions
| 69 | func x86_arg_reg_name(idx: i64) -> *u8 called by 1: x86ctx_emit_param_prologue |
| 82 | func x86_syscall_arg_reg_name(idx: i64) -> *u8 |
| 94 | func x86_indent(o: *OutBuf) -> i64 calls 1: out_char |
| 102 | func x86_pct_reg(o: *OutBuf, reg: *u8) -> i64 |
| 110 | func x86_emit_section_text(o: *OutBuf) -> i64 |
| 115 | func x86_emit_section_rodata(o: *OutBuf) -> i64 |
| 122 | func x86_emit_label(o: *OutBuf, name: *u8) -> i64 |
| 129 | func x86_emit_function_start(o: *OutBuf, name: *u8) -> i64 called by 6: mainmainmainx86ctx_emit_functionmainmain calls 4: x86_emit_section_textout_strout_charx86_emit_label |
| 141 | func x86_emit_function_end(o: *OutBuf, name: *u8) -> i64 |
| 156 | func x86_emit_asciz(o: *OutBuf, s: *u8, n: i64) -> i64 |
| 223 | func x86_round_up_16(n: i64) -> i64 called by 1: x86_emit_prologue |
| 227 | func x86_emit_prologue(o: *OutBuf, frame_size: i64) -> i64 |
| 239 | func x86_emit_epilogue(o: *OutBuf) -> i64 |
| 251 | func x86_emit_movabsq(o: *OutBuf, reg: *u8, imm: i64) -> i64 called by 15: x86_emit_syscall_immmainemit_write_bytemainmainx86ctx_load_value+9 calls 3: out_strout_i64out_char |
| 262 | func x86_emit_movq_reg_reg(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 276 | func x86_emit_leaq_rip(o: *OutBuf, label: *u8, reg: *u8) -> i64 |
| 290 | func x86_emit_addq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 299 | func x86_emit_subq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 318 | func x86_emit_syscall(o: *OutBuf) -> i64 |
| 329 | func x86_emit_syscall_imm(o: *OutBuf, num: i64, n_args: i64, |
| 345 | func x86_emit_gnu_stack_note(o: *OutBuf) -> i64 |
| 370 | func x86_reg_low32(reg: *u8) -> *u8 |
| 390 | func x86_reg_low16(reg: *u8) -> *u8 called by 1: x86_emit_store_word |
| 410 | func x86_reg_low8(reg: *u8) -> *u8 called by 1: x86_emit_store_byte |
| 434 | func x86_emit_mem_disp(o: *OutBuf, disp: i64, base: *u8) -> i64 |
| 452 | func x86_emit_load_qword(o: *OutBuf, base: *u8, disp: i64, dst: *u8) -> i64 |
| 461 | func x86_emit_load_dword_signed(o: *OutBuf, base: *u8, disp: i64, |
| 471 | func x86_emit_load_dword_unsigned(o: *OutBuf, base: *u8, disp: i64, |
| 482 | func x86_emit_load_word_signed(o: *OutBuf, base: *u8, disp: i64, |
| 492 | func x86_emit_load_word_unsigned(o: *OutBuf, base: *u8, disp: i64, |
| 502 | func x86_emit_load_byte_signed(o: *OutBuf, base: *u8, disp: i64, |
| 512 | func x86_emit_load_byte_unsigned(o: *OutBuf, base: *u8, disp: i64, |
| 527 | func x86_emit_store_qword(o: *OutBuf, src: *u8, base: *u8, disp: i64) -> i64 called by 3: x86ctx_emit_cs_savex86ctx_store_resultx86ctx_emit_store calls 3: out_strx86_emit_mem_dispout_char |
| 536 | func x86_emit_store_dword(o: *OutBuf, src: *u8, base: *u8, disp: i64) -> i64 |
| 546 | func x86_emit_store_word(o: *OutBuf, src: *u8, base: *u8, disp: i64) -> i64 |
| 556 | func x86_emit_store_byte(o: *OutBuf, src: *u8, base: *u8, disp: i64) -> i64 called by 5: mainemit_write_bytemainx86ctx_emit_storemain calls 4: x86_reg_low8out_strx86_emit_mem_dispout_char |
| 574 | func x86_emit_gep_add(o: *OutBuf, base_reg: *u8, off_reg: *u8) -> i64 |
| 586 | func x86_emit_lea_disp(o: *OutBuf, base: *u8, disp: i64, dst: *u8) -> i64 |
| 611 | func x86_cc_suffix(cc: i64) -> *u8 |
| 634 | func x86_emit_cmpq_rr(o: *OutBuf, src1: *u8, src2: *u8) -> i64 |
| 643 | func x86_emit_cmpq_imm(o: *OutBuf, imm: i64, src: *u8) -> i64 |
| 652 | func x86_emit_testq_rr(o: *OutBuf, src1: *u8, src2: *u8) -> i64 |
| 666 | func x86_emit_setcc(o: *OutBuf, cc: i64, dst8: *u8) -> i64 |
| 675 | func x86_emit_movzbq_rr(o: *OutBuf, src8: *u8, dst: *u8) -> i64 |
| 686 | func x86_emit_jmp_label(o: *OutBuf, label: *u8) -> i64 |
| 693 | func x86_emit_jcc_label(o: *OutBuf, cc: i64, label: *u8) -> i64 |
| 718 | func x86_emit_imulq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 730 | func x86_emit_mulq_r(o: *OutBuf, src: *u8) -> i64 |
| 737 | func x86_emit_cqo(o: *OutBuf) -> i64 |
| 745 | func x86_emit_crc32q_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 758 | func x86_emit_pdep_rrr(o: *OutBuf, src2: *u8, src1: *u8, dst: *u8) -> i64 |
| 772 | func x86_emit_pext_rrr(o: *OutBuf, src2: *u8, src1: *u8, dst: *u8) -> i64 |
| 783 | func x86_emit_idivq_r(o: *OutBuf, src: *u8) -> i64 |
| 790 | func x86_emit_divq_r(o: *OutBuf, src: *u8) -> i64 |
| 797 | func x86_emit_xorq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 806 | func x86_emit_andq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 815 | func x86_emit_orq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 824 | func x86_emit_negq_r(o: *OutBuf, dst: *u8) -> i64 |
| 831 | func x86_emit_notq_r(o: *OutBuf, dst: *u8) -> i64 |
| 841 | func x86_emit_shlq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 848 | func x86_emit_sarq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 855 | func x86_emit_shrq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 865 | func x86_emit_rolq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 872 | func x86_emit_rorq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 881 | func x86_emit_bswapq_rax(o: *OutBuf) -> i64 |
| 887 | func x86_emit_popcntq_rax(o: *OutBuf) -> i64 |
| 895 | func x86_emit_lzcntl_eax(o: *OutBuf) -> i64 |
| 901 | func x86_emit_tzcntl_eax(o: *OutBuf) -> i64 |
| 909 | func x86_emit_xchgq_rax_mem_r11(o: *OutBuf) -> i64 |
| 913 | func x86_emit_lock_cmpxchgq_rcx_mem_r11(o: *OutBuf) -> i64 |
| 917 | func x86_emit_sete_al(o: *OutBuf) -> i64 |
| 921 | func x86_emit_lock_xaddq_rax_mem_r11(o: *OutBuf) -> i64 |
| 925 | func x86_emit_mfence(o: *OutBuf) -> i64 |
| 932 | func x86_emit_shlq_imm(o: *OutBuf, n: i64, dst: *u8) -> i64 |
| 941 | func x86_emit_sarq_imm(o: *OutBuf, n: i64, dst: *u8) -> i64 |
| 950 | func x86_emit_shrq_imm(o: *OutBuf, n: i64, dst: *u8) -> i64 |
| 976 | func x86_emit_call_label(o: *OutBuf, name: *u8) -> i64 |
| 986 | func x86_emit_call_indirect(o: *OutBuf, reg: *u8) -> i64 |
| 996 | func x86_emit_tail_call_label(o: *OutBuf, name: *u8) -> i64 |
| 1003 | func x86_emit_tail_call_indirect(o: *OutBuf, reg: *u8) -> i64 |
| 1019 | func x86_emit_push_arg_imm(o: *OutBuf, imm: i64) -> i64 |
| 1026 | func x86_emit_push_arg_reg(o: *OutBuf, reg: *u8) -> i64 |
| 1034 | func x86_emit_pad_for_call(o: *OutBuf, n_stack_args: i64) -> i64 calls 1: out_str |
| 1042 | func x86_emit_unpad_after_call(o: *OutBuf, n_stack_args: i64, |
| 1059 | func x86_emit_return_value_to_rax(o: *OutBuf, src: *u8) -> i64 calls 1: x86_emit_movq_reg_reg |