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 · 10 importers
imports: nx_syscalls.nxnx_outbuf.nx
imported by: nx_compile_field_candidate_t280.nxnx_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 |
| 611 | const NX_X64_CC_O: i64 = 10 |
| 612 | const NX_X64_CC_NO: i64 = 11 |
functions
| 69 | func x86_arg_reg_name(idx: i64) -> *u8 |
| 82 | func x86_syscall_arg_reg_name(idx: i64) -> *u8 |
| 94 | func x86_indent(o: *OutBuf) -> i64 |
| 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 |
| 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 |
| 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 |
| 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 |
| 410 | func x86_reg_low8(reg: *u8) -> *u8 |
| 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 |
| 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 |
| 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 |
| 614 | func x86_cc_suffix(cc: i64) -> *u8 |
| 639 | func x86_emit_cmpq_rr(o: *OutBuf, src1: *u8, src2: *u8) -> i64 |
| 648 | func x86_emit_cmpq_imm(o: *OutBuf, imm: i64, src: *u8) -> i64 |
| 657 | func x86_emit_testq_rr(o: *OutBuf, src1: *u8, src2: *u8) -> i64 |
| 671 | func x86_emit_setcc(o: *OutBuf, cc: i64, dst8: *u8) -> i64 |
| 680 | func x86_emit_movzbq_rr(o: *OutBuf, src8: *u8, dst: *u8) -> i64 |
| 691 | func x86_emit_jmp_label(o: *OutBuf, label: *u8) -> i64 |
| 698 | func x86_emit_jcc_label(o: *OutBuf, cc: i64, label: *u8) -> i64 |
| 723 | func x86_emit_imulq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 735 | func x86_emit_mulq_r(o: *OutBuf, src: *u8) -> i64 |
| 742 | func x86_emit_cqo(o: *OutBuf) -> i64 |
| 750 | func x86_emit_crc32q_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 763 | func x86_emit_pdep_rrr(o: *OutBuf, src2: *u8, src1: *u8, dst: *u8) -> i64 |
| 777 | func x86_emit_pext_rrr(o: *OutBuf, src2: *u8, src1: *u8, dst: *u8) -> i64 |
| 788 | func x86_emit_idivq_r(o: *OutBuf, src: *u8) -> i64 |
| 795 | func x86_emit_divq_r(o: *OutBuf, src: *u8) -> i64 |
| 802 | func x86_emit_xorq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 811 | func x86_emit_andq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 820 | func x86_emit_orq_rr(o: *OutBuf, src: *u8, dst: *u8) -> i64 |
| 829 | func x86_emit_negq_r(o: *OutBuf, dst: *u8) -> i64 |
| 836 | func x86_emit_notq_r(o: *OutBuf, dst: *u8) -> i64 |
| 846 | func x86_emit_shlq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 853 | func x86_emit_sarq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 860 | func x86_emit_shrq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 870 | func x86_emit_rolq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 877 | func x86_emit_rorq_cl(o: *OutBuf, dst: *u8) -> i64 |
| 886 | func x86_emit_bswapq_rax(o: *OutBuf) -> i64 |
| 892 | func x86_emit_popcntq_rax(o: *OutBuf) -> i64 |
| 900 | func x86_emit_lzcntl_eax(o: *OutBuf) -> i64 |
| 906 | func x86_emit_tzcntl_eax(o: *OutBuf) -> i64 |
| 914 | func x86_emit_xchgq_rax_mem_r11(o: *OutBuf) -> i64 |
| 918 | func x86_emit_lock_cmpxchgq_rcx_mem_r11(o: *OutBuf) -> i64 |
| 922 | func x86_emit_sete_al(o: *OutBuf) -> i64 |
| 926 | func x86_emit_lock_xaddq_rax_mem_r11(o: *OutBuf) -> i64 |
| 930 | func x86_emit_mfence(o: *OutBuf) -> i64 |
| 937 | func x86_emit_shlq_imm(o: *OutBuf, n: i64, dst: *u8) -> i64 |
| 946 | func x86_emit_sarq_imm(o: *OutBuf, n: i64, dst: *u8) -> i64 |
| 955 | func x86_emit_shrq_imm(o: *OutBuf, n: i64, dst: *u8) -> i64 |
| 981 | func x86_emit_call_label(o: *OutBuf, name: *u8) -> i64 |
| 991 | func x86_emit_call_indirect(o: *OutBuf, reg: *u8) -> i64 |
| 1001 | func x86_emit_tail_call_label(o: *OutBuf, name: *u8) -> i64 |
| 1008 | func x86_emit_tail_call_indirect(o: *OutBuf, reg: *u8) -> i64 |
| 1024 | func x86_emit_push_arg_imm(o: *OutBuf, imm: i64) -> i64 |
| 1031 | func x86_emit_push_arg_reg(o: *OutBuf, reg: *u8) -> i64 |
| 1039 | func x86_emit_pad_for_call(o: *OutBuf, n_stack_args: i64) -> i64 |
| 1047 | func x86_emit_unpad_after_call(o: *OutBuf, n_stack_args: i64, |
| 1064 | func x86_emit_return_value_to_rax(o: *OutBuf, src: *u8) -> i64 |