v2.gen.arm64 #
fn Gen.new #
fn Gen.new(mod &mir.Module) &Gen
fn Linker.new #
fn Linker.new(macho &MachOObject) &Linker
fn MachOObject.new #
fn MachOObject.new() &MachOObject
struct Gen #
struct Gen {
pub:
mod &mir.Module
mut:
macho &MachOObject
pub mut:
stack_map map[int]int
alloca_offsets map[int]int
stack_size int
curr_offset int
block_offsets []int // indexed by block_id, -1 = not yet visited
pending_label_blks []int
pending_label_offs []int
func_count int
total_pending int
total_resolved int
// Register allocation
reg_map map[int]int
used_regs []int
next_blk int
cur_blk_id int // current block being generated (for phi copy emission)
// Track which string literals have been materialized (value_id -> str_data offset)
string_literal_offsets map[int]int
// Cache for parsed constant integer values (value_id -> parsed i64)
const_cache map[int]i64
// Current function's return type (for handling struct returns)
cur_func_ret_type int
cur_func_name string
// Stack offset where x8 (indirect return pointer) is saved for large struct returns
x8_save_offset int
// Cache for deduplicating string data in cstring section (content -> offset)
string_data_cache map[string]int
// alloca values whose addresses are stored in sumtype `_data` fields and
// therefore must outlive the current stack frame.
sumtype_data_heap_allocas map[int]bool
// Type layout caches/guards to avoid recursive size/alignment loops.
type_size_cache []int // indexed by type_id, 0 = not cached (valid sizes are > 0 or == 0 only for void)
type_align_cache []int // indexed by type_id, 0 = not cached
type_size_stack []bool // indexed by type_id (recursion guard)
type_align_stack []bool // indexed by type_id (recursion guard)
// Cache for struct field offset calculations (key: typ_id << 16 | field_idx)
struct_field_offset_cache map[int]int
// Lookup caches for O(1) name resolution
func_by_name map[string]int // function name → index in g.mod.funcs
global_by_name map[string]int // global name → index in g.mod.globals
// Per-function cache for alloca pointer analysis (cleared per function)
alloca_ptr_cache map[int]u8 // alloca_id → 1=has_ptrs, 2=no_ptrs
// Cached environment variables for debug tracing (read once at init)
env_dump_funcrefs string
env_trace_skip_dead string
env_dump_stackmap string
env_dump_blocks string
env_trace_paramspill string
env_trace_val string
env_trace_instr string
env_trace_cmp string
env_trace_store string
env_trace_load string
env_trace_call string
env_trace_ret string
env_trace_bitcast string
env_trace_assign string
env_trace_extract string
env_trace_struct_init string
env_trace_agg_copy string
env_trace_insert string
env_trace_callcount string
env_trace_callarg string
env_trace_struct_addr string
env_trace_strlit string
env_trace_storeval string
env_trace_regalloc string
env_no_regalloc bool
// SP-relative addressing: sp_base_offset = callee_saved_size + stack_size
// so that fp - N = sp + (sp_base_offset - N) for positive sp-relative offsets.
sp_base_offset int
sp_adjusted bool // true when sp is temporarily modified (call arg push)
sp_adjust_amt int // how much SP was decremented (valid when sp_adjusted)
// Reverse map: val_id → block_id for block-kind values.
// Value.index is unreliable in ARM64-compiled binaries, so use this instead.
val_to_block []int
// Last-store cache for eliminating redundant store-then-load sequences.
// After store_reg_to_val records (reg, val_id), the next load_val_to_reg
// for the same val_id can reuse the register instead of loading from stack.
// Cleared at block boundaries, function calls, and any register write.
last_store_reg int = -1
last_store_val int
last_store_blk int = -1
last_store_next_instr_idx int = -1
// Current block instruction list and index, for lookahead optimizations.
cur_blk_instrs []int
cur_blk_instr_idx int
// Function boundaries for dead-stripping.
fn_starts []int // text offset where each function begins
fn_ends []int // text offset where each function ends
fn_names []string // symbol name of each function
fn_sym_ids []int // symbol index in macho.symbols
// Stats counters for optimization analysis.
stats_total_stores int
stats_skipped_stores int
stats_cache_hits int
}
fn (Gen) gen #
fn (mut g Gen) gen()
fn (Gen) gen_pre_pass #
fn (mut g Gen) gen_pre_pass()
gen_pre_pass registers global symbols and builds lookup caches. Must be called before any gen_func calls.
fn (Gen) gen_post_pass #
fn (mut g Gen) gen_post_pass()
gen_post_pass emits the unresolved stub, global data, and patches symbol addresses. Must be called after all gen_func calls.
fn (Gen) pre_populate_type_caches #
fn (mut g Gen) pre_populate_type_caches()
new_worker_clone creates a new Gen instance for parallel code generation. The worker shares the read-only MIR module and lookup caches, but has its own MachOObject buffers for independent code emission. pre_populate_type_caches computes type_size and type_align for ALL types in the type store, so that workers can share the caches read-only.
fn (Gen) new_worker_clone #
fn (g &Gen) new_worker_clone() &Gen
fn (Gen) merge_worker #
fn (mut g Gen) merge_worker(w &Gen)
merge_worker merges a parallel worker's output buffers into the main Gen. text_data, str_data, symbols, and relocations are concatenated with offset adjustment.
fn (Gen) gen_func #
fn (mut g Gen) gen_func(func mir.Function)
fn (Gen) write_file #
fn (mut g Gen) write_file(path string)
fn (Gen) link_executable #
fn (mut g Gen) link_executable(output_path string)
fn (Gen) extract_function #
fn (mut g Gen) extract_function(fn_name string) []u8
extract_function extracts the raw machine code bytes for a named function. Used for hot code reloading: the extracted bytes can be loaded into a JIT page and called via a function pointer.
struct Linker #
struct Linker {
macho &MachOObject
pub mut:
// Frameworks to link (e.g. ['Metal', 'Cocoa', 'QuartzCore'])
frameworks []string
mut:
// Output buffer
buf []u8
// Segment/section info
text_vmaddr u64
text_fileoff int
text_size int
data_vmaddr u64
data_fileoff int
data_size int
linkedit_off int
linkedit_size int
// External symbols needing binding
extern_syms []string
// GOT entries for external symbols
got_offset int // Offset within __DATA segment
got_size int
// Stubs for external function calls
stubs_offset int
stubs_size int
// Symbol to GOT index mapping
sym_to_got map[string]int
// Multi-dylib support: dylib paths and per-symbol ordinal mapping
dylibs []string // ['/usr/lib/libSystem.B.dylib', '/usr/lib/libobjc.A.dylib', ...]
sym_to_dylib map[string]int // symbol name → index into dylibs[] (ordinal = idx + 1)
// Code start offset (after header + load commands)
code_start int
}
fn (Linker) link #
fn (mut l Linker) link(output_path string, entry_name string)
struct MachOObject #
struct MachOObject {
pub mut:
text_data []u8
str_data []u8
data_data []u8
relocs []RelocationInfo
symbols []Symbol
str_table []u8
sym_by_name map[string]int // symbol name → index in symbols
}
fn (MachOObject) add_symbol #
fn (mut m MachOObject) add_symbol(name string, addr u64, is_ext bool, sect u8) int
fn (MachOObject) add_undefined #
fn (mut m MachOObject) add_undefined(name string) int
fn (MachOObject) add_reloc #
fn (mut m MachOObject) add_reloc(addr int, sym_idx int, typ int, pcrel bool)
fn (MachOObject) write #
fn (mut m MachOObject) write(path string)