#![allow(dead_code)]

#[allow(dead_code)]
use anyhow::Result;
use log::{debug, trace, warn};
use crate::tsn_diag_codegen;
// Cranelift 0.93.2 导入
use clcodegen::ir::types;
use clcodegen::ir::{AbiParam, InstBuilder, Type, Value};
use clcodegen::ir::condcodes::{IntCC, FloatCC};
use clcodegen::ir::MemFlags;
use clcodegen::settings;
use clcodegen::settings::Configurable;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use cranelift_module::{DataContext, Linkage, Module};
use cranelift_object::{ObjectBuilder, ObjectModule, ObjectProduct};
use clcodegen::ir:: StackSlotData;
use clcodegen::ir:: StackSlotKind;
#[allow(unused_imports)]
use object::read::{Object as ReadObject, ObjectSection, ObjectSymbol};

// === 原始模块数据结构（从原生 object::write::Object 提取） ===

#[derive(Debug, Clone)]
pub struct RawModuleData {
    pub functions: std::collections::HashMap<String, Vec<u8>>,
    pub data_items: std::collections::HashMap<String, Vec<u8>>,
    pub symbols: Vec<RawSymbol>,
    pub relocations: Vec<RawRelocation>,
}

#[derive(Debug, Clone)]
pub struct RawSymbol {
    pub name: String,
    pub section: u8,   // 0=.text, 1=.data, 2=.rdata
    pub offset: u32,
    pub is_global: bool,
}

#[derive(Debug, Clone)]
pub struct RawRelocation {
    pub section: u8,
    pub offset: u32,
    pub reloc_type: u8,  // 0=REL32, 1=ADDR64
    pub target_symbol: String,
}

pub const UNDEFINED: u64 = 0x7FF4_0000_0000_0000;  // TAG_UNDEFINED
pub const NULL: u64 = 0x7FF5_0000_0000_0000;        // TAG_NULL
pub const BIGINT_TAG: u64 = 0x7FFA_0000_0000_0000;  // TAG_BIGINT
pub const TRUE: u64 = 0x7FFF_0000_0000_0001;
pub const FALSE: u64 = 0x7FFF_0000_0000_0000;
pub const STRING_TAG: u64 = 0x7FF1_0000_0000_0000;  // TAG_STRING
pub const ARRAY_TAG: u64 = 0x7FF7_0000_0000_0000;   // TAG_ARRAY
pub const OBJECT_TAG: u64 = 0x7FF2_0000_0000_0000;  // TAG_OBJECT
pub const FUNCTION_TAG: u64 = 0x7FF6_0000_0000_0000; // TAG_FUNCTION
pub const BUFFER_TAG: u64 = 0x7FF8_0000_0000_0000;  // TAG_BUFFER

// 标准事件类型
pub const EVENT_CLICK: u64 = 1;
pub const EVENT_KEYDOWN: u64 = 2;
pub const EVENT_KEYUP: u64 = 3;
pub const EVENT_MOUSEMOVE: u64 = 4;
pub const EVENT_CHANGE: u64 = 5;
pub const EVENT_SUBMIT: u64 = 6;
pub const EVENT_FOCUS: u64 = 7;
pub const EVENT_BLUR: u64 = 8;
pub const EVENT_CHANGE_VALUE: u64 = 9;

fn map_event_type(event_name: &str) -> u64 {
    match event_name {
        "click" => EVENT_CLICK,
        "keydown" => EVENT_KEYDOWN,
        "keyup" => EVENT_KEYUP,
        "mousemove" => EVENT_MOUSEMOVE,
        "change" => EVENT_CHANGE,
        "submit" => EVENT_SUBMIT,
        "focus" => EVENT_FOCUS,
        "blur" => EVENT_BLUR,
        "changeValue" => EVENT_CHANGE_VALUE,
        _ => 0,  // 未知事件，运行时处理
    }
}

#[derive(Debug, Clone)]
pub enum HirExpr {
    Number(f64),
    BigInt(String),  // 任意精度大整数，保留完整精度
    Boolean(bool),
    String(String),
    Null,
    Undefined,
    Identifier(String),

    /// 模块导入绑定：记录 "localName" 来自 "moduleName"
    /// 例如 import { readFileSync } from "fs" → ImportBinding { local: "readFileSync", module: "fs", imported: "readFileSync" }
    ImportBinding { local: String, module: String, imported: String },

    /// 模块导出声明
    Export {
        local: String,     // 本地名称
        exported: String,  // 导出名称（"default" 为默认导出）
        module: String,    // re-export 来源模块名（空串表示当前模块）
        is_default: bool,  // 是否为默认导出
    },

    Binary { op: BinOp, left: Box<HirExpr>, right: Box<HirExpr> },
    Unary { op: UnaryOp, operand: Box<HirExpr> },
    Typeof(Box<HirExpr>),

    Call { callee: Box<HirExpr>, args: Vec<HirExpr> },

    Ternary { cond: Box<HirExpr>, then_expr: Box<HirExpr>, else_expr: Box<HirExpr> },

    Function { name: String, params: Vec<String>, body: Vec<HirExpr> },

    Return(Option<Box<HirExpr>>),
    Var { name: String, init: Option<Box<HirExpr>>, is_mut: bool },

    If { cond: Box<HirExpr>, then_body: Vec<HirExpr>, else_body: Option<Vec<HirExpr>> },
    While { cond: Box<HirExpr>, body: Vec<HirExpr> },
    For { init: Option<Box<HirExpr>>, cond: Option<Box<HirExpr>>, update: Option<Box<HirExpr>>, body: Vec<HirExpr> },

    Block(Vec<HirExpr>),

    Break,
    Continue,

    Assign { target: Box<HirExpr>, value: Box<HirExpr> },

    Array(Vec<HirExpr>),
    Index { object: Box<HirExpr>, index: Box<HirExpr> },

    Object(Vec<(String, HirExpr)>),
    Property { object: Box<HirExpr>, name: String },

    TryCatch {
        try_body: Vec<HirExpr>,
        catch_param: Option<String>,
        catch_body: Option<Vec<HirExpr>>,
        finally_body: Option<Vec<HirExpr>>,
    },
    Throw(Option<Box<HirExpr>>),
    ExprStmt(Box<HirExpr>),
    Seq(Vec<HirExpr>),

    // Regex support
    Regex { pattern: String, flags: String },
    RegexTest { regex: Box<HirExpr>, text: Box<HirExpr> },
    RegexExec { regex: Box<HirExpr>, text: Box<HirExpr> },
    RegexMatch { regex: Box<HirExpr>, text: Box<HirExpr> },

    // Class support
    Class {
        name: String,
        parent: Option<String>,  // 父类名称
        constructor: Option<Box<HirExpr>>,  // 构造函数
        methods: Vec<ClassMethod>,
        properties: Vec<String>,  // 属性名
    },
    New {
        class_name: String,
        args: Vec<HirExpr>
    },
    This,
    SuperMethod {
        method_name: String,
        args: Vec<HirExpr>
    },
    /// super() 构造函数调用
    SuperCall(Vec<HirExpr>),

    // Generator support
    Generator {
        name: String,
        params: Vec<String>,
        body: Vec<HirExpr>
    },
    Yield(Box<HirExpr>),
    YieldFrom(Box<HirExpr>),

    // Async/Await support
    AsyncFunction {
        name: String,
        params: Vec<String>,
        body: Vec<HirExpr>
    },
    Await(Box<HirExpr>),

    // Decorator support
    Decorator {
        target: String,
        target_type: String,  // "class", "method", "property", "parameter"
        name: String,
        args: Vec<HirExpr>,
    },
    DecoratedClass {
        name: String,
        parent: Option<String>,
        constructor: Option<Box<HirExpr>>,
        methods: Vec<ClassMethod>,
        properties: Vec<String>,
        decorators: Vec<HirExpr>,
    },
    DecoratedMethod {
        name: String,
        params: Vec<String>,
        body: Vec<HirExpr>,
        is_static: bool,
        decorators: Vec<HirExpr>,
    },
}

#[derive(Debug, Clone, Copy)]
pub enum BinOp {
    Add, Sub, Mul, Div, Mod,
    Eq, Ne, Lt, Le, Gt, Ge,
    And, Or,
    BitAnd, BitOr, BitXor, Shl, Shr,
    Instanceof,
}

#[derive(Debug, Clone, Copy)]
pub enum UnaryOp {
    Not, Neg, PreInc, PreDec, PostInc, PostDec,
}

#[derive(Debug, Clone)]
pub struct ClassMethod {
    pub name: String,
    pub params: Vec<String>,
    pub body: Vec<HirExpr>,
    pub is_static: bool,
}

/// FNV-1a 64-bit hash for property key strings.
/// More robust than djb2 for avoiding collisions with similar property names.
fn fnv1a_64(name: &str) -> u64 {
    let mut hash: u64 = 0xcbf29ce484222325;
    for byte in name.bytes() {
        hash ^= byte as u64;
        hash = hash.wrapping_mul(0x100000001b3);
    }
    hash
}

/// Source Map 条目：代码偏移 ↔ 源码位置
#[derive(Debug, Clone)]
pub struct SourceMapEntry {
    pub code_offset: u32,   // 机器码中的偏移
    pub func_name: String,  // 函数名
    pub src_line: u32,      // 源码行号（1-based）
    pub src_col: u32,       // 源码列号（1-based）
    pub node_type: String,  // HIR 节点类型（如 "Call", "Binary", "Return"）
}

/// 编译性能统计
#[derive(Debug, Clone, Default)]
pub struct CompileStats {
    pub parse_time_ms: u64,
    pub codegen_time_ms: u64,
    pub coff_time_ms: u64,
    pub extract_time_ms: u64,
    pub function_count: usize,
    pub string_count: usize,
    pub code_size: usize,
    pub data_size: usize,
    pub rdata_size: usize,
}

pub struct CodeGen {
    builder_context: FunctionBuilderContext,
    function_ids: std::collections::HashMap<String, cranelift_module::FuncId>,
    function_param_counts: std::collections::HashMap<String, usize>,
    string_pool: std::collections::HashSet<String>,
    external_functions: std::collections::HashMap<String, String>,
    /// Source map: 代码偏移 → 源码位置
    source_map: Vec<SourceMapEntry>,
    /// 当前编译的函数名（用于 source map）
    current_func: String,
    /// 当前源码行号（由 swc_transform 设置）
    current_line: u32,
    /// 编译性能统计
    stats: CompileStats,
    import_bindings: std::collections::HashMap<String, (String, String)>,
    /// 模块符号表：函数名 -> 定义该函数的模块路径
    /// 用于跨模块调用时声明外部符号
    module_symbols: std::collections::HashMap<String, String>,
    /// 跨模块 const export 值（导出名 → HirExpr 字面值）
    const_values: std::collections::HashMap<String, HirExpr>,
    /// native addon 配置（包名 → NativeAddonConfig）
    /// 用于将 import 绑定映射为 addon DLL 外部函数调用
    native_addon_config: std::collections::HashMap<String, crate::project::NativeAddonConfig>,
    /// QuickJS fallback 包列表（使用 QuickJS 执行的纯 JS 包）
    js_engine_fallback: Vec<String>,
    /// 标记为 rest 参数函数的集合（函数名）
    rest_functions: std::collections::HashSet<String>,
    /// Class 方法映射表：方法名 -> 完整函数名（如 "greet" -> "MyClass_greet"）
    class_methods: std::collections::HashMap<String, String>,
}

// === 编译上下文：减少 compile_stmt / compile_expr 的参数传递 ===
// 注意：FunctionBuilder 不包含在 Ctx 中，因为 FunctionBuilder<'a> 的生命周期
// 会导致借用检查器无法在块边界释放借用。改为单独传递 builder 参数。

struct Ctx<'a> {
    variables: &'a mut std::collections::HashMap<String, Variable>,
    /// 下一个可用的变量索引（单调递增，避免重复声明）
    next_var_idx: u32,
    /// 函数参数名列表（不应对参数执行 release）
    param_names: &'a [String],
    module: &'a mut ObjectModule,
    function_ids: &'a std::collections::HashMap<String, cranelift_module::FuncId>,
    function_param_counts: &'a std::collections::HashMap<String, usize>,
    string_data: &'a std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
    import_bindings: &'a std::collections::HashMap<String, (String, String)>,
    module_symbols: &'a std::collections::HashMap<String, String>,
    /// 跨模块 const export 值（导出名 → HirExpr 字面值）
    const_values: &'a std::collections::HashMap<String, HirExpr>,
    /// native addon 配置（包名 → NativeAddonConfig）
    native_addon_config: &'a std::collections::HashMap<String, crate::project::NativeAddonConfig>,
    /// QuickJS fallback 包列表
    js_engine_fallback: &'a [String],
    /// 最后一个表达式语句的计算结果（用于 async await 捕获）
    last_expr_value: Option<clcodegen::ir::Value>,
    /// 当前 try 块的异常检查目标块（throw 时跳转到这里）
    current_try_check: Option<clcodegen::ir::Block>,
    /// Class 方法查找表：方法名 -> 完整函数名
    class_methods: &'a std::collections::HashMap<String, String>,
    /// 当前函数的 entry_block（用于 rest 参数数组构造）
    entry_block: Option<clcodegen::ir::Block>,
    /// 当前函数声明的参数总数（含 rest 展开的额外参数）
    declared_param_count: usize,
    /// rest 参数函数集合（调用这些函数时不填充额外参数）
    rest_functions: &'a std::collections::HashSet<String>,
}

// === GC 辅助函数：retain/release ===

/// 对指定变量调用 `js_release`，释放其引用的堆对象（string/object/array）。
/// 对 number/boolean/null/undefined 无害（runtime 内部检查 tag）。
fn emit_release_var(ctx: &mut Ctx, builder: &mut FunctionBuilder, var: Variable) {
    let val = builder.use_var(var);
    call_import(ctx, builder, "js_release", &[val]);
}

/// 释放所有局部变量（非参数变量）的引用。
/// 可选跳过某个变量名（用于 return 语句中保留返回值）。
fn emit_release_locals(ctx: &mut Ctx, builder: &mut FunctionBuilder, skip_name: Option<&str>) {
    // 收集要释放的变量名列表（避免遍历时修改 HashMap）
    let var_names: Vec<String> = ctx.variables.keys()
        .filter(|name| {
            // 跳过参数变量
            if ctx.param_names.contains(name) {
                return false;
            }
            // 可选跳过指定名称
            if let Some(skip) = skip_name {
                if *name == skip {
                    return false;
                }
            }
            true
        })
        .cloned()
        .collect();
    for name in var_names {
        if let Some(&var) = ctx.variables.get(&name) {
            emit_release_var(ctx, builder, var);
        }
    }
}

// === 辅助函数：声明外部导入函数 ===

/// 声明一个外部导入函数并返回 FuncRef（如果声明成功）。
fn declare_import(ctx: &mut Ctx, builder: &mut FunctionBuilder, name: &str, params: &[Type], ret: Type) -> Option<clcodegen::ir::FuncRef> {
    let mut sig = ctx.module.make_signature();
    for &p in params {
        sig.params.push(AbiParam::new(p));
    }
    sig.returns.push(AbiParam::new(ret));
    // 先尝试声明（可能已存在不同签名）
    match ctx.module.declare_function(name, Linkage::Preemptible, &sig) {
        Ok(id) => Some(ctx.module.declare_func_in_func(id, &mut builder.func)),
        Err(_) => {
            // 已存在声明但签名不同：用零参签名再试一次（泛型 fallback）
            let mut fallback_sig = ctx.module.make_signature();
            fallback_sig.returns.push(AbiParam::new(ret));
            ctx.module.declare_function(name, Linkage::Preemptible, &fallback_sig).ok()
                .map(|id| ctx.module.declare_func_in_func(id, &mut builder.func))
        }
    }
}

/// 声明并调用一个返回 F64 的外部导入函数（所有参数均为 F64）。
fn call_import(ctx: &mut Ctx, builder: &mut FunctionBuilder, name: &str, args: &[Value]) -> Value {
    let param_types: Vec<Type> = vec![types::F64; args.len()];
    if let Some(func_ref) = declare_import(ctx, builder, name, &param_types, types::F64) {
        let call = builder.ins().call(func_ref, args);
        builder.inst_results(call)[0]
    } else {
        builder.ins().f64const(f64::from_bits(UNDEFINED))
    }
}

/// 直接调用外部导入函数（不需要 Ctx，用于避免借用冲突）
/// 接收 Ctx 的原始字段引用
fn call_import_direct(
    module: &mut ObjectModule,
    _function_ids: &std::collections::HashMap<String, cranelift_module::FuncId>,
    _function_param_counts: &std::collections::HashMap<String, usize>,
    _string_data: &std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
    _import_bindings: &std::collections::HashMap<String, (String, String)>,
    _module_symbols: &std::collections::HashMap<String, String>,
    _native_addon_config: &std::collections::HashMap<String, crate::project::NativeAddonConfig>,
    _js_engine_fallback: &[String],
    builder: &mut FunctionBuilder,
    name: &str,
    args: &[Value],
) -> Value {
    let param_types: Vec<Type> = vec![types::F64; args.len()];
    let mut sig = module.make_signature();
    for &p in &param_types {
        sig.params.push(AbiParam::new(p));
    }
    sig.returns.push(AbiParam::new(types::F64));
    if let Ok(id) = module.declare_function(name, Linkage::Preemptible, &sig) {
        let func_ref = module.declare_func_in_func(id, &mut builder.func);
        let call = builder.ins().call(func_ref, args);
        builder.inst_results(call)[0]
    } else {
        builder.ins().f64const(f64::from_bits(UNDEFINED))
    }
}

// === 辅助函数：常量折叠 ===

/// 编译期计算两个数字常量的二元运算结果
fn fold_const_binary(op: BinOp, a: f64, b: f64) -> Option<f64> {
    match op {
        BinOp::Add => Some(a + b),
        BinOp::Sub => Some(a - b),
        BinOp::Mul => Some(a * b),
        BinOp::Div => if b != 0.0 { Some(a / b) } else { None },
        BinOp::Mod => if b != 0.0 { Some(a % b) } else { None },
        BinOp::Eq => Some(if a == b { f64::from_bits(TRUE) } else { f64::from_bits(FALSE) }),
        BinOp::Ne => Some(if a != b { f64::from_bits(TRUE) } else { f64::from_bits(FALSE) }),
        BinOp::Lt => Some(if a < b { f64::from_bits(TRUE) } else { f64::from_bits(FALSE) }),
        BinOp::Le => Some(if a <= b { f64::from_bits(TRUE) } else { f64::from_bits(FALSE) }),
        BinOp::Gt => Some(if a > b { f64::from_bits(TRUE) } else { f64::from_bits(FALSE) }),
        BinOp::Ge => Some(if a >= b { f64::from_bits(TRUE) } else { f64::from_bits(FALSE) }),
        BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor | BinOp::Shl | BinOp::Shr | BinOp::And | BinOp::Or | BinOp::Instanceof => None, // 位运算/短路/instanceof 不做常量折叠
    }
}

/// 声明并调用 js_add（使用 f64 参数和返回值）。
fn call_js_add(ctx: &mut Ctx, builder: &mut FunctionBuilder, a: Value, b: Value) -> Value {
    let param_types = vec![types::F64, types::F64];
    if let Some(func_ref) = declare_import(ctx, builder, "js_add", &param_types, types::F64) {
        let call = builder.ins().call(func_ref, &[a, b]);
        builder.inst_results(call)[0]
    } else {
        builder.ins().f64const(f64::from_bits(UNDEFINED))
    }
}

/// 声明并调用一个无返回值的外部导入函数（所有参数均为 F64）。
fn call_import_void(ctx: &mut Ctx, builder: &mut FunctionBuilder, name: &str, args: &[Value]) {
    let param_types: Vec<Type> = vec![types::F64; args.len()];
    if let Some(func_ref) = declare_import(ctx, builder, name, &param_types, types::I32) {
        builder.ins().call(func_ref, args);
    }
}

/// 声明并调用一个返回 I32 的外部导入函数（无参数）。
fn call_import_i32_no_args(ctx: &mut Ctx, builder: &mut FunctionBuilder, name: &str) -> Value {
    if let Some(func_ref) = declare_import(ctx, builder, name, &[], types::I32) {
        let call = builder.ins().call(func_ref, &[]);
        builder.inst_results(call)[0]
    } else {
        builder.ins().iconst(types::I32, 0)
    }
}

/// 声明并调用一个返回 F64 的外部导入函数（无参数）。
fn call_import_f64_no_args(ctx: &mut Ctx, builder: &mut FunctionBuilder, name: &str) -> Value {
    if let Some(func_ref) = declare_import(ctx, builder, name, &[], types::F64) {
        let call = builder.ins().call(func_ref, &[]);
        builder.inst_results(call)[0]
    } else {
        builder.ins().f64const(f64::from_bits(UNDEFINED))
    }
}

/// 声明并调用一个返回 F64 的外部导入函数（一个 I64 参数）。
fn call_import_i64_to_f64(ctx: &mut Ctx, builder: &mut FunctionBuilder, name: &str, arg: Value) -> Value {
    if let Some(func_ref) = declare_import(ctx, builder, name, &[types::I64], types::F64) {
        let call = builder.ins().call(func_ref, &[arg]);
        builder.inst_results(call)[0]
    } else {
        builder.ins().f64const(f64::from_bits(UNDEFINED))
    }
}

// === 辅助函数：console.log / console.error / console.warn / console.debug ===

/// 发射 console.log / console.error / console.warn / console.debug 的 IR。
/// 优化：将所有参数值存入 stack slot，一次调用 js_print_multi（减少 FFI 次数）。
fn emit_console_log(ctx: &mut Ctx, builder: &mut FunctionBuilder, args: &[HirExpr]) -> Value {
    let count = args.len();

    if count == 0 {
        // 无参数：直接调用 js_print_newline
        let mut sig_nl = ctx.module.make_signature();
        sig_nl.returns.push(AbiParam::new(types::F64));
        if let Ok(id) = ctx.module.declare_function("js_print_newline", Linkage::Import, &sig_nl) {
            let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
            builder.ins().call(func_ref, &[]);
        }
        return builder.ins().f64const(f64::from_bits(UNDEFINED));
    }

    // 1. 编译所有参数，得到 f64 值
    let vals: Vec<Value> = args.iter()
        .map(|arg| compile_expr(arg, ctx, builder))
        .collect();

    // 2. 分配 stack slot 存放 f64 数组
    let slot_size = (count * 8) as u32;
    let ss = builder.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, slot_size));

    // 3. 将每个 f64 值 store 到 stack slot 中
    for (i, &val) in vals.iter().enumerate() {
        let offset = (i * 8) as i32;
        builder.ins().stack_store(val, ss, offset);
    }

    // 4. 获取 stack slot 的地址作为 *const f64
    let addr = builder.ins().stack_addr(types::I64, ss, 0);

    // 5. 一次调用 js_print_multi(addr, count)
    let mut sig = ctx.module.make_signature();
    sig.params.push(AbiParam::new(types::I64)); // values_ptr
    sig.params.push(AbiParam::new(types::I32)); // count
    sig.returns.push(AbiParam::new(types::F64));
    if let Ok(id) = ctx.module.declare_function("js_print_multi", Linkage::Import, &sig) {
        let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
        let count_val = builder.ins().iconst(types::I32, count as i64);
        builder.ins().call(func_ref, &[addr, count_val]);
    }

    builder.ins().f64const(f64::from_bits(UNDEFINED))
}

// === 辅助函数：is_truthy ===

/// 将驼峰格式的模块函数名转换为下划线格式的 runtime 函数名
/// 例如: "fs.readFileSync" → "js_fs_read_file_sync"
/// "os.platform" → "js_os_platform"
/// "process.cwd" → "js_process_cwd"
fn to_runtime_fn_name(full_name: &str) -> String {
    // 先移除可能的换行符、回车符等空白字符
    let cleaned = full_name.trim();
    let mut result = String::from("js_");
    let chars: Vec<char> = cleaned.chars().collect();
    let mut i = 0;
    while i < chars.len() {
        let c = chars[i];
        if c == '.' {
            result.push('_');
            i += 1;
        } else if c.is_uppercase() {
            // 找到连续大写字母的末尾
            let start = i;
            while i < chars.len() && chars[i].is_uppercase() {
                i += 1;
            }
            let upper_run = &chars[start..i];
            // 如果连续大写后面还有小写字母（如 "UUID" 后面没小写，"ParseURL" 后面有）
            // 则最后一个大写字母属于下一个单词（acronym boundary）
            let split = if upper_run.len() > 1 && i < chars.len() && chars[i].is_lowercase() {
                upper_run.len() - 1
            } else {
                upper_run.len()
            };
            // 在连续大写前插入下划线（如果不是开头且前一个不是 '.'）
            if start > 0 && chars.get(start - 1) != Some(&'.') {
                result.push('_');
            }
            for (j, &uc) in upper_run.iter().enumerate() {
                result.push(uc.to_ascii_lowercase());
                // 在 acronym boundary 处插入下划线
                if j + 1 == split && split < upper_run.len() {
                    result.push('_');
                }
            }
        } else {
            result.push(c);
            i += 1;
        }
    }
    result
}

/// 将 NaN-tagged 值转为 i32 布尔值（1 = truthy, 0 = falsy）。
/// falsy: f64 0.0 (bits=0) 或 NaN:false (bits=0x7FFF000000000000)
fn is_truthy(val: Value, builder: &mut FunctionBuilder) -> Value {
    let val_bits = builder.ins().bitcast(types::I64, MemFlags::new(), val);
    let zero = builder.ins().iconst(types::I64, 0);
    let false_bits = builder.ins().iconst(types::I64, FALSE as i64);
    let is_zero = builder.ins().icmp(IntCC::Equal, val_bits, zero);
    let is_false = builder.ins().icmp(IntCC::Equal, val_bits, false_bits);
    let is_falsy = builder.ins().bor(is_zero, is_false);
    // icmp/bor 结果类型是 i8，brif 条件需要 i8，直接返回 i8
    // 1 = truthy, 0 = falsy
    let one_i8 = builder.ins().iconst(types::I8, 1);
    let is_truthy_val = builder.ins().bxor(is_falsy, one_i8);
    is_truthy_val
}

impl CodeGen {
    pub fn new() -> Self {
        Self {
            builder_context: FunctionBuilderContext::new(),
            function_ids: std::collections::HashMap::new(),
            function_param_counts: std::collections::HashMap::new(),
            string_pool: std::collections::HashSet::new(),
            external_functions: std::collections::HashMap::new(),
            source_map: Vec::new(),
            current_func: String::new(),
            current_line: 0,
            stats: CompileStats::default(),
            import_bindings: std::collections::HashMap::new(),
            module_symbols: std::collections::HashMap::new(),
            native_addon_config: std::collections::HashMap::new(),
            js_engine_fallback: Vec::new(),
            class_methods: std::collections::HashMap::new(),
            rest_functions: std::collections::HashSet::new(),
            const_values: std::collections::HashMap::new(),
        }
    }

    /// 设置模块符号表（用于跨模块编译）
    pub fn set_module_symbols(&mut self, symbols: std::collections::HashMap<String, String>) {
        self.module_symbols = symbols;
    }

    /// 设置跨模块 const export 值
    pub fn set_const_values(&mut self, values: std::collections::HashMap<String, HirExpr>) {
        self.const_values = values;
    }

    /// 获取已编译的函数数量
    pub fn get_compiled_function_count(&self) -> usize {
        self.stats.function_count
    }

    /// 获取 source map 引用
    pub fn source_map(&self) -> &[SourceMapEntry] {
        &self.source_map
    }

    /// 获取编译统计
    pub fn stats(&self) -> &CompileStats {
        &self.stats
    }

    /// 记录 source map 条目
    fn record_source_map(&mut self, code_offset: u32, node_type: &str) {
        if self.current_line > 0 {
            self.source_map.push(SourceMapEntry {
                code_offset,
                func_name: self.current_func.clone(),
                src_line: self.current_line,
                src_col: 0,
                node_type: node_type.to_string(),
            });
        }
    }

    /// 设置当前编译的函数名
    fn set_current_func(&mut self, name: &str) {
        self.current_func = name.to_string();
    }

    /// 设置当前源码行号
    pub fn set_current_line(&mut self, line: u32) {
        self.current_line = line;
    }

    pub fn with_external_functions(mut self, functions: std::collections::HashMap<String, String>) -> Self {
        self.external_functions = functions;
        self
    }

    pub fn set_external_functions(&mut self, functions: std::collections::HashMap<String, String>) {
        self.external_functions = functions;
    }

    /// 设置 native addon 配置（用于 FFI 桥接）
    pub fn with_native_addons(mut self, addons: std::collections::HashMap<String, crate::project::NativeAddonConfig>) -> Self {
        self.native_addon_config = addons;
        self
    }

    /// 设置 native addon 配置（可变引用版本）
    pub fn set_native_addons(&mut self, addons: std::collections::HashMap<String, crate::project::NativeAddonConfig>) {
        self.native_addon_config = addons;
    }

    /// 设置 QuickJS fallback 包列表
    pub fn with_qjs_fallback(mut self, fallback: Vec<String>) -> Self {
        self.js_engine_fallback = fallback;
        self
    }

    /// 设置 QuickJS fallback 包列表（可变引用版本）
    pub fn set_qjs_fallback(&mut self, fallback: Vec<String>) {
        self.js_engine_fallback = fallback;
    }

    /// 编译为 COFF .obj 字节流（标准格式）
    pub fn compile_coff(&mut self, exprs: &mut [HirExpr]) -> Result<Vec<u8>> {
        use std::time::Instant;
        let codegen_start = Instant::now();

        let mut flag_builder = settings::builder();
        flag_builder.set("use_colocated_libcalls", "false").unwrap();
        flag_builder.set("is_pic", "false").unwrap();
        flag_builder.set("opt_level", "speed").unwrap();
        let isa = cranelift_native::builder()
            .map_err(|e| anyhow::anyhow!("{}", e))?;
        let isa = isa.finish(settings::Flags::new(flag_builder))?;

        let builder = ObjectBuilder::new(
            isa,
            "ts_native",
            cranelift_module::default_libcall_names(),
        )?;
        let mut module: ObjectModule = ObjectModule::new(builder);

        // 第一遍：收集所有函数签名和字符串常量
        tsn_diag_codegen!("compile_coff: {} HIR expressions", exprs.len());
        for (i, expr) in exprs.iter().enumerate() {
            if let HirExpr::Function { name, .. } = expr {
                tsn_diag_codegen!("  HIR[{}]: Function '{}'", i, name);
            }
            if let HirExpr::AsyncFunction { name, .. } = expr {
                tsn_diag_codegen!("  HIR[{}]: AsyncFunction '{}'", i, name);
            }

            if let HirExpr::Function { name, params, body } = expr {
                // 检测 rest 参数函数（body 中存在 js_array_from_args 调用的 Var）
                let is_rest = body.iter().any(|s| {
                    matches!(s, HirExpr::Var { init: Some(init), .. } if matches!(
                        init.as_ref(),
                        HirExpr::Call { callee, .. } if matches!(
                            callee.as_ref(),
                            HirExpr::Identifier(cname) if cname == "js_array_from_args"
                        )
                    ))
                });
                if is_rest {
                    self.rest_functions.insert(name.clone());
                }

                let param_count = if is_rest {
                    params.len() + 1 // rest 函数：命名参数 + 一个数组参数
                } else {
                    params.len()
                };
                let mut sig = module.make_signature();
                for _ in 0..param_count {
                    sig.params.push(AbiParam::new(types::F64));
                }
                sig.returns.push(AbiParam::new(types::F64));

                let func_id = module.declare_function(name, Linkage::Export, &sig)?;
                self.function_ids.insert(name.clone(), func_id);
                self.function_param_counts.insert(name.clone(), param_count);
            }
            // AsyncFunction: 签名为 fn(ctx, params...) → f64
            if let HirExpr::AsyncFunction { name, params, body: _ } = expr {
                let mut sig = module.make_signature();
                sig.params.push(AbiParam::new(types::F64)); // ctx_handle
                for _ in params {
                    sig.params.push(AbiParam::new(types::F64));
                }
                sig.returns.push(AbiParam::new(types::F64));

                let func_id = module.declare_function(name, Linkage::Export, &sig)?;
                self.function_ids.insert(name.clone(), func_id);
                // param_count 包含 ctx，所以 +1
                self.function_param_counts.insert(name.clone(), params.len() + 1);
                tsn_diag_codegen!("  Registered async function '{}': params={} (with ctx: {})", name, params.len(), params.len() + 1);
            }
            // Generator 函数：fn(ctx_handle, params...) -> f64（同 async 模式）
            if let HirExpr::Generator { name, params, body: _ } = expr {
                let mut sig = module.make_signature();
                sig.params.push(AbiParam::new(types::F64)); // ctx_handle
                for _ in params {
                    sig.params.push(AbiParam::new(types::F64));
                }
                sig.returns.push(AbiParam::new(types::F64));
                let func_id = module.declare_function(name, Linkage::Export, &sig)?;
                self.function_ids.insert(name.clone(), func_id);
                self.function_param_counts.insert(name.clone(), params.len() + 1);
                tsn_diag_codegen!("  Registered generator '{}': params={} (with ctx: {})", name, params.len(), params.len() + 1);
            }
            // 新增：提取 class 的方法为独立函数
            if let HirExpr::Class { name, constructor, methods, .. } = expr {
                // constructor -> ClassName_constructor
                if let Some(HirExpr::Function { name: _, params, body: _ }) = constructor.as_deref() {
                    let ctor_name = format!("{}_constructor", name);
                    let mut sig = module.make_signature();
                    // constructor 第一个参数是 this（实例对象）
                    sig.params.push(AbiParam::new(types::F64)); // this
                    for _ in params {
                        sig.params.push(AbiParam::new(types::F64));
                    }
                    sig.returns.push(AbiParam::new(types::F64));
                    let func_id = module.declare_function(&ctor_name, Linkage::Export, &sig)?;
                    self.function_ids.insert(ctor_name.clone(), func_id);
                    self.function_param_counts.insert(ctor_name, params.len() + 1); // +1 for this
                }
                // methods -> ClassName_methodName
                for method in methods {
                    let method_name = format!("{}_{}", name, method.name);
                    let mut sig = module.make_signature();
                    // 方法第一个参数是 this（实例对象）
                    sig.params.push(AbiParam::new(types::F64)); // this
                    for _ in &method.params {
                        sig.params.push(AbiParam::new(types::F64));
                    }
                    sig.returns.push(AbiParam::new(types::F64));
                    let func_id = module.declare_function(&method_name, Linkage::Export, &sig)?;
                    self.function_ids.insert(method_name.clone(), func_id);
                    self.function_param_counts.insert(method_name, method.params.len() + 1); // +1 for this
                    // 注册方法名查找：greet -> MyClass_greet
                    self.class_methods.insert(method.name.clone(), format!("{}_{}", name, method.name));
                }
            }
            self.collect_strings(expr);
        }

        // === 第一遍扩展：发现并注册嵌套匿名函数（闭包/箭头函数） ===
        let anon_count = self.discover_nested_functions(&mut *exprs, &mut module)?;
        if anon_count > 0 {
            debug!("Discovered {} anonymous/nested function(s)", anon_count);
        }

        // 收集所有模块导入绑定
        for expr in exprs.iter() {
            // 顶层 ImportBinding
            if let HirExpr::ImportBinding { local, module, imported } = expr {
                self.import_bindings.insert(local.clone(), (module.clone(), imported.clone()));
            }
            // 函数体内的 ImportBinding
            if let HirExpr::Function { body, .. } = expr {
                for stmt in body {
                    if let HirExpr::ImportBinding { local, module, imported } = stmt {
                        self.import_bindings.insert(local.clone(), (module.clone(), imported.clone()));
                    }
                }
            }
        }


        // 收集 native addon 的外部函数映射
        // 当 import_bindings 中的 module 是 native addon 时，生成 addon_ 前缀的外部符号
        for (local, (module, imported)) in &self.import_bindings {
            if let Some(addon_config) = self.native_addon_config.get(module) {
                if let Some(_dll_fn) = addon_config.functions.get(imported) {
                    // 生成外部符号名：addon_<包名>_<函数名>
                    let extern_name = format!("addon_{}_{}", module, imported);
                    self.external_functions.insert(local.clone(), extern_name.clone());
                }
            }
        }

        // 创建字符串数据对象
        let mut string_data: std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)> = std::collections::HashMap::new();
        for string in self.string_pool.iter() {
            let data_name = format!("str_{}", string_data.len());
            let data_id = module.declare_data(&data_name, Linkage::Local, false, false)?;

            let mut data_ctx = DataContext::new();
            let mut bytes: Vec<u8> = string.bytes().collect();
            bytes.push(0);
            data_ctx.define(bytes.clone().into_boxed_slice());

            string_data.insert(string.clone(), (data_id, bytes));
            module.define_data(data_id, &data_ctx)?;
        }

        // 第二遍：编译函数体
        for expr in exprs.iter_mut() {
            if let HirExpr::Function { name, params, body } = expr {
                self.compile_function(&mut module, name, params, body, &string_data)?;
            }
            if let HirExpr::AsyncFunction { name, params, body } = expr {
                // 使用轻量微状态机编译 async 函数
                self.compile_async_function(&mut module, name, params, body, &string_data)?;
            }
            if let HirExpr::Generator { name, params, body } = expr {
                // 使用状态机编译 generator（类似 async，但 yield 返回值）
                self.compile_generator_function(&mut module, name, params, body, &string_data)?;
            }
            // 新增：编译 class 的方法体
            if let HirExpr::Class { name, constructor, methods, .. } = expr {
                // 编译 constructor
                if let Some(HirExpr::Function { params, body, .. }) = constructor.as_deref() {
                    let ctor_name = format!("{}_constructor", name);
                    // constructor 的参数：第一个是 this，后面是用户参数
                    let mut ctor_params = vec!["this".to_string()];
                    ctor_params.extend(params.iter().cloned());
                    self.compile_function(&mut module, &ctor_name, &ctor_params, body, &string_data)?;
                }
                // 编译 methods
                for method in methods {
                    let method_name = format!("{}_{}", name, method.name);
                    let mut method_params = vec!["this".to_string()];
                    method_params.extend(method.params.iter().cloned());
                    self.compile_function(&mut module, &method_name, &method_params, &method.body, &string_data)?;
                }
            }
        }

        // === 第二遍扩展：编译所有嵌套函数表达式（闭包/箭头函数） ===
        self.compile_nested_functions(&mut *exprs, &mut module, &string_data, true)?;

        let product = module.finish();

        // 直接输出 COFF 字节流
        let coff_bytes = product.object.write().unwrap_or_default();

        // 更新编译统计
        self.stats.codegen_time_ms = codegen_start.elapsed().as_millis() as u64;
        self.stats.function_count = self.function_ids.len();
        self.stats.string_count = self.string_pool.len();
        self.stats.code_size = coff_bytes.len();

        trace!("Compile stats: codegen={}ms, functions={}, strings={}, code_size={}bytes",
            self.stats.codegen_time_ms, self.stats.function_count,
            self.stats.string_count, self.stats.code_size);

        Ok(coff_bytes)
    }

    /// 编译并提取原始模块数据（供 JIT/FFI 路径使用）
    pub fn compile_to_raw_data(&mut self, exprs: &mut [HirExpr]) -> Result<RawModuleData> {
        // 复用 compile_coff 的编译逻辑，然后从 COFF 提取数据
        let coff_bytes = self.compile_coff(exprs)?;

        // 从 COFF 字节流解析原始数据
        let object_file = object::read::coff::CoffFile::parse(coff_bytes.as_slice())
            .map_err(|e| anyhow::anyhow!("COFF parse error: {}", e))?;

        let mut raw = RawModuleData {
            functions: std::collections::HashMap::new(),
            data_items: std::collections::HashMap::new(),
            symbols: Vec::new(),
            relocations: Vec::new(),
        };

        // 遍历 section，按类型分类
        let mut section_map: std::collections::HashMap<usize, u8> = std::collections::HashMap::new();
        let mut section_data_map: std::collections::HashMap<usize, &[u8]> = std::collections::HashMap::new();

        for section in object_file.sections() {
            let index = section.index().0;
            let kind = section.kind();
            let data = section.data().unwrap_or(&[]);

            let our_section = match kind {
                object::SectionKind::Text => 0u8,
                object::SectionKind::Data => 1u8,
                object::SectionKind::ReadOnlyData | object::SectionKind::ReadOnlyString => 2u8,
                _ => continue,
            };

            if !data.is_empty() {
                section_data_map.insert(index, data);
                if our_section == 0 {
                    raw.functions.insert(format!("__text_{}", index), data.to_vec());
                } else {
                    raw.data_items.insert(format!("__section_{}", index), data.to_vec());
                }
            }

            section_map.insert(index, our_section);
        }

        // 遍历符号
        for symbol in object_file.symbols() {
            let name = symbol.name().unwrap_or("").to_string();
            let is_undefined = symbol.is_undefined();
            let section_index = symbol.section_index();

            if name.is_empty() { continue; }

            if is_undefined {
                raw.symbols.push(RawSymbol {
                    name,
                    section: 0xFF,
                    offset: 0,
                    is_global: true,
                });
            } else if let Some(idx) = section_index {
                let our_section = *section_map.get(&idx.0).unwrap_or(&0xFF);
                raw.symbols.push(RawSymbol {
                    name,
                    section: our_section,
                    offset: symbol.address() as u32,
                    is_global: true,
                });
            }
        }

        // 遍历重定位
        for section in object_file.sections() {
            let sec_idx = section.index().0;
            let our_section = *section_map.get(&sec_idx).unwrap_or(&0xFF);

            for (offset, reloc) in section.relocations() {
                let target_name = match reloc.target() {
                    object::RelocationTarget::Symbol(sym_idx) => {
                        if let Ok(target_sym) = object_file.symbol_by_index(sym_idx) {
                            target_sym.name().unwrap_or("unknown").to_string()
                        } else {
                            "unknown".to_string()
                        }
                    }
                    _ => continue,
                };

                raw.relocations.push(RawRelocation {
                    section: our_section,
                    offset: offset as u32,
                    reloc_type: match reloc.kind() {
                        object::RelocationKind::Relative => 0,  // REL32
                        object::RelocationKind::Absolute => 1,  // ADDR64
                        _ => 1,
                    },
                    target_symbol: target_name,
                });
            }
        }

        Ok(raw)
    }

    fn collect_strings(&mut self, expr: &HirExpr) {
        match expr {
            HirExpr::String(s) => {
                self.string_pool.insert(s.clone());
            }
            HirExpr::BigInt(s) => {
                // BigInt 字面量字符串也可能包含在代码中，但通常不需要入池
                // 保留为空以保持 match 完整性
            }
            HirExpr::Binary { left, right, .. } => {
                self.collect_strings(left);
                self.collect_strings(right);
            }
            HirExpr::Unary { operand, .. } => {
                self.collect_strings(operand);
            }
            HirExpr::Typeof(expr) => {
                self.collect_strings(expr);
            }
            HirExpr::Call { callee, args } => {
                self.collect_strings(callee);
                for arg in args {
                    self.collect_strings(arg);
                }
            }
            HirExpr::Ternary { cond, then_expr, else_expr } => {
                self.collect_strings(cond);
                self.collect_strings(then_expr);
                self.collect_strings(else_expr);
            }
            HirExpr::Function { body, .. } | HirExpr::AsyncFunction { body, .. } => {
                for stmt in body {
                    self.collect_strings(stmt);
                }
            }
            HirExpr::Return(val) => {
                if let Some(v) = val {
                    self.collect_strings(v);
                }
            }
            HirExpr::Var { init, .. } => {
                if let Some(i) = init {
                    self.collect_strings(i);
                }
            }
            HirExpr::If { cond, then_body, else_body } => {
                self.collect_strings(cond);
                for stmt in then_body {
                    self.collect_strings(stmt);
                }
                if let Some(else_stmts) = else_body {
                    for stmt in else_stmts {
                        self.collect_strings(stmt);
                    }
                }
            }
            HirExpr::While { cond, body } => {
                self.collect_strings(cond);
                for stmt in body {
                    self.collect_strings(stmt);
                }
            }
            HirExpr::For { init, cond, update, body } => {
                if let Some(i) = init {
                    self.collect_strings(i);
                }
                if let Some(c) = cond {
                    self.collect_strings(c);
                }
                if let Some(u) = update {
                    self.collect_strings(u);
                }
                for stmt in body {
                    self.collect_strings(stmt);
                }
            }
            HirExpr::Block(stmts) => {
                for stmt in stmts {
                    self.collect_strings(stmt);
                }
            }
            HirExpr::Assign { target, value } => {
                self.collect_strings(target);
                self.collect_strings(value);
            }
            HirExpr::Array(elements) => {
                for elem in elements {
                    self.collect_strings(elem);
                }
            }
            HirExpr::Index { object, index } => {
                self.collect_strings(object);
                self.collect_strings(index);
            }
            HirExpr::Object(properties) => {
                for (_, value) in properties {
                    self.collect_strings(value);
                }
            }
            HirExpr::Property { object, .. } => {
                self.collect_strings(object);
            }
            HirExpr::TryCatch { try_body, catch_body, finally_body, .. } => {
                for stmt in try_body {
                    self.collect_strings(stmt);
                }
                if let Some(body) = catch_body {
                    for stmt in body {
                        self.collect_strings(stmt);
                    }
                }
                if let Some(body) = finally_body {
                    for stmt in body {
                        self.collect_strings(stmt);
                    }
                }
            }
            HirExpr::Throw(val) => {
                if let Some(v) = val {
                    self.collect_strings(v);
                }
            }
            HirExpr::ExprStmt(expr) => {
                self.collect_strings(expr);
            }

            // Class
            HirExpr::Class { methods, .. } => {
                for method in methods {
                    for stmt in &method.body {
                        self.collect_strings(stmt);
                    }
                }
            }
            HirExpr::New { args, .. } => {
                for arg in args {
                    self.collect_strings(arg);
                }
            }

            // Decorator
            HirExpr::Decorator { args, .. } => {
                for arg in args {
                    self.collect_strings(arg);
                }
            }
            HirExpr::DecoratedClass { decorators, methods, .. } => {
                for dec in decorators {
                    self.collect_strings(dec);
                }
                for method in methods {
                    for stmt in &method.body {
                        self.collect_strings(stmt);
                    }
                }
            }
            HirExpr::DecoratedMethod { decorators, body, .. } => {
                for dec in decorators {
                    self.collect_strings(dec);
                }
                for stmt in body {
                    self.collect_strings(stmt);
                }
            }

            // Generator
            HirExpr::Generator { body, .. } => {
                for stmt in body {
                    self.collect_strings(stmt);
                }
            }
            HirExpr::Yield(value) => {
                self.collect_strings(value);
            }
            HirExpr::YieldFrom(value) => {
                self.collect_strings(value);
            }

            // Async
            HirExpr::Await(value) => {
                self.collect_strings(value);
            }
            _ => {}
        }
    }

    /// 递归发现并注册嵌套匿名函数（闭包/箭头函数），生成唯一名称。
    /// 返回发现的嵌套函数数量。
    fn discover_nested_functions(
        &mut self,
        exprs: &mut [HirExpr],
        module: &mut ObjectModule,
    ) -> Result<u32> {
        let mut counter: u32 = 0;
        // 递归 walk，is_top_level=true 跳过顶层函数声明
        Self::walk_nested_functions(
            exprs, &mut counter, self, module, true,
        )?;
        Ok(counter)
    }

    /// 递归遍历 HIR 树中的表达式，发现并重命名嵌套函数
    fn walk_nested_functions(
        exprs: &mut [HirExpr],
        counter: &mut u32,
        codegen: &mut CodeGen,
        module: &mut ObjectModule,
        is_top_level: bool,
    ) -> Result<()> {
        for expr in exprs.iter_mut() {
            Self::walk_one_nested(expr, counter, codegen, module, is_top_level)?;
        }
        Ok(())
    }

    fn walk_one_nested(
        expr: &mut HirExpr,
        counter: &mut u32,
        codegen: &mut CodeGen,
        module: &mut ObjectModule,
        is_top_level: bool,
    ) -> Result<()> {
        match expr {
            HirExpr::Function { ref mut name, params, body } => {
                if !is_top_level {
                    // 检测 rest 参数
                    let is_rest = body.iter().any(|s| {
                        matches!(s, HirExpr::Var { init: Some(init), .. } if matches!(
                            init.as_ref(),
                            HirExpr::Call { callee, .. } if matches!(
                                callee.as_ref(),
                                HirExpr::Identifier(cname) if cname == "js_array_from_args"
                            )
                        ))
                    });
                    if is_rest {
                        codegen.rest_functions.insert(name.clone());
                    }
                    let param_count = if is_rest { params.len() + 1 } else { params.len() };

                    // 只有匿名函数才重命名，命名函数保留原名以便调用处能找到
                    let needs_rename = name.as_str() == "anonymous"
                        || name.starts_with("$anon_");
                    if needs_rename {
                        let unique_name = format!("$anon_{}", *counter);
                        *counter += 1;
                        // 注册函数签名
                        let mut sig = module.make_signature();
                        for _ in 0..param_count {
                            sig.params.push(AbiParam::new(types::F64));
                        }
                        sig.returns.push(AbiParam::new(types::F64));
                        let func_id = module.declare_function(&unique_name, Linkage::Export, &sig)
                            .map_err(|e| anyhow::anyhow!("{}", e))?;
                        codegen.function_ids.insert(unique_name.clone(), func_id);
                        codegen.function_param_counts.insert(unique_name.clone(), param_count);
                        debug!("Registered nested function '{}' → '{}' ({} params)", name, unique_name, param_count);
                        *name = unique_name;
                    } else {
                        // 命名嵌套函数：用原名注册
                        let mut sig = module.make_signature();
                        for _ in 0..param_count {
                            sig.params.push(AbiParam::new(types::F64));
                        }
                        sig.returns.push(AbiParam::new(types::F64));
                        let func_id = module.declare_function(name, Linkage::Export, &sig)
                            .map_err(|e| anyhow::anyhow!("{}", e))?;
                        codegen.function_ids.insert(name.clone(), func_id);
                        codegen.function_param_counts.insert(name.clone(), param_count);
                        debug!("Registered nested function '{}' ({} params)", name, param_count);
                    }
                }
                // 递归扫描函数体
                Self::walk_nested_functions(body.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::AsyncFunction { ref mut name, params, body } => {
                if !is_top_level {
                    let needs_rename = name.as_str() == "anonymous"
                        || !codegen.function_ids.contains_key(name.as_str());
                    if needs_rename {
                        let unique_name = format!("$anon_{}", *counter);
                        *counter += 1;
                        let mut sig = module.make_signature();
                        sig.params.push(AbiParam::new(types::F64)); // ctx
                        for _ in params.iter() {
                            sig.params.push(AbiParam::new(types::F64));
                        }
                        sig.returns.push(AbiParam::new(types::F64));
                        let func_id = module.declare_function(&unique_name, Linkage::Export, &sig)
                            .map_err(|e| anyhow::anyhow!("{}", e))?;
                        codegen.function_ids.insert(unique_name.clone(), func_id);
                        codegen.function_param_counts.insert(unique_name.clone(), params.len() + 1);
                        *name = unique_name;
                    }
                }
                Self::walk_nested_functions(body.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Generator { ref mut name, params, body } => {
                if !is_top_level && !codegen.function_ids.contains_key(name.as_str()) {
                    let unique_name = format!("$anon_{}", *counter);
                    *counter += 1;
                    let mut sig = module.make_signature();
                    sig.params.push(AbiParam::new(types::F64)); // ctx
                    for _ in params.iter() {
                        sig.params.push(AbiParam::new(types::F64));
                    }
                    sig.returns.push(AbiParam::new(types::F64));
                    let func_id = module.declare_function(&unique_name, Linkage::Export, &sig)
                        .map_err(|e| anyhow::anyhow!("{}", e))?;
                    codegen.function_ids.insert(unique_name.clone(), func_id);
                    codegen.function_param_counts.insert(unique_name.clone(), params.len() + 1);
                    *name = unique_name;
                }
                Self::walk_nested_functions(body.as_mut_slice(), counter, codegen, module, false)?;
            }
            // 遍历所有子节点
            HirExpr::Binary { left, right, .. } => {
                Self::walk_one_nested(left, counter, codegen, module, false)?;
                Self::walk_one_nested(right, counter, codegen, module, false)?;
            }
            HirExpr::Unary { operand, .. } | HirExpr::Typeof(operand) => {
                Self::walk_one_nested(operand, counter, codegen, module, false)?;
            }
            HirExpr::Call { callee, args } => {
                Self::walk_one_nested(callee, counter, codegen, module, false)?;
                Self::walk_nested_functions(args.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Ternary { cond, then_expr, else_expr } => {
                Self::walk_one_nested(cond, counter, codegen, module, false)?;
                Self::walk_one_nested(then_expr, counter, codegen, module, false)?;
                Self::walk_one_nested(else_expr, counter, codegen, module, false)?;
            }
            HirExpr::Return(Some(val)) => {
                Self::walk_one_nested(val, counter, codegen, module, false)?;
            }
            HirExpr::Var { init: Some(init), .. } => {
                Self::walk_one_nested(init, counter, codegen, module, false)?;
            }
            HirExpr::If { cond, then_body, else_body } => {
                Self::walk_one_nested(cond, counter, codegen, module, false)?;
                Self::walk_nested_functions(then_body.as_mut_slice(), counter, codegen, module, false)?;
                if let Some(else_stmts) = else_body.as_mut() {
                    Self::walk_nested_functions(else_stmts.as_mut_slice(), counter, codegen, module, false)?;
                }
            }
            HirExpr::While { cond, body } => {
                Self::walk_one_nested(cond, counter, codegen, module, false)?;
                Self::walk_nested_functions(body.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::For { init, cond, update, body } => {
                if let Some(i) = init.as_mut() { Self::walk_one_nested(i, counter, codegen, module, false)?; }
                if let Some(c) = cond.as_mut() { Self::walk_one_nested(c, counter, codegen, module, false)?; }
                if let Some(u) = update.as_mut() { Self::walk_one_nested(u, counter, codegen, module, false)?; }
                Self::walk_nested_functions(body.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Block(stmts) | HirExpr::Seq(stmts) => {
                Self::walk_nested_functions(stmts.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Assign { target, value } => {
                Self::walk_one_nested(target, counter, codegen, module, false)?;
                Self::walk_one_nested(value, counter, codegen, module, false)?;
            }
            HirExpr::Array(elements) => {
                Self::walk_nested_functions(elements.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Index { object, index } => {
                Self::walk_one_nested(object, counter, codegen, module, false)?;
                Self::walk_one_nested(index, counter, codegen, module, false)?;
            }
            HirExpr::Object(properties) => {
                for (_, value) in properties.iter_mut() {
                    Self::walk_one_nested(value, counter, codegen, module, false)?;
                }
            }
            HirExpr::Property { object, .. } => {
                Self::walk_one_nested(object, counter, codegen, module, false)?;
            }
            HirExpr::ExprStmt(e) => {
                Self::walk_one_nested(e, counter, codegen, module, false)?;
            }
            HirExpr::TryCatch { try_body, catch_body, finally_body, .. } => {
                Self::walk_nested_functions(try_body.as_mut_slice(), counter, codegen, module, false)?;
                if let Some(cb) = catch_body.as_mut() {
                    Self::walk_nested_functions(cb.as_mut_slice(), counter, codegen, module, false)?;
                }
                if let Some(fb) = finally_body.as_mut() {
                    Self::walk_nested_functions(fb.as_mut_slice(), counter, codegen, module, false)?;
                }
            }
            HirExpr::Throw(Some(val)) => {
                Self::walk_one_nested(val, counter, codegen, module, false)?;
            }
            HirExpr::Class { constructor, methods, .. } => {
                if let Some(ctor) = constructor.as_mut() {
                    Self::walk_one_nested(ctor, counter, codegen, module, false)?;
                }
                for method in methods.iter_mut() {
                    Self::walk_nested_functions(method.body.as_mut_slice(), counter, codegen, module, false)?;
                }
            }
            HirExpr::New { args, .. } => {
                Self::walk_nested_functions(args.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Decorator { args, .. } => {
                Self::walk_nested_functions(args.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::SuperCall(args) | HirExpr::SuperMethod { args, .. } => {
                Self::walk_nested_functions(args.as_mut_slice(), counter, codegen, module, false)?;
            }
            HirExpr::Yield(val) | HirExpr::YieldFrom(val) | HirExpr::Await(val) => {
                Self::walk_one_nested(val, counter, codegen, module, false)?;
            }
            HirExpr::RegexTest { regex, text } | HirExpr::RegexExec { regex, text } | HirExpr::RegexMatch { regex, text } => {
                Self::walk_one_nested(regex, counter, codegen, module, false)?;
                Self::walk_one_nested(text, counter, codegen, module, false)?;
            }
            HirExpr::DecoratedClass { decorators, constructor, methods, .. } => {
                for dec in decorators.iter_mut() { Self::walk_one_nested(dec, counter, codegen, module, false)?; }
                if let Some(ctor) = constructor.as_mut() { Self::walk_one_nested(ctor, counter, codegen, module, false)?; }
                for method in methods.iter_mut() {
                    Self::walk_nested_functions(method.body.as_mut_slice(), counter, codegen, module, false)?;
                }
            }
            HirExpr::DecoratedMethod { decorators, body, .. } => {
                for dec in decorators.iter_mut() { Self::walk_one_nested(dec, counter, codegen, module, false)?; }
                Self::walk_nested_functions(body.as_mut_slice(), counter, codegen, module, false)?;
            }
            // Leaf nodes: no children to walk
            HirExpr::Number(_) | HirExpr::BigInt(_) | HirExpr::Boolean(_) | HirExpr::String(_)
            | HirExpr::Null | HirExpr::Undefined | HirExpr::Identifier(_)
            | HirExpr::This | HirExpr::Break | HirExpr::Continue
            | HirExpr::ImportBinding { .. } | HirExpr::Export { .. }
            | HirExpr::Regex { .. } | HirExpr::Return(None)
            | HirExpr::Throw(None) | HirExpr::Var { init: None, .. } => {}
        }
        Ok(())
    }

    /// 递归编译所有嵌套函数表达式（闭包/箭头函数）。
    /// is_top_level=true 表示跳过顶层函数声明（已在主循环中编译）。
    fn compile_nested_functions(
        &mut self,
        exprs: &mut [HirExpr],
        module: &mut ObjectModule,
        string_data: &std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
        is_top_level: bool,
    ) -> Result<()> {
        for expr in exprs.iter_mut() {
            Self::compile_one_nested(expr, self, module, string_data, is_top_level)?;
        }
        Ok(())
    }

    fn compile_one_nested(
        expr: &mut HirExpr,
        codegen: &mut CodeGen,
        module: &mut ObjectModule,
        string_data: &std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
        is_top_level: bool,
    ) -> Result<()> {
        match expr {
            HirExpr::Function { name, params, body } => {
                if !is_top_level {
                    // 编译嵌套函数（已在第一遍注册为 $anon_N）
                    codegen.compile_function(module, name, params, body, string_data)?;
                }
                // 递归扫描函数体中的更深层嵌套
                codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::AsyncFunction { name, params, body } => {
                if !is_top_level {
                    codegen.compile_async_function(module, name, params, body, string_data)?;
                }
                codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Generator { name, params, body } => {
                if !is_top_level {
                    codegen.compile_generator_function(module, name, params, body, string_data)?;
                }
                codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
            }
            // 遍历子节点
            HirExpr::Binary { left, right, .. } => {
                Self::compile_one_nested(left, codegen, module, string_data, false)?;
                Self::compile_one_nested(right, codegen, module, string_data, false)?;
            }
            HirExpr::Unary { operand, .. } | HirExpr::Typeof(operand) => {
                Self::compile_one_nested(operand, codegen, module, string_data, false)?;
            }
            HirExpr::Call { callee, args } => {
                Self::compile_one_nested(callee, codegen, module, string_data, false)?;
                codegen.compile_nested_functions(args.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Ternary { cond, then_expr, else_expr } => {
                Self::compile_one_nested(cond, codegen, module, string_data, false)?;
                Self::compile_one_nested(then_expr, codegen, module, string_data, false)?;
                Self::compile_one_nested(else_expr, codegen, module, string_data, false)?;
            }
            HirExpr::Return(Some(val)) => {
                Self::compile_one_nested(val, codegen, module, string_data, false)?;
            }
            HirExpr::Var { init: Some(init), .. } => {
                Self::compile_one_nested(init, codegen, module, string_data, false)?;
            }
            HirExpr::If { cond, then_body, else_body } => {
                Self::compile_one_nested(cond, codegen, module, string_data, false)?;
                codegen.compile_nested_functions(then_body.as_mut_slice(), module, string_data, false)?;
                if let Some(else_stmts) = else_body.as_mut() {
                    codegen.compile_nested_functions(else_stmts.as_mut_slice(), module, string_data, false)?;
                }
            }
            HirExpr::While { cond, body } => {
                Self::compile_one_nested(cond, codegen, module, string_data, false)?;
                codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::For { init, cond, update, body } => {
                if let Some(i) = init.as_mut() { Self::compile_one_nested(i, codegen, module, string_data, false)?; }
                if let Some(c) = cond.as_mut() { Self::compile_one_nested(c, codegen, module, string_data, false)?; }
                if let Some(u) = update.as_mut() { Self::compile_one_nested(u, codegen, module, string_data, false)?; }
                codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Block(stmts) | HirExpr::Seq(stmts) => {
                codegen.compile_nested_functions(stmts.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Assign { target, value } => {
                Self::compile_one_nested(target, codegen, module, string_data, false)?;
                Self::compile_one_nested(value, codegen, module, string_data, false)?;
            }
            HirExpr::Array(elements) => {
                codegen.compile_nested_functions(elements.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Index { object, index } => {
                Self::compile_one_nested(object, codegen, module, string_data, false)?;
                Self::compile_one_nested(index, codegen, module, string_data, false)?;
            }
            HirExpr::Object(properties) => {
                for (_, value) in properties.iter_mut() {
                    Self::compile_one_nested(value, codegen, module, string_data, false)?;
                }
            }
            HirExpr::Property { object, .. } => {
                Self::compile_one_nested(object, codegen, module, string_data, false)?;
            }
            HirExpr::ExprStmt(e) => {
                Self::compile_one_nested(e, codegen, module, string_data, false)?;
            }
            HirExpr::TryCatch { try_body, catch_body, finally_body, .. } => {
                codegen.compile_nested_functions(try_body.as_mut_slice(), module, string_data, false)?;
                if let Some(cb) = catch_body.as_mut() { codegen.compile_nested_functions(cb.as_mut_slice(), module, string_data, false)?; }
                if let Some(fb) = finally_body.as_mut() { codegen.compile_nested_functions(fb.as_mut_slice(), module, string_data, false)?; }
            }
            HirExpr::Throw(Some(val)) => {
                Self::compile_one_nested(val, codegen, module, string_data, false)?;
            }
            // Class 节点：方法已在主循环中通过专门逻辑编译，此处只递归扫描内部嵌套函数
            HirExpr::Class { constructor, methods, .. } => {
                if let Some(ctor) = constructor.as_mut() {
                    // constructor body 可能含嵌套函数
                    if let HirExpr::Function { body, .. } = ctor.as_mut() {
                        codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
                    }
                }
                for method in methods.iter_mut() {
                    codegen.compile_nested_functions(method.body.as_mut_slice(), module, string_data, false)?;
                }
            }
            HirExpr::New { args, .. } => {
                codegen.compile_nested_functions(args.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Decorator { args, .. } | HirExpr::SuperCall(args) | HirExpr::SuperMethod { args, .. } => {
                codegen.compile_nested_functions(args.as_mut_slice(), module, string_data, false)?;
            }
            HirExpr::Yield(val) | HirExpr::YieldFrom(val) | HirExpr::Await(val) => {
                Self::compile_one_nested(val, codegen, module, string_data, false)?;
            }
            HirExpr::RegexTest { regex, text } | HirExpr::RegexExec { regex, text } | HirExpr::RegexMatch { regex, text } => {
                Self::compile_one_nested(regex, codegen, module, string_data, false)?;
                Self::compile_one_nested(text, codegen, module, string_data, false)?;
            }
            HirExpr::DecoratedClass { decorators, constructor, methods, .. } => {
                for dec in decorators.iter_mut() { Self::compile_one_nested(dec, codegen, module, string_data, false)?; }
                if let Some(ctor) = constructor.as_mut() {
                    if let HirExpr::Function { body, .. } = ctor.as_mut() {
                        codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
                    }
                }
                for method in methods.iter_mut() {
                    codegen.compile_nested_functions(method.body.as_mut_slice(), module, string_data, false)?;
                }
            }
            HirExpr::DecoratedMethod { decorators, body, .. } => {
                for dec in decorators.iter_mut() { Self::compile_one_nested(dec, codegen, module, string_data, false)?; }
                codegen.compile_nested_functions(body.as_mut_slice(), module, string_data, false)?;
            }
            // Leaf nodes
            HirExpr::Number(_) | HirExpr::BigInt(_) | HirExpr::Boolean(_) | HirExpr::String(_)
            | HirExpr::Null | HirExpr::Undefined | HirExpr::Identifier(_)
            | HirExpr::This | HirExpr::Break | HirExpr::Continue
            | HirExpr::ImportBinding { .. } | HirExpr::Export { .. }
            | HirExpr::Regex { .. } | HirExpr::Return(None)
            | HirExpr::Throw(None) | HirExpr::Var { init: None, .. } => {}
        }
        Ok(())
    }

    // ==================== 异步函数分析 ====================

    /// 分析 async 函数体，返回按 await 分割的段落
    /// 返回: (segments, var_slots, await_count)
    /// - segments: 按 await 分割的段落列表，每段是不含 Await 的 HIR 列表
    /// - var_slots: 局部变量名 → 槽位索引的映射
    /// - await_count: await 表达式总数
    fn analyze_async_body(
        body: &[HirExpr],
    ) -> (Vec<Vec<HirExpr>>, std::collections::HashMap<String, usize>, usize) {
        let mut segments: Vec<Vec<HirExpr>> = vec![Vec::new()];
        let mut var_slots: std::collections::HashMap<String, usize> = std::collections::HashMap::new();
        let mut next_slot: usize = 0;
        let mut await_count: usize = 0;

        /// 递归收集变量声明
        fn collect_vars(expr: &HirExpr, var_slots: &mut std::collections::HashMap<String, usize>, next_slot: &mut usize) {
            match expr {
                HirExpr::Var { name, init, .. } => {
                    if !var_slots.contains_key(name) && !name.is_empty() {
                        var_slots.insert(name.clone(), *next_slot);
                        *next_slot += 1;
                    }
                    if let Some(init) = init {
                        collect_vars(init, var_slots, next_slot);
                    }
                }
                HirExpr::Await(inner) => {
                    collect_vars(inner, var_slots, next_slot);
                }
                HirExpr::Binary { left, right, .. } => {
                    collect_vars(left, var_slots, next_slot);
                    collect_vars(right, var_slots, next_slot);
                }
                HirExpr::Unary { operand, .. } => {
                    collect_vars(operand, var_slots, next_slot);
                }
                HirExpr::Call { callee, args } => {
                    collect_vars(callee, var_slots, next_slot);
                    for arg in args { collect_vars(arg, var_slots, next_slot); }
                }
                HirExpr::If { cond, then_body, else_body } => {
                    collect_vars(cond, var_slots, next_slot);
                    for s in then_body { collect_vars(s, var_slots, next_slot); }
                    if let Some(eb) = else_body {
                        for s in eb { collect_vars(s, var_slots, next_slot); }
                    }
                }
                HirExpr::While { cond: _, body } | HirExpr::For { cond: Some(_), body, .. } => {
                    if let HirExpr::While { cond, .. } = expr { collect_vars(cond, var_slots, next_slot); }
                    for s in body { collect_vars(s, var_slots, next_slot); }
                }
                HirExpr::For { init, update, body, .. } => {
                    if let Some(init) = init { collect_vars(init, var_slots, next_slot); }
                    if let Some(update) = update { collect_vars(update, var_slots, next_slot); }
                    for s in body { collect_vars(s, var_slots, next_slot); }
                }
                HirExpr::Block(stmts) | HirExpr::Seq(stmts) => {
                    for s in stmts { collect_vars(s, var_slots, next_slot); }
                }
                HirExpr::Function { body, .. } | HirExpr::AsyncFunction { body, .. } => {
                    for s in body { collect_vars(s, var_slots, next_slot); }
                }
                HirExpr::Ternary { cond, then_expr, else_expr } => {
                    collect_vars(cond, var_slots, next_slot);
                    collect_vars(then_expr, var_slots, next_slot);
                    collect_vars(else_expr, var_slots, next_slot);
                }
                HirExpr::TryCatch { try_body, catch_body, finally_body, .. } => {
                    for s in try_body { collect_vars(s, var_slots, next_slot); }
                    if let Some(cb) = catch_body { for s in cb { collect_vars(s, var_slots, next_slot); } }
                    if let Some(fb) = finally_body { for s in fb { collect_vars(s, var_slots, next_slot); } }
                }
                HirExpr::Return(val) => {
                    if let Some(v) = val { collect_vars(v, var_slots, next_slot); }
                }
                HirExpr::Array(elems) => {
                    for v in elems.iter() {
                        collect_vars(v, var_slots, next_slot);
                    }
                }
                HirExpr::Object(props) => {
                    for (_, v) in props.iter() {
                        collect_vars(v, var_slots, next_slot);
                    }
                }
                _ => {}
            }
        }

        /// 递归分割函数体，在 Await 处分段
        fn split_body(
            body: &[HirExpr],
            segments: &mut Vec<Vec<HirExpr>>,
            var_slots: &std::collections::HashMap<String, usize>,
            _next_slot: &mut usize,
            await_count: &mut usize,
        ) {
            for stmt in body {
                match stmt {
                    // Var { init: Await(expr) } → expr 作为当前段结尾，Var 绑定放到下一段
                    HirExpr::Var { name, init: Some(init), is_mut } => {
                        if matches!(init.as_ref(), HirExpr::Await(_)) {
                            if let HirExpr::Await(await_expr) = init.as_ref() {
                                // 注册变量槽位
                                if !var_slots.contains_key(name) {
                                    // 已经在上面的 collect_vars 中注册
                                }
                                // 当前段：计算 await 表达式并存结果
                                segments.last_mut().unwrap().push(HirExpr::ExprStmt(await_expr.clone()));
                                *await_count += 1;
                                // 下一段：从 ctx.result 恢复变量值
                                segments.push(vec![
                                    HirExpr::Var {
                                        name: name.clone(),
                                        init: Some(Box::new(HirExpr::Identifier("__async_result".to_string()))),
                                        is_mut: *is_mut,
                                    }
                                ]);
                            }
                        } else {
                            segments.last_mut().unwrap().push(stmt.clone());
                        }
                    }
                    // 独立的 Await 表达式（不是 Var 的 init）
                    HirExpr::Await(inner) => {
                        segments.last_mut().unwrap().push(HirExpr::ExprStmt(inner.clone()));
                        *await_count += 1;
                        segments.push(Vec::new());
                    }
                    _ => {
                        segments.last_mut().unwrap().push(stmt.clone());
                    }
                }
            }

            // 清理尾部空段
            while segments.len() > 1 && segments.last().map(|s| s.is_empty()).unwrap_or(false) {
                segments.pop();
            }
        }

        // 第一遍：收集所有变量声明
        for stmt in body {
            collect_vars(stmt, &mut var_slots, &mut next_slot);
        }

        // 第二遍：按 await 分割
        split_body(body, &mut segments, &var_slots, &mut next_slot, &mut await_count);

        (segments, var_slots, await_count)
    }

    /// 使用轻量微状态机编译 async 函数
    /// 
    /// 编译策略：
    /// 1. 函数签名为 fn(ctx_handle, params...) → f64
    /// 2. 入口处做状态分发 (switch on ctx.state)
    /// 3. 每个 await 点将函数体分割为独立状态段落
    /// 4. 跨 await 的局部变量通过 ctx.locals[slot] 保存/恢复
    /// 5. 最后一段执行完毕后 return 最终结果
    fn compile_async_function(
        &mut self,
        module: &mut ObjectModule,
        name: &str,
        params: &[String],
        body: &[HirExpr],
        string_data: &std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
    ) -> Result<()> {
        self.set_current_func(name);

        let func_id = *self.function_ids.get(name)
            .ok_or_else(|| anyhow::anyhow!("Async function {} not found", name))?;

        // 分析函数体：分割段落、分配变量槽位
        let (segments, var_slots, await_count) = Self::analyze_async_body(body);
        
        debug!("Async '{}': {} segments, {} await points, {} var slots",
            name, segments.len(), await_count, var_slots.len());

        // 创建函数上下文（签名：ctx + 原始参数）
        let mut ctx_func = module.make_context();
        ctx_func.func.signature.params.push(AbiParam::new(types::F64)); // ctx_handle
        for _ in params {
            ctx_func.func.signature.params.push(AbiParam::new(types::F64));
        }
        ctx_func.func.signature.returns.push(AbiParam::new(types::F64));

        let mut builder = FunctionBuilder::new(&mut ctx_func.func, &mut self.builder_context);

        // === 入口块：绑定参数 ===
        let entry_block = builder.create_block();
        builder.append_block_params_for_function_params(entry_block);
        builder.switch_to_block(entry_block);
        builder.seal_block(entry_block);

        let ctx_val = builder.block_params(entry_block)[0]; // ctx 是第一个参数

        let mut variables = std::collections::HashMap::new();
        // 使用高偏移量避免与 Cranelift 内部变量冲突
        let param_offset: u32 = 1000;
        for (i, param) in params.iter().enumerate() {
            let var = Variable::from_u32(param_offset + i as u32);
            variables.insert(param.clone(), var);
            let val = builder.block_params(entry_block)[i + 1];
            builder.declare_var(var, types::F64);
            builder.def_var(var, val);
        }

        let next_var_start = param_offset + params.len() as u32;

        // 在 async context 中存储函数指针（供事件循环 resume 用）
        let self_func_ref = module.declare_func_in_func(func_id, &mut builder.func);
        let self_func_addr = builder.ins().func_addr(types::I64, self_func_ref);
        let self_func_f64 = builder.ins().bitcast(types::F64, MemFlags::new(), self_func_addr);
        call_import_direct(module, &self.function_ids,
            &self.function_param_counts, string_data,
            &self.import_bindings, &self.module_symbols,
            &self.native_addon_config, &self.js_engine_fallback,
            &mut builder, "js_async_ctx_set_func", &[ctx_val, self_func_f64]);

        // === 分发块：switch on ctx.state ===
        let dispatch_block = builder.create_block();
        let num_states = segments.len();
        // 为每个状态创建独立 Cranelift 块
        let state_blocks: Vec<clcodegen::ir::Block> = (0..num_states)
            .map(|_| builder.create_block())
            .collect();
        // 最终返回块（用于未匹配的状态）
        let fallback_block = builder.create_block();

        builder.ins().jump(dispatch_block, &[]);

        // 分发逻辑
        builder.switch_to_block(dispatch_block);
        // 获取 ctx.state（dispatch_block 在状态段落编译完后 seal，因为段落会跳回它）
        let mut dispatch_ctx = Ctx {
            variables: &mut variables,
            next_var_idx: next_var_start,
            param_names: params,
            module,
            function_ids: &self.function_ids,
            function_param_counts: &self.function_param_counts,
            string_data,
            import_bindings: &self.import_bindings,
            module_symbols: &self.module_symbols,
            native_addon_config: &self.native_addon_config,
            js_engine_fallback: &self.js_engine_fallback,
            last_expr_value: None,
            current_try_check: None,
            class_methods: &self.class_methods,
            entry_block: None,
            declared_param_count: 0,
            rest_functions: &self.rest_functions,
            const_values: &self.const_values,
        };
        let state_val = call_import(&mut dispatch_ctx, &mut builder, "js_async_ctx_get_state", &[ctx_val]);

        // 链式 if-else 分发
        let mut prev_dispatch_block = dispatch_block;
        for i in 0..num_states {
            let expected = builder.ins().f64const(i as f64);
            let cmp = builder.ins().fcmp(FloatCC::Equal, state_val, expected);
            let next_block = builder.create_block();
            builder.ins().brif(cmp, state_blocks[i], &[], next_block, &[]);
            // seal 上一个 dispatch 块（它已有 brif 作为终止符）
            if i > 0 {
                builder.seal_block(prev_dispatch_block);
            }
            builder.switch_to_block(next_block);
            prev_dispatch_block = next_block;
        }
        // seal 最后一个 dispatch 链块（当前块）
        builder.seal_block(prev_dispatch_block);
        // 所有状态均未匹配：跳转到 fallback
        builder.ins().jump(fallback_block, &[]);

        // fallback: 返回 undefined
        builder.switch_to_block(fallback_block);
        builder.seal_block(fallback_block);
        let undef = builder.ins().f64const(f64::from_bits(UNDEFINED));
        builder.ins().return_(&[undef]);

        // === 编译各状态段落 ===
        let mut next_var_idx = next_var_start;
        for (seg_idx, segment) in segments.iter().enumerate() {
            let is_last = seg_idx == segments.len() - 1;
            let block = state_blocks[seg_idx];
            
            builder.switch_to_block(block);
            builder.seal_block(block);

            // 为当前段落创建独立的变量上下文
            let mut seg_vars = variables.clone();

            // 非首段：从 ctx 恢复局部变量
            if seg_idx > 0 {
                // 恢复所有跨 await 的变量（使用临时作用域避免借用冲突）
                for (var_name, slot) in &var_slots {
                    let var = Variable::from_u32(next_var_idx);
                    next_var_idx += 1;
                    let slot_const = builder.ins().f64const(*slot as f64);
                    // 直接调用 runtime 函数而不创建 Ctx
                    let val = call_import_direct(module, &self.function_ids,
                        &self.function_param_counts, string_data,
                        &self.import_bindings, &self.module_symbols,
                        &self.native_addon_config, &self.js_engine_fallback,
                        &mut builder, "js_async_ctx_get_local", &[ctx_val, slot_const]);
                    builder.declare_var(var, types::F64);
                    builder.def_var(var, val);
                    seg_vars.insert(var_name.clone(), var);
                }

                // __async_result 伪变量：加载上一个 await 的结果
                let result_var = Variable::from_u32(next_var_idx);
                next_var_idx += 1;
                let result_val = call_import_direct(module, &self.function_ids,
                    &self.function_param_counts, string_data,
                    &self.import_bindings, &self.module_symbols,
                    &self.native_addon_config, &self.js_engine_fallback,
                    &mut builder, "js_async_ctx_get_result", &[ctx_val]);
                builder.declare_var(result_var, types::F64);
                builder.def_var(result_var, result_val);
                seg_vars.insert("__async_result".to_string(), result_var);
            }

            // 编译段落内的所有语句
            let mut seg_ctx = Ctx {
                variables: &mut seg_vars,
                next_var_idx,
                param_names: params,
                module,
                function_ids: &self.function_ids,
                function_param_counts: &self.function_param_counts,
                string_data,
                import_bindings: &self.import_bindings,
                module_symbols: &self.module_symbols,
                native_addon_config: &self.native_addon_config,
                js_engine_fallback: &self.js_engine_fallback,
                last_expr_value: None,
                current_try_check: None,
                class_methods: &self.class_methods,
                entry_block: None,
                declared_param_count: 0,
                rest_functions: &self.rest_functions,
                const_values: &self.const_values,
            };

            let mut has_return = false;
            for stmt in segment {
                if compile_stmt(stmt, &mut seg_ctx, &mut builder) {
                    has_return = true;
                    break;
                }
            }
            // 将当前段分配的变量 ID 保存回函数级计数器
            next_var_idx = seg_ctx.next_var_idx;

            if !has_return {
                if is_last {
                    // 最后一段：返回 undefined（如果没有显式 return）
                    // 释放所有局部变量（GC）
                    emit_release_locals(&mut seg_ctx, &mut builder, None);
                    let undef_const = builder.ins().f64const(f64::from_bits(UNDEFINED));
                    builder.ins().return_(&[undef_const]);
                } else {
                    // 非最后段：保存变量 → 设置下一状态 → 跳回分发
                    // 提取 last_expr_value（先于 seg_vars 的不可变借用以避免借用冲突）
                    let last_expr_val = seg_ctx.last_expr_value;

                    // 更新全局 variables 以反映新定义的变量
                    for (k, v) in &seg_vars {
                        if !variables.contains_key(k) {
                            variables.insert(k.clone(), *v);
                        }
                    }

                    // 存储 await 结果到 ctx.result（如果当前段末尾是 await 产生的表达式）
                    if let Some(result_val) = last_expr_val {
                        call_import_direct(module, &self.function_ids,
                            &self.function_param_counts, string_data,
                            &self.import_bindings, &self.module_symbols,
                            &self.native_addon_config, &self.js_engine_fallback,
                            &mut builder, "js_async_ctx_set_result", &[ctx_val, result_val]);
                    }

                    // 保存所有跨 await 变量到 ctx（使用直接调用避免借用冲突）
                    for (var_name, slot) in &var_slots {
                        if let Some(&var) = seg_vars.get(var_name) {
                            let val = builder.use_var(var);
                            let slot_const = builder.ins().f64const(*slot as f64);
                            call_import_direct(module, &self.function_ids,
                                &self.function_param_counts, string_data,
                                &self.import_bindings, &self.module_symbols,
                                &self.native_addon_config, &self.js_engine_fallback,
                                &mut builder, "js_async_ctx_set_local", &[ctx_val, slot_const, val]);
                        }
                    }

                    // 设置下一状态
                    let next_state = builder.ins().f64const((seg_idx + 1) as f64);
                    call_import_direct(module, &self.function_ids,
                        &self.function_param_counts, string_data,
                        &self.import_bindings, &self.module_symbols,
                        &self.native_addon_config, &self.js_engine_fallback,
                        &mut builder, "js_async_ctx_set_state", &[ctx_val, next_state]);

                    // 调度事件循环恢复，然后返回（让出控制权）
                    let zero = builder.ins().f64const(0.0);
                    call_import_direct(module, &self.function_ids,
                        &self.function_param_counts, string_data,
                        &self.import_bindings, &self.module_symbols,
                        &self.native_addon_config, &self.js_engine_fallback,
                        &mut builder, "js_schedule", &[ctx_val, next_state, zero]);
                    let undef = builder.ins().f64const(f64::from_bits(UNDEFINED));
                    builder.ins().return_(&[undef]);
                }
            }
        }

        // seal dispatch_block（状态段落都已编译，所有前驱已知）
        builder.seal_block(dispatch_block);

        debug!("Async '{}' compiled: {} blocks", name, builder.func.dfg.num_blocks());
        trace!("IR for async '{}':\n{}", name, builder.func.display());
        builder.finalize();

        if let Err(e) = module.define_function(func_id, &mut ctx_func) {
            return Err(anyhow::anyhow!("Verifier errors for async '{}': {}", name, e));
        }
        module.clear_context(&mut ctx_func);

        Ok(())
    }

    /// 编译 Generator 函数（状态机模式，类似 async 但使用 yield 替代 await）
    fn compile_generator_function(
        &mut self,
        module: &mut ObjectModule,
        name: &str,
        params: &[String],
        body: &[HirExpr],
        string_data: &std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
    ) -> Result<()> {
        tsn_diag_codegen!("Compiling generator '{}' with {} params", name, params.len());

        // 分析 generator 体：变量收集 + yield 分段（复用 async 的分析逻辑）
        let (segments, var_slots, yield_count) = Self::analyze_async_body(body);
        let num_states = segments.len().max(1);

        tsn_diag_codegen!("  Generator '{}': {} states, {} local slots, {} yields", name, num_states, var_slots.len(), yield_count);

        // 注册函数（已在第一遍完成），查找 FuncId
        let func_id = match self.function_ids.get(name) {
            Some(id) => *id,
            None => return Err(anyhow::anyhow!("Generator '{}' not registered", name)),
        };
        let expected_params = self.function_param_counts.get(name).copied().unwrap_or(1);
        let mut ctx_func = module.make_context();
        // 函数签名已在第一遍注册：fn(ctx_handle, params...) -> f64
        {
            let mut sig = module.make_signature();
            sig.params.push(AbiParam::new(types::F64)); // ctx_handle
            for _ in 0..(expected_params - 1) {
                sig.params.push(AbiParam::new(types::F64));
            }
            sig.returns.push(AbiParam::new(types::F64));
            ctx_func.func.signature = sig;
        }

        let mut builder = FunctionBuilder::new(&mut ctx_func.func, &mut self.builder_context);

        // 入口块绑定参数（ctx_handle + params）
        let entry_block = builder.create_block();
        builder.append_block_params_for_function_params(entry_block);
        builder.switch_to_block(entry_block);
        builder.seal_block(entry_block);
        let ctx_val = builder.block_params(entry_block)[0]; // ctx_handle

        let mut variables = std::collections::HashMap::new();
        let param_offset: u32 = 1000;
        for (i, param) in params.iter().enumerate() {
            let var = Variable::from_u32(param_offset + i as u32);
            variables.insert(param.clone(), var);
            let val = builder.block_params(entry_block)[i + 1];
            builder.declare_var(var, types::F64);
            builder.def_var(var, val);
        }
        let next_var_start = param_offset + params.len() as u32;

        // 创建分发块和状态块
        let dispatch_block = builder.create_block();
        let num_states_block = if num_states > 0 { num_states } else { 1 };
        let state_blocks: Vec<clcodegen::ir::Block> = (0..num_states_block)
            .map(|_| builder.create_block())
            .collect();
        let fallback_block = builder.create_block();

        builder.ins().jump(dispatch_block, &[]);

        // 状态分发
        builder.switch_to_block(dispatch_block);
        let state_val = call_import_direct(module, &self.function_ids,
            &self.function_param_counts, string_data,
            &self.import_bindings, &self.module_symbols,
            &self.native_addon_config, &self.js_engine_fallback,
            &mut builder, "js_async_ctx_get_state", &[ctx_val]);

        let mut prev_block = dispatch_block;
        for i in 0..num_states_block {
            let expected = builder.ins().f64const(i as f64);
            let cmp = builder.ins().fcmp(FloatCC::Equal, state_val, expected);
            let next_block = builder.create_block();
            builder.ins().brif(cmp, state_blocks[i], &[], next_block, &[]);
            if i > 0 {
                builder.seal_block(prev_block);
            }
            builder.switch_to_block(next_block);
            prev_block = next_block;
        }
        builder.seal_block(prev_block);
        builder.ins().jump(fallback_block, &[]);

        // fallback: 返回 undefined
        builder.switch_to_block(fallback_block);
        builder.seal_block(fallback_block);
        let undef = builder.ins().f64const(f64::from_bits(UNDEFINED));
        builder.ins().return_(&[undef]);

        // 编译各状态段落
        let mut next_var_idx = next_var_start;
        for (seg_idx, segment) in segments.iter().enumerate() {
            let is_last = seg_idx == segments.len() - 1;
            let block = state_blocks[seg_idx];

            builder.switch_to_block(block);
            builder.seal_block(block);

            // 非首段：从 ctx 恢复变量
            let mut seg_vars = variables.clone();
            if seg_idx > 0 {
                for (var_name, slot) in &var_slots {
                    let var = Variable::from_u32(next_var_idx);
                    next_var_idx += 1;
                    let slot_const = builder.ins().f64const(*slot as f64);
                    let val = call_import_direct(module, &self.function_ids,
                        &self.function_param_counts, string_data,
                        &self.import_bindings, &self.module_symbols,
                        &self.native_addon_config, &self.js_engine_fallback,
                        &mut builder, "js_async_ctx_get_local", &[ctx_val, slot_const]);
                    builder.declare_var(var, types::F64);
                    builder.def_var(var, val);
                    seg_vars.insert(var_name.clone(), var);
                }
                // 恢复 yield 结果
                let result_var = Variable::from_u32(next_var_idx);
                next_var_idx += 1;
                let result_val = call_import_direct(module, &self.function_ids,
                    &self.function_param_counts, string_data,
                    &self.import_bindings, &self.module_symbols,
                    &self.native_addon_config, &self.js_engine_fallback,
                    &mut builder, "js_async_ctx_get_result", &[ctx_val]);
                builder.declare_var(result_var, types::F64);
                builder.def_var(result_var, result_val);
                seg_vars.insert("__yield_result".to_string(), result_var);
            }

            let (has_return, seg_last_expr) = {
                let mut seg_ctx = Ctx {
                    variables: &mut seg_vars,
                    next_var_idx,
                    param_names: params,
                    module,
                    function_ids: &self.function_ids,
                    function_param_counts: &self.function_param_counts,
                    string_data,
                    import_bindings: &self.import_bindings,
                    module_symbols: &self.module_symbols,
                    native_addon_config: &self.native_addon_config,
                    js_engine_fallback: &self.js_engine_fallback,
                    last_expr_value: None,
                    current_try_check: None,
                    class_methods: &self.class_methods,
                    entry_block: None,
                    declared_param_count: 0,
                    rest_functions: &self.rest_functions,
                    const_values: &self.const_values,
                };


                let mut has_return = false;
                for stmt in segment {
                    if compile_stmt(stmt, &mut seg_ctx, &mut builder) {
                        has_return = true;
                        break;
                    }
                }
                next_var_idx = seg_ctx.next_var_idx;
                let last_expr = seg_ctx.last_expr_value;
                (has_return, last_expr)
            };

            if !has_return {
                if is_last {
                    // 最后一段：返回 undefined（generator 结束）
                    // 释放所有局部变量（GC）
                    for (var_name, &var) in &seg_vars {
                        if params.iter().any(|p| p == var_name) {
                            continue;
                        }
                        let val = builder.use_var(var);
                        let mut sig_release = module.make_signature();
                        sig_release.params.push(AbiParam::new(types::F64));
                        sig_release.returns.push(AbiParam::new(types::F64));
                        if let Ok(rel_id) = module.declare_function("js_release", Linkage::Import, &sig_release) {
                            let rel_ref = module.declare_func_in_func(rel_id, &mut builder.func);
                            builder.ins().call(rel_ref, &[val]);
                        }
                    }
                    let undef_const = builder.ins().f64const(f64::from_bits(UNDEFINED));
                    builder.ins().return_(&[undef_const]);
                } else {
                    // 非最后段：保存变量，设置下一状态，返回 yield 值
                    let last_expr_val = seg_last_expr;

                    for (k, v) in &seg_vars {
                        if !variables.contains_key(k) {
                            variables.insert(k.clone(), *v);
                        }
                    }

                    // 保存 yield 结果到 ctx.result
                    if let Some(result_val) = last_expr_val {
                        call_import_direct(module, &self.function_ids,
                            &self.function_param_counts, string_data,
                            &self.import_bindings, &self.module_symbols,
                            &self.native_addon_config, &self.js_engine_fallback,
                            &mut builder, "js_async_ctx_set_result", &[ctx_val, result_val]);
                    }

                    // 保存跨 yield 变量
                    for (var_name, slot) in &var_slots {
                        if let Some(&var) = seg_vars.get(var_name) {
                            let val = builder.use_var(var);
                            let slot_const = builder.ins().f64const(*slot as f64);
                            call_import_direct(module, &self.function_ids,
                                &self.function_param_counts, string_data,
                                &self.import_bindings, &self.module_symbols,
                                &self.native_addon_config, &self.js_engine_fallback,
                                &mut builder, "js_async_ctx_set_local", &[ctx_val, slot_const, val]);
                        }
                    }

                    // 设置下一状态
                    let next_state = builder.ins().f64const((seg_idx + 1) as f64);
                    call_import_direct(module, &self.function_ids,
                        &self.function_param_counts, string_data,
                        &self.import_bindings, &self.module_symbols,
                        &self.native_addon_config, &self.js_engine_fallback,
                        &mut builder, "js_async_ctx_set_state", &[ctx_val, next_state]);

                    // 返回 yield 值（从 ctx.result 或直接返回）
                    if let Some(result_val) = seg_last_expr {
                        builder.ins().return_(&[result_val]);
                    } else {
                        let undef_const = builder.ins().f64const(f64::from_bits(UNDEFINED));
                        builder.ins().return_(&[undef_const]);
                    }
                }
            }
        }

        // seal dispatch_block
        builder.seal_block(dispatch_block);

        debug!("Generator '{}' compiled: {} blocks", name, builder.func.dfg.num_blocks());
        builder.finalize();

        if let Err(e) = module.define_function(func_id, &mut ctx_func) {
            return Err(anyhow::anyhow!("Verifier errors for generator '{}': {}", name, e));
        }
        module.clear_context(&mut ctx_func);

        Ok(())
    }

    fn compile_function(
        &mut self,
        module: &mut ObjectModule,
        name: &str,
        params: &[String],
        body: &[HirExpr],
        string_data: &std::collections::HashMap<String, (cranelift_module::DataId, Vec<u8>)>,
    ) -> Result<()> {
        self.set_current_func(name);

        let func_id = *self.function_ids.get(name)
            .ok_or_else(|| anyhow::anyhow!("Function {} not found", name))?;

        let mut ctx_func = module.make_context();
        // 使用 function_param_counts 中声明的参数数量，而非 params.len()（rest 参数函数可能声明更多参数）
        let declared_count = self.function_param_counts.get(name).copied().unwrap_or(params.len());
        for _ in 0..declared_count {
            ctx_func.func.signature.params.push(AbiParam::new(types::F64));
        }
        ctx_func.func.signature.returns.push(AbiParam::new(types::F64));

        let mut builder = FunctionBuilder::new(&mut ctx_func.func, &mut self.builder_context);

        let entry_block = builder.create_block();
        builder.append_block_params_for_function_params(entry_block);
        builder.switch_to_block(entry_block);
        builder.seal_block(entry_block);

        let mut variables = std::collections::HashMap::new();
        // 只绑定 params 中声明的命名参数到变量，rest 函数的额外参数不绑定
        for (i, param) in params.iter().enumerate() {
            let var = Variable::from_u32(i as u32);
            variables.insert(param.clone(), var);
            let val = builder.block_params(entry_block)[i];
            builder.declare_var(var, types::F64);
            builder.def_var(var, val);
        }

        // 使用块隔离 ctx 的作用域，避免 module（在 ctx 中）与后续直接使用 module 的借用冲突
        let has_return = {
            let mut ctx = Ctx {
                variables: &mut variables,
                next_var_idx: params.len() as u32,
                param_names: params,
                module,
                function_ids: &self.function_ids,
                function_param_counts: &self.function_param_counts,
                string_data,
                import_bindings: &self.import_bindings,
                module_symbols: &self.module_symbols,
                native_addon_config: &self.native_addon_config,
                js_engine_fallback: &self.js_engine_fallback,
                last_expr_value: None,
                current_try_check: None,
                class_methods: &self.class_methods,
                entry_block: Some(entry_block),
                declared_param_count: declared_count,
                rest_functions: &self.rest_functions,
                const_values: &self.const_values,
            };

            let mut has_return = false;
            for stmt in body.iter() {
                if compile_stmt(stmt, &mut ctx, &mut builder) {
                    has_return = true;
                    break;
                }
            }
            has_return
        };

        // 入口函数（main）执行后启动事件循环，驱动 async 恢复
        if !has_return && (name == "main" || name == "default") {
            call_import_direct(module, &self.function_ids,
                &self.function_param_counts, string_data,
                &self.import_bindings, &self.module_symbols,
                &self.native_addon_config, &self.js_engine_fallback,
                &mut builder, "js_run_event_loop", &[]);
        }

        if !has_return {
            let undef = builder.ins().f64const(f64::from_bits(UNDEFINED));
            // 释放所有局部变量（GC）
            let var_list: Vec<(String, Variable)> = variables.iter()
                .filter(|(name, _)| !params.contains(name))
                .map(|(name, &var)| (name.clone(), var))
                .collect();
            let mut sig_release = module.make_signature();
            sig_release.params.push(AbiParam::new(types::F64));
            sig_release.returns.push(AbiParam::new(types::F64));
            if let Ok(rel_id) = module.declare_function("js_release", Linkage::Import, &sig_release) {
                let rel_ref = module.declare_func_in_func(rel_id, &mut builder.func);
                for (_name, var) in &var_list {
                    let val = builder.use_var(*var);
                    builder.ins().call(rel_ref, &[val]);
                }
            }
            builder.ins().return_(&[undef]);
        }

        debug!("Function '{}' compiled: {} blocks", name, builder.func.dfg.num_blocks());
        trace!("IR for '{}':\n{}", name, builder.func.display());
        builder.finalize();

        if let Err(e) = module.define_function(func_id, &mut ctx_func) {
            eprintln!("=== CRANELIFT VERIFIER ERROR ===");
            eprintln!("{:#}", e);
            eprintln!("================================");
            return Err(anyhow::anyhow!("Verifier errors: {:#}", e));
        }
        module.clear_context(&mut ctx_func);

        Ok(())
    }
}

fn compile_stmt(stmt: &HirExpr, ctx: &mut Ctx, builder: &mut FunctionBuilder) -> bool {
    match stmt {
        HirExpr::Return(val) => {
            if let Some(v) = val {
                let result = compile_expr(v, ctx, builder);
                // 释放局部变量（保留返回值的变量，因为所有权转移给调用者）
                let skip = match v.as_ref() {
                    HirExpr::Identifier(name) => Some(name.as_str()),
                    _ => None,
                };
                emit_release_locals(ctx, builder, skip);
                builder.ins().return_(&[result]);
            } else {
                // 释放所有局部变量
                emit_release_locals(ctx, builder, None);
                let undef = builder.ins().f64const(f64::from_bits(UNDEFINED));
                builder.ins().return_(&[undef]);
            }
            true
        }
        HirExpr::Var { name, init, is_mut: _ } => {
            let val = if let Some(i) = init {
                // rest 参数数组构造：直接从 entry_block 参数构建
                let is_rest_init = matches!(i.as_ref(),
                    HirExpr::Call { callee, .. } if matches!(
                        callee.as_ref(),
                        HirExpr::Identifier(n) if n == "js_array_from_args"
                    )
                );
                if is_rest_init && ctx.entry_block.is_some() {
                    let start_idx = if let HirExpr::Call { args, .. } = i.as_ref() {
                        if let Some(HirExpr::Number(n)) = args.first() {
                            *n as usize
                        } else { 0 }
                    } else { 0 };
                    // rest 函数的数组已由调用方打包为单个数组参数传入，直接引用 block param
                    let block = ctx.entry_block.unwrap();
                    builder.block_params(block)[start_idx]
                } else {
                    let v = compile_expr(i, ctx, builder);
                    if matches!(i.as_ref(), HirExpr::Identifier(id) if !id.starts_with("__")) {
                        call_import(ctx, builder, "js_retain", &[v]);
                    }
                    v
                }
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            };

            // 诊断：检查变量是否已存在（可能导致 "declared multiple times"）
            if ctx.variables.contains_key(name) {
                tsn_diag_codegen!("Variable '{}' already declared (redeclaration in same scope?)", name);
            }

            let var_idx = ctx.next_var_idx;
            ctx.next_var_idx += 1;
            let var = Variable::from_u32(var_idx);
            ctx.variables.insert(name.clone(), var);
            builder.declare_var(var, types::F64);
            builder.def_var(var, val);
            false
        }
        HirExpr::If { cond, then_body, else_body } => {
            // 死代码消除：常量条件
            match cond.as_ref() {
                HirExpr::Boolean(true) => {
                    // if (true) { ... } -> 直接执行 then_body
                    let mut has_return = false;
                    for s in then_body {
                        has_return = compile_stmt(s, ctx, builder);
                    }
                    return has_return;
                }
                HirExpr::Boolean(false) => {
                    // if (false) { ... } -> 执行 else_body
                    if let Some(else_stmts) = else_body {
                        let mut has_return = false;
                        for s in else_stmts {
                            has_return = compile_stmt(s, ctx, builder);
                        }
                        return has_return;
                    }
                    return false;
                }
                _ => {}
            }

            let cond_val = compile_expr(cond, ctx, builder);
            let cond_bool = is_truthy(cond_val, builder);

            let then_block = builder.create_block();
            let else_block = builder.create_block();
            let merge_block = builder.create_block();

            builder.ins().brif(cond_bool, then_block, &[], else_block, &[]);

            builder.switch_to_block(then_block);
            builder.seal_block(then_block);
            let mut then_returns = false;
            for s in then_body {
                if compile_stmt(s, ctx, builder) {
                    then_returns = true;
                }
            }
            if !then_returns {
                builder.ins().jump(merge_block, &[]);
            }

            builder.switch_to_block(else_block);
            builder.seal_block(else_block);
            let mut else_returns = false;
            if let Some(else_stmts) = else_body {
                for s in else_stmts {
                    if compile_stmt(s, ctx, builder) {
                        else_returns = true;
                    }
                }
            }
            if !else_returns {
                builder.ins().jump(merge_block, &[]);
            }

            if !then_returns || !else_returns {
                builder.switch_to_block(merge_block);
                builder.seal_block(merge_block);
            }

            then_returns && else_returns
        }
        HirExpr::While { cond, body } => {
            let header_block = builder.create_block();
            let body_block = builder.create_block();
            let exit_block = builder.create_block();

            builder.ins().jump(header_block, &[]);

            builder.switch_to_block(header_block);
            let cond_val = compile_expr(cond, ctx, builder);
            let cond_bool = is_truthy(cond_val, builder);
            builder.ins().brif(cond_bool, body_block, &[], exit_block, &[]);

            builder.switch_to_block(body_block);
            for s in body {
                compile_stmt(s, ctx, builder);
            }
            builder.ins().jump(header_block, &[]);

            builder.seal_block(header_block);
            builder.seal_block(body_block);

            builder.switch_to_block(exit_block);
            builder.seal_block(exit_block);

            false
        }
        HirExpr::For { init, cond, update, body } => {
            if let Some(i) = init {
                compile_stmt(i, ctx, builder);
            }

            let header_block = builder.create_block();
            let body_block = builder.create_block();
            let update_block = builder.create_block();
            let exit_block = builder.create_block();

            builder.ins().jump(header_block, &[]);

            builder.switch_to_block(header_block);
            if let Some(c) = cond {
                let cond_val = compile_expr(c, ctx, builder);
                let cond_bool = is_truthy(cond_val, builder);
                builder.ins().brif(cond_bool, body_block, &[], exit_block, &[]);
            } else {
                builder.ins().jump(body_block, &[]);
            }

            builder.switch_to_block(body_block);
            for s in body {
                compile_stmt(s, ctx, builder);
            }
            builder.ins().jump(update_block, &[]);

            builder.switch_to_block(update_block);
            if let Some(u) = update {
                compile_stmt(u, ctx, builder);
            }
            builder.ins().jump(header_block, &[]);

            builder.seal_block(header_block);
            builder.seal_block(body_block);
            builder.seal_block(update_block);

            builder.switch_to_block(exit_block);
            builder.seal_block(exit_block);

            false
        }
        HirExpr::Block(stmts) => {
            let mut has_return = false;
            for s in stmts {
                if compile_stmt(s, ctx, builder) {
                    has_return = true;
                }
            }
            has_return
        }
        HirExpr::Assign { target, value } => {
            let val = compile_expr(value, ctx, builder);
            match target.as_ref() {
                HirExpr::Identifier(name) => {
                    if let Some(&var) = ctx.variables.get(name) {
                        // 释放旧值（GC），新值接管引用
                        let old_val = builder.use_var(var);
                        call_import(ctx, builder, "js_release", &[old_val]);
                        builder.def_var(var, val);
                    }
                }
                HirExpr::Index { object, index } => {
                    let obj_val = compile_expr(object, ctx, builder);
                    let idx_val = compile_expr(index, ctx, builder);

                    let result = call_import(ctx, builder, "js_array_set", &[obj_val, idx_val, val]);

                    // 修复：js_array_set 可能返回新数组指针（扩容时）
                    // 需要更新变量：arr = js_array_set(arr, idx, value)
                    if let HirExpr::Identifier(var_name) = object.as_ref() {
                        if let Some(&var) = ctx.variables.get(var_name) {
                            builder.def_var(var, result);
                        }
                    }
                }
                HirExpr::Property { object, name } => {
                    let obj_val = compile_expr(object, ctx, builder);

                    // NOTE: Property keys are stored as string hashes (not real JsString pointers).
                    // The C runtime compares keys by 64-bit value, not by dereferencing.
                    let hash = fnv1a_64(name);
                    let key_val = builder.ins().f64const(f64::from_bits(STRING_TAG | (hash & 0x0000_FFFF_FFFF_FFFF)));
                    let result = call_import(ctx, builder, "js_object_set", &[obj_val, key_val, val]);

                    // 修复：js_object_set 可能返回新对象指针（扩容时）
                    // 需要更新变量：obj = js_object_set(obj, key, value)
                    if let HirExpr::Identifier(var_name) = object.as_ref() {
                        if let Some(&var) = ctx.variables.get(var_name) {
                            builder.def_var(var, result);
                        }
                    }
                }
                _ => {}
            }
            false
        }
                HirExpr::TryCatch { try_body, catch_param, catch_body, finally_body } => {
            tsn_diag_codegen!("Compiling TryCatch: try_body={} stmts, catch_body={:?} stmts, finally={:?}",
                try_body.len(), catch_body.as_ref().map(|b| b.len()), finally_body.as_ref().map(|b| b.len()));

            let mut sig_try_begin = ctx.module.make_signature();
            sig_try_begin.returns.push(AbiParam::new(types::I32));
            let try_begin_id = ctx.module.declare_function("js_try_begin", cranelift_module::Linkage::Import, &sig_try_begin);

            let sig_try_end = ctx.module.make_signature();
            let try_end_id = ctx.module.declare_function("js_try_end", cranelift_module::Linkage::Import, &sig_try_end);

            let mut sig_get_exception = ctx.module.make_signature();
            sig_get_exception.returns.push(AbiParam::new(types::F64));
            let get_exception_id = ctx.module.declare_function("js_get_exception", cranelift_module::Linkage::Import, &sig_get_exception);

            let sig_clear_exception = ctx.module.make_signature();
            let clear_exception_id = ctx.module.declare_function("js_clear_exception", cranelift_module::Linkage::Import, &sig_clear_exception);

            let try_block = builder.create_block();
            let catch_check_block = builder.create_block();
            let catch_block = builder.create_block();
            let finally_block = builder.create_block();
            let merge_block = builder.create_block();

            // js_try_begin() -> i32 (0 = 正常, 1 = 有异常)
            let entered_normally = if let Ok(id) = try_begin_id {
                let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                let call = builder.ins().call(func_ref, &[]);
                builder.inst_results(call)[0]
            } else {
                builder.ins().iconst(types::I32, 0)
            };

            let zero = builder.ins().iconst(types::I32, 0);
            let is_normal = builder.ins().icmp(IntCC::Equal, entered_normally, zero);
            builder.ins().brif(is_normal, try_block, &[], catch_block, &[]);

            // === try 块 ===
            builder.switch_to_block(try_block);

            // 设置异常跳转目标，使 try 块内的 throw 跳转到 catch_check_block
            let prev_try_check = ctx.current_try_check;
            ctx.current_try_check = Some(catch_check_block);

            let mut try_returns = false;
            for s in try_body {
                if compile_stmt(s, ctx, builder) {
                    try_returns = true;
                    break;
                }
            }

            ctx.current_try_check = prev_try_check;

            // seal try 块（所有前驱已知）
            builder.seal_block(try_block);

            // try 块未终止 -> 在末尾检查是否有异常
            if !try_returns {
                let exc_val = if let Ok(id) = get_exception_id {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    let call = builder.ins().call(func_ref, &[]);
                    builder.inst_results(call)[0]
                } else {
                    builder.ins().f64const(f64::from_bits(UNDEFINED))
                };

                let undef_val = builder.ins().f64const(f64::from_bits(UNDEFINED));
                let has_exc = builder.ins().fcmp(FloatCC::NotEqual, exc_val, undef_val);

                let normal_end_block = builder.create_block();
                builder.ins().brif(has_exc, catch_check_block, &[], normal_end_block, &[]);

                // 无异常：跳到 finally
                builder.switch_to_block(normal_end_block);
                builder.seal_block(normal_end_block);
                if let Ok(id) = try_end_id {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    builder.ins().call(func_ref, &[]);
                }
                if let Ok(id) = clear_exception_id {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    builder.ins().call(func_ref, &[]);
                }
                builder.ins().jump(finally_block, &[]);
            }

            // === catch_check_block（throw 跳转目标） ===
            builder.switch_to_block(catch_check_block);
            builder.seal_block(catch_check_block);
            if let Ok(id) = try_end_id {
                let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                builder.ins().call(func_ref, &[]);
            }
            builder.ins().jump(catch_block, &[]);

            // === catch 块 ===
            builder.switch_to_block(catch_block);
            builder.seal_block(catch_block);
            if let Some(body) = catch_body {
                if let Some(param) = catch_param {
                    let exception_val = if let Ok(id) = get_exception_id {
                        let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                        let call = builder.ins().call(func_ref, &[]);
                        builder.inst_results(call)[0]
                    } else {
                        builder.ins().f64const(f64::from_bits(UNDEFINED))
                    };

                    let var_idx = ctx.next_var_idx;
                    ctx.next_var_idx += 1;
                    let var = Variable::from_u32(var_idx);
                    ctx.variables.insert(param.clone(), var);
                    builder.declare_var(var, types::F64);
                    builder.def_var(var, exception_val);
                }
                if let Ok(id) = clear_exception_id {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    builder.ins().call(func_ref, &[]);
                }
                for s in body {
                    compile_stmt(s, ctx, builder);
                }
            }
            if let Ok(id) = try_end_id {
                let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                builder.ins().call(func_ref, &[]);
            }
            builder.ins().jump(finally_block, &[]);

            // === finally 块 ===
            builder.switch_to_block(finally_block);
            builder.seal_block(finally_block);
            if let Some(body) = finally_body {
                for s in body {
                    compile_stmt(s, ctx, builder);
                }
            }
            builder.ins().jump(merge_block, &[]);

            // 只在有路径到达 merge_block 时 seal
            if finally_body.is_some() || !try_returns || catch_body.is_some() {
                builder.switch_to_block(merge_block);
                builder.seal_block(merge_block);
            }

            false
        }
                HirExpr::Throw(val) => {
            tsn_diag_codegen!("Compiling Throw");
            let throw_val = if let Some(v) = val {
                compile_expr(v, ctx, builder)
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            };

            // 调用 js_throw(value) - 设置异常值
            call_import_void(ctx, builder, "js_throw", &[throw_val]);

            if let Some(check_block) = ctx.current_try_check {
                // 在 try 块内：跳转到 catch_check_block，由 try/catch 处理
                builder.ins().jump(check_block, &[]);
            } else {
                // 不在 try 块内：函数返回
                let undef_val = builder.ins().f64const(f64::from_bits(UNDEFINED));
                builder.ins().return_(&[undef_val]);
            }
            true
        }
        HirExpr::ExprStmt(expr) => {
            match expr.as_ref() {
                HirExpr::Assign { .. } | HirExpr::Var { .. } | HirExpr::Return(_) | HirExpr::Break | HirExpr::Continue | HirExpr::Throw(_) => {
                    compile_stmt(expr, ctx, builder)
                }
                _ => {
                    let val = compile_expr(expr, ctx, builder);
                    ctx.last_expr_value = Some(val);
                    false
                }
            }
        }

        // === Class 系统 ===
        HirExpr::ImportBinding { .. } | HirExpr::Export { .. } => false,
        HirExpr::Class { name, parent, methods, properties, .. } => {
            #[cfg(debug_assertions)]
            {
            debug!("Class: {}", name);
            debug!("  Methods: {}", methods.len());
            debug!("  Properties: {}", properties.len());
            }

            // 创建类原型对象：js_object_new()
            let class_obj = if let Some(func_ref) = declare_import(ctx, builder, "js_object_new",
                &[], types::F64) {
                let call = builder.ins().call(func_ref, &[]);
                builder.inst_results(call)[0]
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            };

            // 将 constructor 注册为 "constructor" 属性
            let ctor_name = format!("{}_constructor", name);
            if let Some(&func_id) = ctx.function_ids.get(&ctor_name) {
                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                let func_ptr = builder.ins().func_addr(types::I64, func_ref);
                let func_f64 = builder.ins().bitcast(types::F64, MemFlags::new(), func_ptr);
                let key_hash = fnv1a_64("constructor");
                let key_val = builder.ins().f64const(f64::from_bits(
                    STRING_TAG | (key_hash & 0x0000_FFFF_FFFF_FFFF)));
                if let Some(func_ref) = declare_import(ctx, builder, "js_object_set",
                    &[types::F64, types::F64, types::F64], types::F64) {
                    builder.ins().call(func_ref, &[class_obj, key_val, func_f64]);
                }
            }

            // 将每个方法注册为属性
            for method in methods {
                let method_fn_name = format!("{}_{}", name, method.name);
                if let Some(&func_id) = ctx.function_ids.get(&method_fn_name) {
                    let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                    let func_ptr = builder.ins().func_addr(types::I64, func_ref);
                    let func_f64 = builder.ins().bitcast(types::F64, MemFlags::new(), func_ptr);
                    let key_hash = fnv1a_64(&method.name);
                    let key_val = builder.ins().f64const(f64::from_bits(
                        STRING_TAG | (key_hash & 0x0000_FFFF_FFFF_FFFF)));
                    if let Some(func_ref) = declare_import(ctx, builder, "js_object_set",
                        &[types::F64, types::F64, types::F64], types::F64) {
                        builder.ins().call(func_ref, &[class_obj, key_val, func_f64]);
                    }
                }
            }

            // 设置原型链（如果存在父类）
            if let Some(parent_name) = parent {
                if let Some(&parent_var) = ctx.variables.get(parent_name) {
                    let parent_obj = builder.use_var(parent_var);
                    if let Some(func_ref) = declare_import(ctx, builder, "js_object_set_prototype",
                        &[types::F64, types::F64], types::F64) {
                        builder.ins().call(func_ref, &[class_obj, parent_obj]);
                    }
                }
            }

            // 将类对象存入变量（同名）
            let var_idx = ctx.next_var_idx;
            ctx.next_var_idx += 1;
            let var = Variable::from_u32(var_idx);
            ctx.variables.insert(name.clone(), var);
            builder.declare_var(var, types::F64);
            builder.def_var(var, class_obj);

            false
        }

        _ => {
            compile_expr(stmt, ctx, builder);
            false
        }
    }
}

fn compile_expr(expr: &HirExpr, ctx: &mut Ctx, builder: &mut FunctionBuilder) -> Value {
    match expr {
        HirExpr::Number(n) => builder.ins().f64const(*n),
        HirExpr::BigInt(s) => {
            // BigInt 字面量：将字符串推入 string_pool 后用静态字符串方式传给运行时
            if let Some((data_id, _bytes)) = ctx.string_data.get(s) {
                let gv = ctx.module.declare_data_in_func(*data_id, &mut builder.func);
                let addr = builder.ins().global_value(types::I64, gv);
                call_import_i64_to_f64(ctx, builder, "js_bigint_new_from_ptr", addr)
            } else {
                builder.ins().f64const(0.0)
            }
        },
        HirExpr::Boolean(true) => builder.ins().f64const(f64::from_bits(TRUE)),
        HirExpr::Boolean(false) => builder.ins().f64const(f64::from_bits(FALSE)),
        HirExpr::Null => builder.ins().f64const(f64::from_bits(NULL)),
        HirExpr::Undefined => builder.ins().f64const(f64::from_bits(UNDEFINED)),
        HirExpr::String(s) => {
            if let Some((data_id, _bytes)) = ctx.string_data.get(s) {
                let gv = ctx.module.declare_data_in_func(*data_id, &mut builder.func);
                let addr = builder.ins().global_value(types::I64, gv);
                call_import_i64_to_f64(ctx, builder, "js_string_from_static", addr)
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }


        HirExpr::Identifier(name) => {
            // 特殊内置标识符
            match name.as_str() {
                "__import_meta__" => {
                    return call_import_f64_no_args(ctx, builder, "js_import_meta");
                }
                "__new_target__" => {
                    return call_import_f64_no_args(ctx, builder, "js_new_target");
                }
                "__dynamic_import__" => {
                    // 动态 import() 通过函数调用参数传递，此处返回 undefined 占位
                    // 实际处理在 Call 表达式分支中：调用 js_dynamic_import(specifier)
                    return call_import_f64_no_args(ctx, builder, "js_dynamic_import_no_args");
                }
                _ => {}
            }
            // 跨模块 const export 值内联
            if let Some(val) = ctx.const_values.get(name) {
                return compile_expr(val, ctx, builder);
            }
            if let Some(&var) = ctx.variables.get(name) {
                builder.use_var(var)
            } else if let Some(&func_id) = ctx.function_ids.get(name) {
                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                let func_addr = builder.ins().func_addr(types::I64, func_ref);
                let tag = builder.ins().iconst(types::I64, FUNCTION_TAG as i64);
                let tagged = builder.ins().bor(tag, func_addr);
                builder.ins().bitcast(types::F64, MemFlags::new(), tagged)
            } else if let Some((mod_name, imported_name)) = ctx.import_bindings.get(name) {
                // 跨模块导入的函数：声明为导入并返回函数引用（用于 typeof 等非调用场景）
                // 命名空间导入（import * as X from "./mod"）有 imported == "*"，跳过函数声明
                if imported_name == "*" {
                    builder.ins().f64const(f64::from_bits(UNDEFINED))
                } else if mod_name.starts_with("./") || mod_name.starts_with("../") {
                    let sig = {
                        let mut s = ctx.module.make_signature();
                        s.params.push(AbiParam::new(types::F64));
                        s.returns.push(AbiParam::new(types::F64));
                        s
                    };
                    if let Ok(func_id) = ctx.module.declare_function(imported_name, cranelift_module::Linkage::Preemptible, &sig) {
                        let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                        let func_addr = builder.ins().func_addr(types::I64, func_ref);
                        let tag = builder.ins().iconst(types::I64, FUNCTION_TAG as i64);
                        let tagged = builder.ins().bor(tag, func_addr);
                        builder.ins().bitcast(types::F64, MemFlags::new(), tagged)
                    } else {
                        builder.ins().f64const(f64::from_bits(UNDEFINED))
                    }
                } else {
                    builder.ins().f64const(f64::from_bits(UNDEFINED))
                }
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        HirExpr::Binary { op, left, right } => {
            // 常量折叠：两个操作数都是数字字面量时直接计算
            if let (HirExpr::Number(a), HirExpr::Number(b)) = (left.as_ref(), right.as_ref()) {
                if let Some(result) = fold_const_binary(*op, *a, *b) {
                    return builder.ins().f64const(result);
                }
            }

            let l = compile_expr(left, ctx, builder);
            let r = compile_expr(right, ctx, builder);

            match op {
                BinOp::Add => {
                    // 使用 js_add 运行时函数
                    call_js_add(ctx, builder, l, r)
                }
                BinOp::Sub => {
                    builder.ins().fsub(l, r)
                }
                BinOp::Mul => {
                    builder.ins().fmul(l, r)
                }
                BinOp::Div => {
                    builder.ins().fdiv(l, r)
                }
                BinOp::Mod => {
                    // fmod via external call (Cranelift 没有原生 fmod 指令)
                    call_import(ctx, builder, "js_fmod", &[l, r])
                }

                BinOp::Eq => {
                    // 优化：当两边都是数字字面量时，直接使用 fcmp 比较
                    // 避免运行时函数调用开销
                    let is_both_number = matches!(left.as_ref(), HirExpr::Number(_))
                        && matches!(right.as_ref(), HirExpr::Number(_));

                    if is_both_number {
                        let cmp = builder.ins().fcmp(FloatCC::Equal, l, r);
                        let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                        let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                        builder.ins().select(cmp, true_val, false_val)
                    } else {
                        // 使用运行时 js_strict_equals 处理 NaN-tagged 值比较
                        // 字符串需要比较内容而非 bits
                        call_import(ctx, builder, "js_strict_equals", &[l, r])
                    }
                }
                BinOp::Ne => {
                    // 优化：当两边都是数字字面量时，直接使用 fcmp 比较
                    let is_both_number = matches!(left.as_ref(), HirExpr::Number(_))
                        && matches!(right.as_ref(), HirExpr::Number(_));

                    if is_both_number {
                        let cmp = builder.ins().fcmp(FloatCC::NotEqual, l, r);
                        let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                        let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                        builder.ins().select(cmp, true_val, false_val)
                    } else {
                        // a != b 等价于 !(a == b)
                        let eq_result = call_import(ctx, builder, "js_strict_equals", &[l, r]);
                        // js_strict_equals 返回 TRUE(1) 或 FALSE(0) 的 NaN-tagged 值
                        // 需要提取布尔值并取反
                        let eq_bits = builder.ins().bitcast(types::I64, MemFlags::new(), eq_result);
                        let false_bits = builder.ins().iconst(types::I64, FALSE as i64);
                        let is_false = builder.ins().icmp(IntCC::Equal, eq_bits, false_bits);
                        let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                        let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                        builder.ins().select(is_false, true_val, false_val)
                    }
                }
                BinOp::Lt => {
                    let cmp = builder.ins().fcmp(FloatCC::LessThan, l, r);
                    let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                    let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                    builder.ins().select(cmp, true_val, false_val)
                }
                BinOp::Le => {
                    let cmp = builder.ins().fcmp(FloatCC::LessThanOrEqual, l, r);
                    let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                    let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                    builder.ins().select(cmp, true_val, false_val)
                }
                BinOp::Gt => {
                    let cmp = builder.ins().fcmp(FloatCC::GreaterThan, l, r);
                    let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                    let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                    builder.ins().select(cmp, true_val, false_val)
                }
                BinOp::Ge => {
                    let cmp = builder.ins().fcmp(FloatCC::GreaterThanOrEqual, l, r);
                    let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                    let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                    builder.ins().select(cmp, true_val, false_val)
                }

                BinOp::Instanceof => {
                    call_import(ctx, builder, "js_instanceof", &[l, r])
                }

                BinOp::And => {
                    // 使用 is_truthy 做短路求值，正确处理 NaN-tagged 布尔值
                    let l_bool = is_truthy(l, builder);

                    let short_circuit_block = builder.create_block();
                    let eval_right_block = builder.create_block();
                    let merge_block = builder.create_block();
                    builder.append_block_param(merge_block, types::F64);

                    builder.ins().brif(l_bool, eval_right_block, &[], short_circuit_block, &[]);

                    builder.switch_to_block(short_circuit_block);
                    builder.seal_block(short_circuit_block);
                    builder.ins().jump(merge_block, &[l]);

                    builder.switch_to_block(eval_right_block);
                    builder.seal_block(eval_right_block);
                    builder.ins().jump(merge_block, &[r]);

                    builder.switch_to_block(merge_block);
                    builder.seal_block(merge_block);
                    builder.block_params(merge_block)[0]
                }
                BinOp::Or => {
                    // 使用 is_truthy 做短路求值，正确处理 NaN-tagged 布尔值
                    let l_bool = is_truthy(l, builder);

                    let short_circuit_block = builder.create_block();
                    let eval_right_block = builder.create_block();
                    let merge_block = builder.create_block();
                    builder.append_block_param(merge_block, types::F64);

                    builder.ins().brif(l_bool, short_circuit_block, &[], eval_right_block, &[]);

                    builder.switch_to_block(short_circuit_block);
                    builder.seal_block(short_circuit_block);
                    builder.ins().jump(merge_block, &[l]);

                    builder.switch_to_block(eval_right_block);
                    builder.seal_block(eval_right_block);
                    builder.ins().jump(merge_block, &[r]);

                    builder.switch_to_block(merge_block);
                    builder.seal_block(merge_block);
                    builder.block_params(merge_block)[0]
                }

                BinOp::BitAnd => {
                    // Convert f64 to i64, bitwise AND, convert back
                    let l_int = builder.ins().fcvt_to_sint_sat(types::I64, l);
                    let r_int = builder.ins().fcvt_to_sint_sat(types::I64, r);
                    let result = builder.ins().band(l_int, r_int);
                    builder.ins().fcvt_from_sint(types::F64, result)
                }
                BinOp::BitOr => {
                    let l_int = builder.ins().fcvt_to_sint_sat(types::I64, l);
                    let r_int = builder.ins().fcvt_to_sint_sat(types::I64, r);
                    let result = builder.ins().bor(l_int, r_int);
                    builder.ins().fcvt_from_sint(types::F64, result)
                }
                BinOp::BitXor => {
                    let l_int = builder.ins().fcvt_to_sint_sat(types::I64, l);
                    let r_int = builder.ins().fcvt_to_sint_sat(types::I64, r);
                    let result = builder.ins().bxor(l_int, r_int);
                    builder.ins().fcvt_from_sint(types::F64, result)
                }
                BinOp::Shl => {
                    let l_int = builder.ins().fcvt_to_sint_sat(types::I64, l);
                    let r_int = builder.ins().fcvt_to_sint_sat(types::I64, r);
                    let result = builder.ins().ishl(l_int, r_int);
                    builder.ins().fcvt_from_sint(types::F64, result)
                }
                BinOp::Shr => {
                    let l_int = builder.ins().fcvt_to_sint_sat(types::I64, l);
                    let r_int = builder.ins().fcvt_to_sint_sat(types::I64, r);
                    let result = builder.ins().ushr(l_int, r_int);
                    builder.ins().fcvt_from_sint(types::F64, result)
                }
            }
        }

        HirExpr::Unary { op, operand } => {
            let val = compile_expr(operand, ctx, builder);
            match op {
                UnaryOp::Not => {
                    let truthy = is_truthy(val, builder);
                    let zero_i8 = builder.ins().iconst(types::I8, 0);
                    let is_false = builder.ins().icmp(IntCC::Equal, truthy, zero_i8);
                    let true_val = builder.ins().f64const(f64::from_bits(TRUE));
                    let false_val = builder.ins().f64const(f64::from_bits(FALSE));
                    builder.ins().select(is_false, true_val, false_val)
                }
                UnaryOp::Neg => builder.ins().fneg(val),
                UnaryOp::PreInc => {
                    // val = val + 1 (仅对数值有效)
                    let one = builder.ins().f64const(1.0);
                    builder.ins().fadd(val, one)
                }
                UnaryOp::PreDec => {
                    let one = builder.ins().f64const(1.0);
                    builder.ins().fsub(val, one)
                }
                UnaryOp::PostInc | UnaryOp::PostDec => {
                    // PostInc/PostDec 在语句上下文中才有意义（需要知道 target variable）
                    // 在表达式上下文中，先返回原值
                    val
                }
            }
        }

        HirExpr::Typeof(expr) => {
            let val = compile_expr(expr, ctx, builder);
            call_import(ctx, builder, "js_typeof", &[val])
        }

        HirExpr::Call { callee, args } => {
            // 已知 Runtime 函数直接调用（不走属性查找路径）
            if let HirExpr::Identifier(name) = callee.as_ref() {
                let runtime_fns = [
                    "js_array_spread", "js_array_from_args",
                    "js_array_concat",
                    "js_function_apply", "js_object_spread", "js_object_spread_new", "js_object_assign",
                    "js_in",
                ];
                if runtime_fns.contains(&name.as_str()) {
                    let arg_values: Vec<Value> = args.iter()
                        .map(|arg| compile_expr(arg, ctx, builder))
                        .collect();
                    return call_import(ctx, builder, name, &arg_values);
                }
            }
            // 动态 import() 特殊处理
            if let HirExpr::Identifier(name) = callee.as_ref() {
                if name == "__dynamic_import__" {
                    let arg_values: Vec<Value> = args.iter()
                        .map(|arg| compile_expr(arg, ctx, builder))
                        .collect();
                    if arg_values.len() >= 1 {
                        return call_import(ctx, builder, "js_dynamic_import", &[arg_values[0]]);
                    }
                    return builder.ins().f64const(f64::from_bits(UNDEFINED));
                }
            }
            if let HirExpr::Identifier(name) = callee.as_ref() {
                // 检查是否为导入的模块函数
                if let Some((mod_name, imported_name)) = ctx.import_bindings.get(name) {
                    // 检查是否为 native addon 调用
                    if let Some(addon_config) = ctx.native_addon_config.get(mod_name) {
                        if let Some(_dll_fn) = addon_config.functions.get(imported_name) {
                            // 生成 addon 外部调用：addon_<包名>_<函数名>
                            let extern_name = format!("addon_{}_{}", mod_name, imported_name);
                            let arg_values: Vec<Value> = args.iter()
                                .map(|arg| compile_expr(arg, ctx, builder))
                                .collect();
                            return call_import(ctx, builder, &extern_name, &arg_values);
                        }
                    }

                    // 检查是否为 shim 模块（__shim__/ 前缀）
                    if mod_name.starts_with("__shim__/") {
                        // shim 模块：生成对 shim runtime 函数的直接调用
                        // import { debounce } from "lodash" (lodash 是 shim)
                        // import_bindings: { "debounce" => ("__shim__/lodash", "debounce") }
                        // 调用时: declare_function("ts_native_shim_lodash_debounce", Linkage::Import, ...)
                        let pkg_name = &mod_name["__shim__/".len()..];
                        // 从 project config 的 shims 映射获取 shim 模块名前缀
                        // 这里使用约定格式: {shim_prefix}_{imported_name}
                        let shim_fn_name = format!("{}_{}", pkg_name, imported_name);
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        return call_import(ctx, builder, &shim_fn_name, &arg_values);
                    }

                    if mod_name.starts_with("./") || mod_name.starts_with("../") {
                        // 项目内模块函数（相对路径）：直接使用函数原名调用
                        // 避免通过 Property 调用导致 to_runtime_fn_name 生成 js_ 前缀的乱名
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        let retained: Vec<Value> = arg_values.iter().map(|&a| {
                            call_import(ctx, builder, "js_retain", &[a])
                        }).collect();
                        let result = call_import(ctx, builder, imported_name, &retained);
                        for &a in &arg_values {
                            call_import(ctx, builder, "js_release", &[a]);
                        }
                        return result;
                    } else {
                        // 递归编译为 Property 调用（如 readFileSync → fs.readFileSync）
                        let prop_callee = HirExpr::Property {
                            object: Box::new(HirExpr::Identifier(mod_name.clone())),
                            name: imported_name.clone(),
                        };
                        return compile_expr(&HirExpr::Call {
                            callee: Box::new(prop_callee),
                            args: args.clone(),
                        }, ctx, builder);
                    }
                }
                // 检查是否为跨模块函数调用
                if let Some(module_path) = ctx.module_symbols.get(name) {
                    tsn_diag_codegen!("Cross-module call to '{}' (from module '{}')", name, module_path);
                    let mut sig = ctx.module.make_signature();
                    let expected_params = ctx.function_param_counts.get(name).copied().unwrap_or(args.len());
                    for _ in 0..expected_params {
                        sig.params.push(AbiParam::new(types::F64));
                    }
                    sig.returns.push(AbiParam::new(types::F64));

                    if let Ok(id) = ctx.module.declare_function(name, Linkage::Import, &sig) {
                        let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        
                        // Retain 所有参数值
                        let retained_args: Vec<Value> = arg_values.iter().map(|&arg| {
                            call_import(ctx, builder, "js_retain", &[arg])
                        }).collect();
                        
                        // 检测 async 函数调用
                        let is_async_call = expected_params == retained_args.len() + 1;
                        
                        let padded_args: Vec<Value> = if is_async_call {
                            let ctx_handle = call_import(ctx, builder, "js_async_ctx_new", &[]);
                            let mut v = vec![ctx_handle];
                            v.extend(retained_args);
                            v
                        } else if retained_args.len() < expected_params {
                            let undef_val = builder.ins().f64const(f64::from_bits(UNDEFINED));
                            let mut v = retained_args;
                            while v.len() < expected_params {
                                v.push(undef_val);
                            }
                            v
                        } else {
                            retained_args
                        };
                        let call_inst = builder.ins().call(func_ref, &padded_args);
                        let call_result = builder.inst_results(call_inst)[0];
                        // 函数返回后释放原参数值
                        for arg in &arg_values {
                            call_import(ctx, builder, "js_release", &[*arg]);
                        }
                        return call_result;
                    }
                }
                if let Some(&func_id) = ctx.function_ids.get(name) {
                    tsn_diag_codegen!("function_ids has {} entries, looking up '{}': {}", ctx.function_ids.len(), name, ctx.function_ids.contains_key(name));
                    let expected_params = ctx.function_param_counts.get(name).copied().unwrap_or(args.len());
                    tsn_diag_codegen!("Local call to '{}': expected_params={}, args.len={}", name, expected_params, args.len());
                    let arg_values: Vec<Value> = args.iter()
                        .map(|arg| compile_expr(arg, ctx, builder))
                        .collect();
                    
                    // Retain 所有参数值（被调函数接收 retained 引用）
                    let is_rest_func = ctx.rest_functions.contains(name.as_str());
                    let retained_args: Vec<Value> = if is_rest_func {
                        let named_count = expected_params.saturating_sub(1);
                        let mut result: Vec<Value> = Vec::new();
                        // Retain 命名参数
                        for arg in arg_values.iter().take(named_count) {
                            result.push(call_import(ctx, builder, "js_retain", &[*arg]));
                        }
                        // 将剩余参数打包为 JS 数组
                        let zero = builder.ins().f64const(0.0);
                        let mut arr = call_import(ctx, builder, "js_array_new", &[zero]);
                        if named_count < arg_values.len() {
                            let mut sig_push = ctx.module.make_signature();
                            sig_push.params.push(AbiParam::new(types::F64));
                            sig_push.params.push(AbiParam::new(types::F64));
                            sig_push.returns.push(AbiParam::new(types::F64));
                            if let Ok(push_id) = ctx.module.declare_function("js_array_push", cranelift_module::Linkage::Import, &sig_push) {
                                let push_ref = ctx.module.declare_func_in_func(push_id, &mut builder.func);
                                for arg in arg_values.iter().skip(named_count) {
                                    let retained = call_import(ctx, builder, "js_retain", &[*arg]);
                                    let c = builder.ins().call(push_ref, &[arr, retained]);
                                    arr = builder.inst_results(c)[0];
                                }
                            }
                        }
                        result.push(call_import(ctx, builder, "js_retain", &[arr]));
                        result
                    } else {
                        arg_values.iter().map(|&arg| {
                            call_import(ctx, builder, "js_retain", &[arg])
                        }).collect()
                    };
                    
                    // 检测是否为 async 函数调用（参数数量比预期少1，因为缺少 ctx）
                    let is_async_call = expected_params == retained_args.len() + 1;
                    
                    let padded_args: Vec<Value> = if is_async_call {
                        // async 函数：预置 ctx_handle 作为第一参数
                        let ctx_handle = call_import(ctx, builder, "js_async_ctx_new", &[]);
                        let mut v = vec![ctx_handle];
                        v.extend(retained_args);
                        v
                    } else if retained_args.len() < expected_params {
                        let undef_val = builder.ins().f64const(f64::from_bits(UNDEFINED));
                        let mut v = retained_args;
                        while v.len() < expected_params {
                            v.push(undef_val);
                        }
                        v
                    } else {
                        retained_args
                    };

                    let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                    let call_inst = builder.ins().call(func_ref, &padded_args);
                    let call_result = builder.inst_results(call_inst)[0];
                    // 函数返回后释放原参数值（调用者释放引用）
                    for arg in &arg_values {
                        call_import(ctx, builder, "js_release", &[*arg]);
                    }
                    call_result
                } else {
                    match name.as_str() {
                        "print" | "console.log" => {
                            emit_console_log(ctx, builder, args)
                        }
                        "Math.sin" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_sin", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.cos" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_cos", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.sqrt" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                builder.ins().sqrt(val)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.pow" => {
                            if args.len() >= 2 {
                                let base = compile_expr(&args[0], ctx, builder);
                                let exp = compile_expr(&args[1], ctx, builder);
                                call_import(ctx, builder, "js_math_pow", &[base, exp])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.abs" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                builder.ins().fabs(val)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.floor" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                builder.ins().floor(val)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.ceil" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                builder.ins().ceil(val)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.round" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                builder.ins().nearest(val)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.log" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_log", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.exp" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_exp", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.tan" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_tan", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.atan" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_atan", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.asin" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_asin", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.acos" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_math_acos", &[val])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Math.max" => {
                            if args.len() >= 2 {
                                let a = compile_expr(&args[0], ctx, builder);
                                let b = compile_expr(&args[1], ctx, builder);
                                call_import(ctx, builder, "js_math_max", &[a, b])
                            } else if !args.is_empty() {
                                compile_expr(&args[0], ctx, builder)
                            } else {
                                builder.ins().f64const(f64::NEG_INFINITY)
                            }
                        }
                        "Math.min" => {
                            if args.len() >= 2 {
                                let a = compile_expr(&args[0], ctx, builder);
                                let b = compile_expr(&args[1], ctx, builder);
                                call_import(ctx, builder, "js_math_min", &[a, b])
                            } else if !args.is_empty() {
                                compile_expr(&args[0], ctx, builder)
                            } else {
                                builder.ins().f64const(f64::INFINITY)
                            }
                        }
                        "document.createElement" => {
                            if !args.is_empty() {
                                let tag = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_dom_create_element", &[tag])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "element.appendChild" => {
                            if args.len() >= 2 {
                                let parent = compile_expr(&args[0], ctx, builder);
                                let child = compile_expr(&args[1], ctx, builder);
                                call_import(ctx, builder, "js_dom_append_child", &[parent, child])
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "element.textContent" => {
                            if args.len() >= 2 {
                                let elem = compile_expr(&args[0], ctx, builder);
                                let text = compile_expr(&args[1], ctx, builder);
                                // js_dom_set_text_content(elem, text) - 无返回值
                                call_import_void(ctx, builder, "js_dom_set_text_content", &[elem, text]);
                            }
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                        "browser.setHTML" => {
                            if !args.is_empty() {
                                let html = compile_expr(&args[0], ctx, builder);
                                call_import_void(ctx, builder, "js_browser_set_html", &[html]);
                            }
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                        "browser.render" => {
                            call_import_f64_no_args(ctx, builder, "js_browser_render");
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                        "parseInt" => {
                            if !args.is_empty() {
                                compile_expr(&args[0], ctx, builder)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "parseFloat" => {
                            if !args.is_empty() {
                                compile_expr(&args[0], ctx, builder)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "String" => {
                            if !args.is_empty() {
                                compile_expr(&args[0], ctx, builder)
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        "Number" => {
                            if !args.is_empty() {
                                compile_expr(&args[0], ctx, builder)
                            } else {
                                builder.ins().f64const(0.0)
                            }
                        }
                        "Boolean" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                let zero = builder.ins().f64const(0.0);
                                let cmp = builder.ins().fcmp(FloatCC::NotEqual, val, zero);
                                builder.ins().fcvt_from_sint(types::F64, cmp)
                            } else {
                                builder.ins().f64const(f64::from_bits(FALSE))
                            }
                        }
                        "String.fromCharCode" => {
                            if !args.is_empty() {
                                let val = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_string_from_char_code", &[val])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        // === 定时器（全局函数） ===
                        "setTimeout" => {
                            if args.len() >= 2 {
                                let cb = compile_expr(&args[0], ctx, builder);
                                let ms = compile_expr(&args[1], ctx, builder);
                                call_import(ctx, builder, "js_set_timeout", &[cb, ms])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        "setInterval" => {
                            if args.len() >= 2 {
                                let cb = compile_expr(&args[0], ctx, builder);
                                let ms = compile_expr(&args[1], ctx, builder);
                                call_import(ctx, builder, "js_set_interval", &[cb, ms])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        "clearTimeout" => {
                            if !args.is_empty() {
                                let v = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_clear_timeout", &[v])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        "clearInterval" => {
                            if !args.is_empty() {
                                let v = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_clear_interval", &[v])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        "setImmediate" => {
                            if !args.is_empty() {
                                let v = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_set_immediate", &[v])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        "clearImmediate" => {
                            if !args.is_empty() {
                                let v = compile_expr(&args[0], ctx, builder);
                                call_import(ctx, builder, "js_clear_immediate", &[v])
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }
                        }
                        _ => {
                            tsn_diag_codegen!("Fallback call to '{}' (not in function_ids or module_symbols), converting to runtime import", name);
                            // fallback: convert to runtime import
                            let arg_values: Vec<Value> = args.iter()
                                .map(|arg| compile_expr(arg, ctx, builder))
                                .collect();

                            let mut sig = ctx.module.make_signature();
                            for _ in 0..arg_values.len() {
                                sig.params.push(AbiParam::new(types::F64));
                            }
                            sig.returns.push(AbiParam::new(types::F64));

                            let c_name = to_runtime_fn_name(&name);

                            if let Ok(id) = ctx.module.declare_function(&c_name, Linkage::Import, &sig) {
                                let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                                let call = builder.ins().call(func_ref, &arg_values);
                                builder.inst_results(call)[0]
                            } else {
                                builder.ins().f64const(f64::from_bits(UNDEFINED))
                            }

                        }
                    }
                }
            } else if let HirExpr::Property { object, name } = callee.as_ref() {
                let full_name = match object.as_ref() {
                    HirExpr::Identifier(obj_name) => format!("{}.{}", obj_name, name),
                    HirExpr::Property { object: inner_obj, name: inner_name } => {
                        match inner_obj.as_ref() {
                            HirExpr::Identifier(obj_name) => format!("{}.{}.{}", obj_name, inner_name, name),
                            _ => format!("{}.{}", inner_name, name),
                        }
                    }
                    _ => name.clone(),
                };

                match full_name.as_str() {
                    "console.log" | "console.error" | "console.warn" | "console.debug" => {
                        emit_console_log(ctx, builder, args)
                    }
                    "Math.sin" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_sin", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.cos" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_cos", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.sqrt" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            builder.ins().sqrt(val)
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.abs" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            builder.ins().fabs(val)
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.floor" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            builder.ins().floor(val)
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.ceil" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            builder.ins().ceil(val)
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.pow" => {
                        if args.len() >= 2 {
                            let base = compile_expr(&args[0], ctx, builder);
                            let exp = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_math_pow", &[base, exp])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.round" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            builder.ins().nearest(val)
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.log" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_log", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.exp" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_exp", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.tan" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_tan", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.atan" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_atan", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.asin" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_asin", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.acos" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_math_acos", &[val])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    "Math.max" => {
                        if args.len() >= 2 {
                            let a = compile_expr(&args[0], ctx, builder);
                            let b = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_math_max", &[a, b])
                        } else if !args.is_empty() {
                            compile_expr(&args[0], ctx, builder)
                        } else {
                            builder.ins().f64const(f64::NEG_INFINITY)
                        }
                    }
                    "Math.min" => {
                        if args.len() >= 2 {
                            let a = compile_expr(&args[0], ctx, builder);
                            let b = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_math_min", &[a, b])
                        } else if !args.is_empty() {
                            compile_expr(&args[0], ctx, builder)
                        } else {
                            builder.ins().f64const(f64::INFINITY)
                        }
                    }
                    "Math.random" => {
                        call_import_f64_no_args(ctx, builder, "js_math_random")
                    }
                    "Date.now" => {
                        call_import_f64_no_args(ctx, builder, "js_date_now")
                    }
                    "setTimeout" => {
                        if args.len() >= 2 {
                            let fn_val = compile_expr(&args[0], ctx, builder);
                            let ms_val = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_set_timeout", &[fn_val, ms_val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "clearTimeout" => {
                        if !args.is_empty() {
                            let id_val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_clear_timeout", &[id_val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "JSON.stringify" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_json_stringify", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "JSON.parse" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_json_parse", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Object.keys" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_object_keys", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Object.values" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_object_values", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Object.assign" => {
                        if args.len() >= 2 {
                            let target = compile_expr(&args[0], ctx, builder);
                            let source = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_object_assign", &[target, source])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Object.entries" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_object_entries", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Object.create" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_object_create", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "String.fromCharCode" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_string_from_char_code", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Object.hasOwn" => {
                        if args.len() >= 2 {
                            let obj = compile_expr(&args[0], ctx, builder);
                            let key_val = if let HirExpr::String(key_name) = &args[1] {
                                let hash = fnv1a_64(key_name);
                                builder.ins().f64const(f64::from_bits(STRING_TAG | (hash & 0x0000_FFFF_FFFF_FFFF)))
                            } else {
                                compile_expr(&args[1], ctx, builder)
                            };
                            call_import(ctx, builder, "js_object_has_own", &[obj, key_val])
                        } else {
                            builder.ins().f64const(f64::from_bits(FALSE))
                        }
                    }
                    "Array.isArray" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_array_is_array", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(FALSE))
                        }
                    }
                    "Array.from" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_array_from", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === fs 模块（同步版本） ===
                    "fs.readFileSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_read_file_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.writeFileSync" => {
                        if args.len() >= 2 {
                            let p = compile_expr(&args[0], ctx, builder);
                            let c = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_write_file_sync", &[p, c]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.appendFileSync" => {
                        if args.len() >= 2 {
                            let p = compile_expr(&args[0], ctx, builder);
                            let c = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_append_file_sync", &[p, c]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.existsSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_exists_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.mkdirSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_mkdir_sync", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.unlinkSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_unlink_sync", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.rmdirSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_rmdir_sync", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.readdirSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_readdir_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.statSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_stat_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.copyFileSync" => {
                        if args.len() >= 2 {
                            let s = compile_expr(&args[0], ctx, builder);
                            let d = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_copy_file_sync", &[s, d]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.renameSync" => {
                        if args.len() >= 2 {
                            let o = compile_expr(&args[0], ctx, builder);
                            let n = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_rename_sync", &[o, n]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.realpathSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_realpath_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === fs 模块（异步版本） ===
                    "fs.readFile" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_read_file", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.writeFile" => {
                        if args.len() >= 2 {
                            let p = compile_expr(&args[0], ctx, builder);
                            let c = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_write_file", &[p, c]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.appendFile" => {
                        if args.len() >= 2 {
                            let p = compile_expr(&args[0], ctx, builder);
                            let c = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_append_file", &[p, c]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.exists" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_exists", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.mkdir" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_mkdir", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.unlink" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_unlink", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.rmdir" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_rmdir", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.readdir" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_readdir", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.stat" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_stat", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.copyFile" => {
                        if args.len() >= 2 {
                            let s = compile_expr(&args[0], ctx, builder);
                            let d = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_copy_file", &[s, d]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.rename" => {
                        if args.len() >= 2 {
                            let o = compile_expr(&args[0], ctx, builder);
                            let n = compile_expr(&args[1], ctx, builder);
                            call_import_void(ctx, builder, "js_fs_rename", &[o, n]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "fs.realpath" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_fs_realpath", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === path 模块 ===
                    "path.dirname" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_dirname", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.basename" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_basename", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.extname" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_extname", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.join" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_join", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.resolve" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_resolve", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.isAbsolute" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_is_absolute", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.normalize" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_normalize", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.relative" => {
                        if args.len() >= 2 {
                            let from = compile_expr(&args[0], ctx, builder);
                            let to = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_path_relative", &[from, to])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.format" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_format", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.parse" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_path_parse", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "path.sep" => {
                        call_import_f64_no_args(ctx, builder, "js_path_sep")
                    }
                    "path.delimiter" => {
                        call_import_f64_no_args(ctx, builder, "js_path_delimiter")
                    }
                    // === buffer 模块 ===
                    "Buffer.from" | "buffer.Buffer.from" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_buffer_from", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Buffer.alloc" | "buffer.Buffer.alloc" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_buffer_alloc", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Buffer.concat" | "buffer.Buffer.concat" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_buffer_concat", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Buffer.allocUnsafe" | "buffer.Buffer.allocUnsafe" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_buffer_alloc_unsafe", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "Buffer.byteLength" | "buffer.Buffer.byteLength" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_buffer_byte_length", &[v])
                        } else {
                            builder.ins().f64const(0.0)
                        }
                    }
                    // === crypto 模块 ===
                    "createHash" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_crypto_create_hash", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "randomBytes" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_crypto_random_bytes", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "createCipheriv" => {
                        if args.len() >= 3 {
                            let a = compile_expr(&args[0], ctx, builder);
                            let k = compile_expr(&args[1], ctx, builder);
                            let i = compile_expr(&args[2], ctx, builder);
                            call_import(ctx, builder, "js_crypto_create_cipheriv", &[a, k, i])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === os 模块 ===
                    "os.platform" => {
                        call_import_f64_no_args(ctx, builder, "js_os_platform")
                    }
                    "os.type" => {
                        call_import_f64_no_args(ctx, builder, "js_os_type")
                    }
                    "os.arch" => {
                        call_import_f64_no_args(ctx, builder, "js_os_arch")
                    }
                    "os.hostname" => {
                        call_import_f64_no_args(ctx, builder, "js_os_hostname")
                    }
                    "os.homedir" => {
                        call_import_f64_no_args(ctx, builder, "js_os_homedir")
                    }
                    "os.tmpdir" => {
                        call_import_f64_no_args(ctx, builder, "js_os_tmpdir")
                    }
                    "os.totalmem" => {
                        call_import_f64_no_args(ctx, builder, "js_os_totalmem")
                    }
                    "os.freemem" => {
                        call_import_f64_no_args(ctx, builder, "js_os_freemem")
                    }
                    "os.uptime" => {
                        call_import_f64_no_args(ctx, builder, "js_os_uptime")
                    }
                    "os.eol" => {
                        call_import_f64_no_args(ctx, builder, "js_os_eol")
                    }
                    "os.endianness" => {
                        call_import_f64_no_args(ctx, builder, "js_os_endianness")
                    }
                    "os.release" => {
                        call_import_f64_no_args(ctx, builder, "js_os_release")
                    }
                    "os.version" => {
                        call_import_f64_no_args(ctx, builder, "js_os_version")
                    }
                    "os.machine" => {
                        call_import_f64_no_args(ctx, builder, "js_os_machine")
                    }
                    "os.networkInterfaces" => {
                        call_import_f64_no_args(ctx, builder, "js_os_network_interfaces")
                    }
                    "os.userInfo" => {
                        call_import_f64_no_args(ctx, builder, "js_os_user_info")
                    }
                    "os.constants" => {
                        call_import_f64_no_args(ctx, builder, "js_os_constants")
                    }
                    "os.devNull" => {
                        call_import_f64_no_args(ctx, builder, "js_os_dev_null")
                    }
                    "os.loadavg" => {
                        call_import_f64_no_args(ctx, builder, "js_os_loadavg")
                    }
                    "os.cpus" => {
                        call_import_f64_no_args(ctx, builder, "js_os_cpus")
                    }
                    // === process 模块 ===
                    "process.cwd" => {
                        call_import_f64_no_args(ctx, builder, "js_process_cwd")
                    }
                    "process.chdir" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_process_chdir", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "process.exit" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_process_exit", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "process.pid" => {
                        call_import_f64_no_args(ctx, builder, "js_process_pid")
                    }
                    "process.ppid" => {
                        call_import_f64_no_args(ctx, builder, "js_process_ppid")
                    }
                    "process.platform" => {
                        call_import_f64_no_args(ctx, builder, "js_process_platform")
                    }
                    "process.arch" => {
                        call_import_f64_no_args(ctx, builder, "js_process_arch")
                    }
                    "process.version" => {
                        call_import_f64_no_args(ctx, builder, "js_process_version")
                    }
                    "process.env" => {
                        call_import_f64_no_args(ctx, builder, "js_process_env")
                    }
                    "process.argv" => {
                        call_import_f64_no_args(ctx, builder, "js_process_argv")
                    }
                    "process.execPath" => {
                        call_import_f64_no_args(ctx, builder, "js_process_exec_path")
                    }
                    "process.hrtime" => {
                        call_import_f64_no_args(ctx, builder, "js_process_hrtime")
                    }
                    "process.memoryUsage" => {
                        call_import_f64_no_args(ctx, builder, "js_process_memory_usage")
                    }
                    "process.uptime" => {
                        call_import_f64_no_args(ctx, builder, "js_process_uptime")
                    }
                    "process.title" => {
                        call_import_f64_no_args(ctx, builder, "js_process_title")
                    }
                    "process.kill" => {
                        if args.len() >= 2 {
                            let pid = compile_expr(&args[0], ctx, builder);
                            let sig = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_process_kill", &[pid, sig])
                        } else if !args.is_empty() {
                            let pid = compile_expr(&args[0], ctx, builder);
                            let sig = builder.ins().f64const(0.0);
                            call_import(ctx, builder, "js_process_kill", &[pid, sig])
                        } else {
                            builder.ins().f64const(f64::from_bits(FALSE))
                        }
                    }
                    "process.umask" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_process_umask", &[v])
                        } else {
                            let zero = builder.ins().f64const(0.0);
                            call_import(ctx, builder, "js_process_umask", &[zero])
                        }
                    }
                    "process.nextTick" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import_void(ctx, builder, "js_process_next_tick", &[v]);
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === crypto 模块 ===
                    "crypto.randomUUID" => {
                        call_import_f64_no_args(ctx, builder, "js_crypto_random_uuid")
                    }
                    "crypto.randomBytes" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_crypto_random_bytes", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "crypto.getHashes" => {
                        call_import_f64_no_args(ctx, builder, "js_crypto_get_hashes")
                    }
                    "crypto.getCiphers" => {
                        call_import_f64_no_args(ctx, builder, "js_crypto_get_ciphers")
                    }
                    "crypto.createHash" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_crypto_create_hash", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "crypto.hash" => {
                        if args.len() >= 2 {
                            let d = compile_expr(&args[0], ctx, builder);
                            let a = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_crypto_hash", &[d, a])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "crypto.createCipheriv" => {
                        if args.len() >= 3 {
                            let a = compile_expr(&args[0], ctx, builder);
                            let k = compile_expr(&args[1], ctx, builder);
                            let i = compile_expr(&args[2], ctx, builder);
                            call_import(ctx, builder, "js_crypto_create_cipher_iv", &[a, k, i])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "crypto.createDecipheriv" => {
                        if args.len() >= 3 {
                            let a = compile_expr(&args[0], ctx, builder);
                            let k = compile_expr(&args[1], ctx, builder);
                            let i = compile_expr(&args[2], ctx, builder);
                            call_import(ctx, builder, "js_crypto_create_decipher_iv", &[a, k, i])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "crypto.timingSafeEqual" => {
                        if args.len() >= 2 {
                            let a = compile_expr(&args[0], ctx, builder);
                            let b = compile_expr(&args[1], ctx, builder);
                            call_import(ctx, builder, "js_crypto_timing_safe_equal", &[a, b])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "crypto.pbkdf2" => {
                        if args.len() >= 3 {
                            let p = compile_expr(&args[0], ctx, builder);
                            let s = compile_expr(&args[1], ctx, builder);
                            let i = compile_expr(&args[2], ctx, builder);
                            call_import(ctx, builder, "js_crypto_pbkdf2", &[p, s, i])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "url.format" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_url_format", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === zlib 模块 ===
                    "zlib.deflateSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_zlib_deflate_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "zlib.inflateSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_zlib_inflate_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "zlib.gzipSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_zlib_gzip_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "zlib.gunzipSync" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_zlib_gunzip_sync", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === querystring 模块 ===
                    "querystring.parse" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_querystring_parse", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "querystring.stringify" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_querystring_stringify", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === url 模块 ===
                    "url.parse" => {
                        if !args.is_empty() {
                            let v = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_url_parse", &[v])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === assert 模块 ===
                    "assert.ok" => {
                        let arg = if !args.is_empty() {
                            compile_expr(&args[0], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        let msg = if args.len() >= 2 {
                            compile_expr(&args[1], ctx, builder)
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        };
                        call_import(ctx, builder, "js_assert_ok", &[arg, msg])
                    }
                    "assert.strictEqual" => {
                        let actual = if !args.is_empty() {
                            compile_expr(&args[0], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        let expected = if args.len() >= 2 {
                            compile_expr(&args[1], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        call_import(ctx, builder, "js_assert_strict_equal", &[actual, expected])
                    }
                    "assert.equal" => {
                        let actual = if !args.is_empty() {
                            compile_expr(&args[0], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        let expected = if args.len() >= 2 {
                            compile_expr(&args[1], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        call_import(ctx, builder, "js_assert_equal", &[actual, expected])
                    }
                    "assert.notEqual" => {
                        let actual = if !args.is_empty() {
                            compile_expr(&args[0], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        let expected = if args.len() >= 2 {
                            compile_expr(&args[1], ctx, builder)
                        } else {
                            builder.ins().f64const(0.0)
                        };
                        call_import(ctx, builder, "js_assert_not_equal", &[actual, expected])
                    }
                    // === util 模块 ===
                    "util.format" => {
                        let count = args.len();
                        if count == 0 {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        } else {
                            let vals: Vec<Value> = args.iter()
                                .map(|arg| compile_expr(arg, ctx, builder))
                                .collect();
                            let slot_size = (count * 8) as u32;
                            let ss = builder.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, slot_size));
                            for (i, &val) in vals.iter().enumerate() {
                                builder.ins().stack_store(val, ss, (i * 8) as i32);
                            }
                            let addr = builder.ins().stack_addr(types::I64, ss, 0);
                            let mut sig = ctx.module.make_signature();
                            sig.params.push(AbiParam::new(types::I64));
                            sig.params.push(AbiParam::new(types::I32));
                            sig.returns.push(AbiParam::new(types::F64));
                            if let Ok(id) = ctx.module.declare_function("js_util_format", Linkage::Import, &sig) {
                                let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                                let count_val = builder.ins().iconst(types::I32, count as i64);
                                builder.ins().call(func_ref, &[addr, count_val]);
                            }
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    "util.inspect" => {
                        if !args.is_empty() {
                            let val = compile_expr(&args[0], ctx, builder);
                            call_import(ctx, builder, "js_util_inspect", &[val])
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                    // === stream 模块 ===
                    "stream.Readable" => {
                        call_import_f64_no_args(ctx, builder, "js_stream_readable_new")
                    }
                    "stream.Writable" => {
                        call_import_f64_no_args(ctx, builder, "js_stream_writable_new")
                    }
                    "stream.pipeline" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_stream_pipeline", &arg_values)
                    }
                    "stream.finished" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_stream_finished", &arg_values)
                    }
                    "stream.Readable.from" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_stream_readable_from", &arg_values)
                    }
                    // === net 模块 ===
                    "net.createConnection" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_net_create_connection", &arg_values)
                    }
                    "net.connect" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_net_connect", &arg_values)
                    }
                    "net.createServer" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_net_create_server", &arg_values)
                    }
                    // === http 模块 ===
                    "http.get" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_http_get", &arg_values)
                    }
                    "http.request" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_http_request", &arg_values)
                    }
                    "http.createServer" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_http_create_server", &arg_values)
                    }
                    // === child_process 模块 ===
                    "child_process.execSync" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_child_process_exec_sync", &arg_values)
                    }
                    "child_process.spawnSync" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_child_process_spawn_sync", &arg_values)
                    }
                    "child_process.execFileSync" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_child_process_exec_file_sync", &arg_values)
                    }
                    // === dns 模块 ===
                    "dns.lookup" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_dns_lookup", &arg_values)
                    }
                    "dns.resolve" => {
                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();
                        call_import(ctx, builder, "js_dns_resolve", &arg_values)
                    }
                    // === 通用回退：未识别的模块/方法调用 ===
                    _ => {
                        // 检查是否为 native addon 的 module.function 调用
                        if let Some((mod_name, fn_name)) = full_name.split_once('.') {
                            // 检查是否为命名空间导入（import * as X from "./mod"）
                            if let Some((ns_mod, ns_imported)) = ctx.import_bindings.get(mod_name) {
                                if ns_imported == "*" && (ns_mod.starts_with("./") || ns_mod.starts_with("../")) {
                                    // 命名空间导入：将 X.fnName 解析为跨模块函数调用
                                    if let Some(_module_path) = ctx.module_symbols.get(fn_name) {
                                        let mut sig = ctx.module.make_signature();
                                        let arg_values: Vec<Value> = args.iter()
                                            .map(|arg| compile_expr(arg, ctx, builder))
                                            .collect();
                                        for _ in &arg_values {
                                            sig.params.push(AbiParam::new(types::F64));
                                        }
                                        sig.returns.push(AbiParam::new(types::F64));
                                        if let Ok(id) = ctx.module.declare_function(fn_name, Linkage::Import, &sig) {
                                            let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                                            let retained: Vec<Value> = arg_values.iter().map(|&a| {
                                                call_import(ctx, builder, "js_retain", &[a])
                                            }).collect();
                                            let call_inst = builder.ins().call(func_ref, &retained);
                                            let call_result = builder.inst_results(call_inst)[0];
                                            for &a in &arg_values {
                                                call_import(ctx, builder, "js_release", &[a]);
                                            }
                                            return call_result;
                                        }
                                    }
                                }
                            }

                            if let Some(addon) = ctx.native_addon_config.get(mod_name) {
                                if let Some(_dll_fn) = addon.functions.get(fn_name) {
                                    let extern_name = format!("addon_{}_{}", mod_name, fn_name);
                                    let arg_values: Vec<Value> = args.iter()
                                        .map(|arg| compile_expr(arg, ctx, builder))
                                        .collect();
                                    return call_import(ctx, builder, &extern_name, &arg_values);
                                }
                            }

                            // 检查是否为 QuickJS fallback 包的 module.function 调用
                            if ctx.js_engine_fallback.contains(&mod_name.to_string()) {
                                // 生成: js_qjs_call(mod_name, fn_name, args_array)
                                // 使用 HirExpr::String 编译为 NaN-tagged 字符串值
                                let mod_val = compile_expr(&HirExpr::String(mod_name.to_string()), ctx, builder);
                                let fn_val = compile_expr(&HirExpr::String(fn_name.to_string()), ctx, builder);
                                // 将参数打包为数组
                                let arg_values: Vec<Value> = args.iter()
                                    .map(|arg| compile_expr(arg, ctx, builder))
                                    .collect();
                                let len_val = builder.ins().f64const(arg_values.len() as f64);
                                let args_array = call_import(ctx, builder, "js_array_new", &[len_val]);
                                for arg_val in &arg_values {
                                    call_import_void(ctx, builder, "js_array_push", &[args_array, *arg_val]);
                                }
                                return call_import(ctx, builder, "js_qjs_call", &[mod_val, fn_val, args_array]);
                            }
                        }

                        // 判断是否为模块级函数调用（不需要 this）
                        // 已知模块名列表：这些是静态模块，不是对象实例
                        let module_names = [
                            "fs", "path", "os", "process", "crypto", "zlib",
                            "Date", "JSON", "Object", "Array", "console", "Math",
                            "util", "url", "querystring", "events", "stream",
                            "buffer", "http", "https", "net", "dns", "tls",
                            "dgram", "child_process", "cluster", "vm",
                            "worker_threads", "perf_hooks", "readline", "repl",
                            "assert", "module",
                        ];
                        let is_module_call = match object.as_ref() {
                            HirExpr::Identifier(obj_name) => module_names.contains(&obj_name.as_str()),
                            _ => false,
                        };

                        let arg_values: Vec<Value> = args.iter()
                            .map(|arg| compile_expr(arg, ctx, builder))
                            .collect();

                        let all_args = if is_module_call {
                            // 模块函数：不传 object 作为 this
                            arg_values
                        } else {
                            // 对象方法：传 object 作为第一个参数（this）
                            let obj_val = compile_expr(object, ctx, builder);
                            let mut all = vec![obj_val];
                            all.extend_from_slice(&arg_values);
                            all
                        };

                        // Retain 所有参数（包括 this 对象）
                        let retained_all: Vec<Value> = all_args.iter().map(|&arg| {
                            call_import(ctx, builder, "js_retain", &[arg])
                        }).collect();

                        let mut sig = ctx.module.make_signature();
                        for _ in 0..retained_all.len() {
                            sig.params.push(AbiParam::new(types::F64));
                        }
                        sig.returns.push(AbiParam::new(types::F64));
                        // 对于对象方法（非模块调用），使用固定的 runtime 函数名映射
                        // 例如 arr.push -> js_array_push，而非 js_arr_push
                        let c_name = if is_module_call {
                            to_runtime_fn_name(&full_name)
                        } else {
                            // 对象方法名到 runtime 函数名的映射
                            match name.as_str() {
                                "push" => "js_push".to_string(),  // 按类型分发（Array/Stream）
                                "pop" => "js_array_pop".to_string(),
                                "shift" => "js_array_shift".to_string(),
                                "unshift" => "js_array_unshift".to_string(),
                                "splice" => "js_array_splice".to_string(),
                                "join" => "js_array_join".to_string(),
                                "indexOf" => "js_array_index_of".to_string(),
                                "includes" => "js_array_includes".to_string(),
                                "map" => "js_array_map".to_string(),
                                "filter" => "js_array_filter".to_string(),
                                "reduce" => "js_array_reduce".to_string(),
                                "forEach" => "js_array_for_each".to_string(),
                                "reverse" => "js_array_reverse".to_string(),
                                "sort" => "js_array_sort".to_string(),
                                "concat" => "js_array_concat".to_string(),
                                "length" => "js_property_length".to_string(),
                                "toString" => "js_to_string".to_string(),
                                "charAt" => "js_string_char_at".to_string(),
                                "substring" => "js_string_substring".to_string(),
                                "slice" => "js_string_slice".to_string(),
                                "toLowerCase" => "js_string_to_lower_case".to_string(),
                                "toUpperCase" => "js_string_to_upper_case".to_string(),
                                "trim" => "js_string_trim".to_string(),
                                "split" => "js_string_split".to_string(),
                                "replace" => "js_string_replace".to_string(),
                                "startsWith" => "js_string_starts_with".to_string(),
                                "endsWith" => "js_string_ends_with".to_string(),
                                "hasOwnProperty" => "js_object_has_own".to_string(),
                                "keys" => "js_object_keys".to_string(),
                                "values" => "js_object_values".to_string(),
                                // EventEmitter 实例方法
                                "on" => "js_events_on".to_string(),
                                "emit" => "js_events_emit".to_string(),
                                "once" => "js_events_once".to_string(),
                                "removeListener" => "js_events_remove_listener".to_string(),
                                "removeAllListeners" => "js_events_remove_all_listeners".to_string(),
                                "listenerCount" => "js_events_listener_count".to_string(),
                                // crypto Hash 实例方法
                                "update" => "js_crypto_hash_update".to_string(),
                                "digest" => "js_crypto_hash_digest".to_string(),
                                // Stream 实例方法
                                "pipe" => "js_stream_readable_pipe".to_string(),
                                "write" => "js_stream_writable_write".to_string(),
                                "end" => "js_stream_writable_end".to_string(),
                                "read" => "js_stream_readable_read".to_string(),
                                // Net Socket/Server 实例方法（由运行时按类型分发）
                                "destroy" => "js_net_socket_destroy".to_string(),
                                "listen" => "js_net_server_listen".to_string(),
                                // HTTP Response 实例方法
                                "writeHead" => "js_http_res_write_head".to_string(),
                                // Set 实例方法
                                "add" => "js_set_add".to_string(),
                                // Map 实例方法
                                "get" => "js_object_get".to_string(),  // Map.get/set 已在 has/set 中处理
                                "set" => "js_map_set".to_string(),
                                "has" => "js_set_has".to_string(),  // Set.has 和 Map.has 统一处理
                                "delete" => "js_set_delete".to_string(), // Set/Map delete 统一
                                "clear" => "js_set_clear".to_string(),    // Set/Map clear 统一
                                _ => {
                                    // 检查是否为 Class 方法
                                    if let Some(full_fn_name) = ctx.class_methods.get(name.as_str()) {
                                        full_fn_name.clone()
                                    } else {
                                        to_runtime_fn_name(&full_name)
                                    }
                                },
                            }
                        };
                        if let Ok(id) = ctx.module.declare_function(&c_name, Linkage::Import, &sig) {
                            let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                            let call = builder.ins().call(func_ref, &retained_all);
                            let result = builder.inst_results(call)[0];

                            // 函数返回后释放所有参数（包括 this 对象）
                            for &arg in &all_args {
                                call_import(ctx, builder, "js_release", &[arg]);
                            }

                            // 修复 REALLOC_ISSUE.md：检测数组修改方法，自动更新变量引用
                            // 只有返回数组指针的方法才需要更新：push/unshift/splice
                            // pop/shift 返回的是弹出的元素，不应更新变量
                            let array_returning_methods = ["push", "unshift", "splice"];
                            if array_returning_methods.contains(&name.as_str()) {
                                if let HirExpr::Identifier(var_name) = object.as_ref() {
                                    if let Some(&var) = ctx.variables.get(var_name) {
                                        // 自动更新变量：var = var.method()
                                        builder.def_var(var, result);
                                    }
                                }
                            }

                            result
                        } else {
                            builder.ins().f64const(f64::from_bits(UNDEFINED))
                        }
                    }
                }
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        HirExpr::Ternary { cond, then_expr, else_expr } => {
            // 常量条件优化
            match cond.as_ref() {
                HirExpr::Boolean(true) => return compile_expr(then_expr, ctx, builder),
                HirExpr::Boolean(false) => return compile_expr(else_expr, ctx, builder),
                _ => {}
            }

            let cond_val = compile_expr(cond, ctx, builder);
            let cond_bool = is_truthy(cond_val, builder);

            let then_block = builder.create_block();
            let else_block = builder.create_block();
            let merge_block = builder.create_block();
            builder.append_block_param(merge_block, types::F64);

            builder.ins().brif(cond_bool, then_block, &[], else_block, &[]);

            builder.switch_to_block(then_block);
            builder.seal_block(then_block);
            let then_val = compile_expr(then_expr, ctx, builder);
            builder.ins().jump(merge_block, &[then_val]);

            builder.switch_to_block(else_block);
            builder.seal_block(else_block);
            let else_val = compile_expr(else_expr, ctx, builder);
            builder.ins().jump(merge_block, &[else_val]);

            builder.switch_to_block(merge_block);
            builder.seal_block(merge_block);

            builder.block_params(merge_block)[0]
        }

        HirExpr::Array(elements) => {
            let len = elements.len();

            if len == 0 {
                // 空数组：直接调用 js_array_new(0)
                let arr_new_id = ctx.module.declare_function("js_array_new", cranelift_module::Linkage::Import,
                    &{
                        let mut sig = ctx.module.make_signature();
                        sig.params.push(AbiParam::new(types::F64));
                        sig.returns.push(AbiParam::new(types::F64));
                        sig
                    });
                if let Ok(id) = arr_new_id {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    let capacity = builder.ins().f64const(0.0);
                    let call = builder.ins().call(func_ref, &[capacity]);
                    builder.inst_results(call)[0]
                } else {
                    builder.ins().f64const(f64::from_bits(ARRAY_TAG))
                }
            } else {
                // 优化：将所有元素值存入 stack slot，一次调用 js_array_new_from_data
                let vals: Vec<Value> = elements.iter()
                    .map(|elem| compile_expr(elem, ctx, builder))
                    .collect();

                let slot_size = (len * 8) as u32;
                let ss = builder.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, slot_size));

                for (i, &val) in vals.iter().enumerate() {
                    let offset = (i * 8) as i32;
                    builder.ins().stack_store(val, ss, offset);
                }

                let addr = builder.ins().stack_addr(types::I64, ss, 0);

                let mut sig = ctx.module.make_signature();
                sig.params.push(AbiParam::new(types::I64));
                sig.params.push(AbiParam::new(types::I32));
                sig.returns.push(AbiParam::new(types::F64));
                if let Ok(id) = ctx.module.declare_function("js_array_new_from_data", cranelift_module::Linkage::Import, &sig) {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    let count_val = builder.ins().iconst(types::I32, len as i64);
                    let call = builder.ins().call(func_ref, &[addr, count_val]);
                    builder.inst_results(call)[0]
                } else {
                    // fallback: 逐个 push
                    let arr_new_id = ctx.module.declare_function("js_array_new", cranelift_module::Linkage::Import,
                        &{
                            let mut sig = ctx.module.make_signature();
                            sig.params.push(AbiParam::new(types::F64));
                            sig.returns.push(AbiParam::new(types::F64));
                            sig
                        });
                    if let Ok(id) = arr_new_id {
                        let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                        let capacity = builder.ins().f64const(len as f64);
                        let call = builder.ins().call(func_ref, &[capacity]);
                        let mut current_arr = builder.inst_results(call)[0];

                        let push_id = ctx.module.declare_function("js_array_push", cranelift_module::Linkage::Import,
                            &{
                                let mut sig = ctx.module.make_signature();
                                sig.params.push(AbiParam::new(types::F64));
                                sig.params.push(AbiParam::new(types::F64));
                                sig.returns.push(AbiParam::new(types::F64));
                                sig
                            });
                        if let Ok(id) = push_id {
                            let push_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                            for &elem_val in vals.iter() {
                                let call = builder.ins().call(push_ref, &[current_arr, elem_val]);
                                current_arr = builder.inst_results(call)[0];
                            }
                        }
                        current_arr
                    } else {
                        builder.ins().f64const(f64::from_bits(ARRAY_TAG))
                    }
                }
            }
        }
        HirExpr::Index { object, index } => {
            let obj_val = compile_expr(object, ctx, builder);
            let idx_val = compile_expr(index, ctx, builder);

            call_import(ctx, builder, "js_index_get", &[obj_val, idx_val])
        }
                HirExpr::Object(properties) => {
            if properties.is_empty() {
                // 空对象：直接调用 js_object_new()
                let obj_new_id = ctx.module.declare_function("js_object_new", cranelift_module::Linkage::Import,
                    &{
                        let mut sig = ctx.module.make_signature();
                        sig.returns.push(AbiParam::new(types::F64));
                        sig
                    });
                if let Ok(id) = obj_new_id {
                    let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                    let call = builder.ins().call(func_ref, &[]);
                    builder.inst_results(call)[0]
                } else {
                    builder.ins().f64const(f64::from_bits(UNDEFINED))
                }
            } else {
                // 检查是否包含 _spread_* 展开键
                let has_spread = properties.iter().any(|(k, _)| k.starts_with("_spread_"));
                // 分离常规属性和展开源
                let regular: Vec<(String, HirExpr)> = properties.iter()
                    .filter(|(k, _)| !k.starts_with("_spread_"))
                    .map(|(k, v)| (k.clone(), v.clone()))
                    .collect();
                let spread_sources: Vec<HirExpr> = properties.iter()
                    .filter_map(|(k, v)| {
                        if k.starts_with("_spread_") {
                            if let HirExpr::Call { callee, args } = v {
                                if let HirExpr::Identifier(name) = callee.as_ref() {
                                    if name == "js_object_spread" && args.len() == 1 {
                                        return Some(args[0].clone());
                                    }
                                }
                            }
                        }
                        None
                    })
                    .collect();

                if has_spread {
                    // 有展开：创建对象 → assign 展开源 → set 常规属性
                    let mut current_obj = {
                        let obj_new_id = ctx.module.declare_function("js_object_new", cranelift_module::Linkage::Import,
                            &{ let mut s = ctx.module.make_signature(); s.returns.push(AbiParam::new(types::F64)); s });
                        if let Ok(id) = obj_new_id {
                            let fr = ctx.module.declare_func_in_func(id, &mut builder.func);
                            let c = builder.ins().call(fr, &[]);
                            builder.inst_results(c)[0]
                        } else { builder.ins().f64const(f64::from_bits(UNDEFINED)) }
                    };

                    // assign 每个展开源
                    let assign_sig = {
                        let mut s = ctx.module.make_signature();
                        s.params.push(AbiParam::new(types::F64));
                        s.params.push(AbiParam::new(types::F64));
                        s.returns.push(AbiParam::new(types::F64));
                        s
                    };
                    if let Ok(assign_id) = ctx.module.declare_function("js_object_assign", cranelift_module::Linkage::Import, &assign_sig) {
                        let assign_ref = ctx.module.declare_func_in_func(assign_id, &mut builder.func);
                        for source in &spread_sources {
                            let src_val = compile_expr(source, ctx, builder);
                            let call = builder.ins().call(assign_ref, &[current_obj, src_val]);
                            current_obj = builder.inst_results(call)[0];
                        }
                    }

                    // set 常规属性
                    if !regular.is_empty() {
                        let set_sig = {
                            let mut s = ctx.module.make_signature();
                            s.params.push(AbiParam::new(types::F64));
                            s.params.push(AbiParam::new(types::F64));
                            s.params.push(AbiParam::new(types::F64));
                            s.returns.push(AbiParam::new(types::F64));
                            s
                        };
                        if let Ok(set_id) = ctx.module.declare_function("js_object_set", cranelift_module::Linkage::Import, &set_sig) {
                            let set_ref = ctx.module.declare_func_in_func(set_id, &mut builder.func);
                            for (key, ref hir_val) in &regular {
                                let hash = fnv1a_64(key);
                                let key_bits = STRING_TAG | (hash & 0x0000_FFFF_FFFF_FFFF);
                                let kv = builder.ins().f64const(f64::from_bits(key_bits));
                                let val = compile_expr(hir_val, ctx, builder);
                                let call = builder.ins().call(set_ref, &[current_obj, kv, val]);
                                current_obj = builder.inst_results(call)[0];
                            }
                        }
                    }
                    current_obj
                } else {
                    // 无展开：使用优化路径 js_object_new_from_entries
                    let count = properties.len();
                    let key_hashes: Vec<u64> = properties.iter()
                        .map(|(key, _)| {
                            let hash = fnv1a_64(key);
                            STRING_TAG | (hash & 0x0000_FFFF_FFFF_FFFF)
                        })
                        .collect();
                    let vals: Vec<Value> = properties.iter()
                        .map(|(_, value)| compile_expr(value, ctx, builder))
                        .collect();

                    let keys_ss = builder.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, (count * 8) as u32));
                    let vals_ss = builder.create_sized_stack_slot(StackSlotData::new(StackSlotKind::ExplicitSlot, (count * 8) as u32));
                    for (i, &key_bits) in key_hashes.iter().enumerate() {
                        let offset = (i * 8) as i32;
                        let key_const = builder.ins().f64const(f64::from_bits(key_bits));
                        builder.ins().stack_store(key_const, keys_ss, offset);
                    }
                    for (i, &val) in vals.iter().enumerate() {
                        let offset = (i * 8) as i32;
                        builder.ins().stack_store(val, vals_ss, offset);
                    }
                    let keys_addr = builder.ins().stack_addr(types::I64, keys_ss, 0);
                    let vals_addr = builder.ins().stack_addr(types::I64, vals_ss, 0);

                    let mut sig = ctx.module.make_signature();
                    sig.params.push(AbiParam::new(types::I64));
                    sig.params.push(AbiParam::new(types::I64));
                    sig.params.push(AbiParam::new(types::I32));
                    sig.returns.push(AbiParam::new(types::F64));
                    if let Ok(id) = ctx.module.declare_function("js_object_new_from_entries", cranelift_module::Linkage::Import, &sig) {
                        let func_ref = ctx.module.declare_func_in_func(id, &mut builder.func);
                        let count_val = builder.ins().iconst(types::I32, count as i64);
                        let call = builder.ins().call(func_ref, &[keys_addr, vals_addr, count_val]);
                        builder.inst_results(call)[0]
                    } else {
                        let mut current_obj = {
                            let obj_new_id = ctx.module.declare_function("js_object_new", cranelift_module::Linkage::Import,
                                &{ let mut s = ctx.module.make_signature(); s.returns.push(AbiParam::new(types::F64)); s });
                            if let Ok(id) = obj_new_id {
                                let fr = ctx.module.declare_func_in_func(id, &mut builder.func);
                                let c = builder.ins().call(fr, &[]);
                                builder.inst_results(c)[0]
                            } else { builder.ins().f64const(f64::from_bits(UNDEFINED)) }
                        };
                        let set_sig = {
                            let mut s = ctx.module.make_signature();
                            s.params.push(AbiParam::new(types::F64));
                            s.params.push(AbiParam::new(types::F64));
                            s.params.push(AbiParam::new(types::F64));
                            s.returns.push(AbiParam::new(types::F64));
                            s
                        };
                        if let Ok(set_id) = ctx.module.declare_function("js_object_set", cranelift_module::Linkage::Import, &set_sig) {
                            let set_ref = ctx.module.declare_func_in_func(set_id, &mut builder.func);
                            for (i, _) in properties.iter().enumerate() {
                                let key_bits = key_hashes[i];
                                let kv = builder.ins().f64const(f64::from_bits(key_bits));
                                let c = builder.ins().call(set_ref, &[current_obj, kv, vals[i]]);
                                current_obj = builder.inst_results(c)[0];
                            }
                        }
                        current_obj
                    }
                }
            }
        }
        HirExpr::Property { object, name } => {
            // 命名空间导入编译时解析（import * as X from "./mod"; X.MY_CONST）
            if let HirExpr::Identifier(obj_name) = object.as_ref() {
                if let Some((mod_name, imported_name)) = ctx.import_bindings.get(obj_name) {
                    if imported_name == "*" && (mod_name.starts_with("./") || mod_name.starts_with("../")) {
                        // 检查 const_values 中的值
                        if let Some(val) = ctx.const_values.get(name) {
                            return compile_expr(val, ctx, builder);
                        }
                        // 检查 module_symbols 中的函数
                        if ctx.module_symbols.contains_key(name) {
                            let mut sig = ctx.module.make_signature();
                            sig.params.push(AbiParam::new(types::F64));
                            sig.returns.push(AbiParam::new(types::F64));
                            if let Ok(func_id) = ctx.module.declare_function(name, cranelift_module::Linkage::Import, &sig) {
                                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                                let func_addr = builder.ins().func_addr(types::I64, func_ref);
                                let tag = builder.ins().iconst(types::I64, FUNCTION_TAG as i64);
                                let tagged = builder.ins().bor(tag, func_addr);
                                return builder.ins().bitcast(types::F64, MemFlags::new(), tagged);
                            }
                        }
                    }
                }
            }
            let obj_val = compile_expr(object, ctx, builder);

            if name == "length" {
                call_import(ctx, builder, "js_property_length", &[obj_val])
            } else {
                let hash = fnv1a_64(name);
                let key_val = builder.ins().f64const(f64::from_bits(STRING_TAG | (hash & 0x0000_FFFF_FFFF_FFFF)));
                call_import(ctx, builder, "js_object_get", &[obj_val, key_val])
            }
        }

        HirExpr::ExprStmt(expr) => compile_expr(expr, ctx, builder),

        HirExpr::Seq(exprs) => {
            if exprs.is_empty() {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            } else {
                let mut last_val = builder.ins().f64const(f64::from_bits(UNDEFINED));
                for (i, expr) in exprs.iter().enumerate() {
                    let val = compile_expr(expr, ctx, builder);
                    if i == exprs.len() - 1 {
                        last_val = val;
                    }
                }
                last_val
            }
        }

        HirExpr::Var { name, init, is_mut: _ } => {
            let val = if let Some(i) = init {
                let v = compile_expr(i, ctx, builder);
                // 如果从另一个变量初始化，retain 该值（两个变量共享引用）
                // 跳过 __ 前缀的内部变量（async 状态机专用）
                if matches!(i.as_ref(), HirExpr::Identifier(id) if !id.starts_with("__")) {
                    call_import(ctx, builder, "js_retain", &[v]);
                }
                v
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            };
            let var_idx = ctx.next_var_idx;
            ctx.next_var_idx += 1;
            let var = Variable::from_u32(var_idx);
            ctx.variables.insert(name.clone(), var);
            builder.declare_var(var, types::F64);
            builder.def_var(var, val);
            val
        }

        HirExpr::Assign { target, value } => {
            let val = compile_expr(value, ctx, builder);
            match target.as_ref() {
                HirExpr::Identifier(name) => {
                    if let Some(&var) = ctx.variables.get(name) {
                        // 释放旧值（GC），新值接管引用
                        let old_val = builder.use_var(var);
                        call_import(ctx, builder, "js_release", &[old_val]);
                        builder.def_var(var, val);
                    }
                }
                HirExpr::Index { object, index } => {
                    let obj_val = compile_expr(object, ctx, builder);
                    let idx_val = compile_expr(index, ctx, builder);
                    call_import_void(ctx, builder, "js_array_set", &[obj_val, idx_val, val]);
                }
                HirExpr::Property { object, name } => {
                    let obj_val = compile_expr(object, ctx, builder);
                    let hash = fnv1a_64(name);
                    let key_val = builder.ins().f64const(f64::from_bits(STRING_TAG | (hash & 0x0000_FFFF_FFFF_FFFF)));
                    call_import_void(ctx, builder, "js_object_set", &[obj_val, key_val, val]);
                }
                _ => {}
            }
            val
        }

        HirExpr::Block(stmts) => {
            let mut last_val = builder.ins().f64const(f64::from_bits(UNDEFINED));
            for (i, s) in stmts.iter().enumerate() {
                if i == stmts.len() - 1 {
                    last_val = compile_expr(s, ctx, builder);
                } else {
                    compile_stmt(s, ctx, builder);
                }
            }
            last_val
        }

        // Regex support
        HirExpr::Regex { pattern, flags } => {
            // Create regex string with pattern and flags combined
            let regex_str = if flags.is_empty() {
                format!("/{}\0", pattern)
            } else {
                format!("/{}/{}\0", pattern, flags)
            };

            // Store as static string
            if let Some((data_id, _)) = ctx.string_data.get(&regex_str) {
                let gv = ctx.module.declare_data_in_func(*data_id, &mut builder.func);
                let addr = builder.ins().global_value(types::I64, gv);
                call_import_i64_to_f64(ctx, builder, "js_regex_new_from_str", addr)
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        HirExpr::RegexTest { regex, text } => {
            let regex_val = compile_expr(regex, ctx, builder);
            let text_val = compile_expr(text, ctx, builder);
            call_import(ctx, builder, "js_regex_test", &[regex_val, text_val])
        }

        HirExpr::RegexExec { regex, text } => {
            let regex_val = compile_expr(regex, ctx, builder);
            let text_val = compile_expr(text, ctx, builder);
            call_import(ctx, builder, "js_regex_exec", &[regex_val, text_val])
        }

        HirExpr::RegexMatch { regex, text } => {
            let regex_val = compile_expr(regex, ctx, builder);
            let text_val = compile_expr(text, ctx, builder);
            call_import(ctx, builder, "js_string_match", &[regex_val, text_val])
        }

        // === Class 表达式 ===
        HirExpr::New { class_name, args } => {
            #[cfg(debug_assertions)]
            debug!("New: {} with {} args", class_name, args.len());

            // 内置类特殊处理
            match class_name.as_str() {
                "Set" => {
                    return call_import(ctx, builder, "js_set_new", &[]);
                }
                "Map" => {
                    return call_import(ctx, builder, "js_map_new", &[]);
                }
                "EventEmitter" => {
                    return call_import(ctx, builder, "js_events_event_emitter_new", &[]);
                }
                "Proxy" => {
                    if args.len() >= 2 {
                        let target = compile_expr(&args[0], ctx, builder);
                        let handler = compile_expr(&args[1], ctx, builder);
                        return call_import(ctx, builder, "js_proxy_new", &[target, handler]);
                    }
                    return builder.ins().f64const(f64::from_bits(UNDEFINED));
                }
                _ => {}
            }

            // 1. 创建实例对象
            let instance = if let Some(func_ref) = declare_import(ctx, builder, "js_object_new",
                &[], types::F64) {
                let call = builder.ins().call(func_ref, &[]);
                builder.inst_results(call)[0]
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            };

            // 1.5 设置实例原型为类的原型对象
            if let Some(&class_var) = ctx.variables.get(class_name) {
                let class_obj = builder.use_var(class_var);
                if let Some(func_ref) = declare_import(ctx, builder, "js_object_set_prototype",
                    &[types::F64, types::F64], types::F64) {
                    builder.ins().call(func_ref, &[instance, class_obj]);
                }
            }

            // 2. 编译参数
            let mut arg_vals: Vec<Value> = vec![instance]; // 第一个参数是 this（实例）
            for arg in args {
                arg_vals.push(compile_expr(arg, ctx, builder));
            }

            // 3. 调用 constructor: ClassName_constructor(instance, ...args)
            let ctor_name = format!("{}_constructor", class_name);
            if let Some(&func_id) = ctx.function_ids.get(&ctor_name) {
                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                let _call = builder.ins().call(func_ref, &arg_vals);
                // constructor 返回值被忽略，返回 instance
            }

            instance
        }

        HirExpr::This => {
            #[cfg(debug_assertions)]
            debug!("This");
            // 返回当前实例（从局部变量获取）
            if let Some(&var) = ctx.variables.get("this") {
                builder.use_var(var)
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        // === Decorator 表达式 ===
        HirExpr::Decorator { name, args, .. } => {
            #[cfg(debug_assertions)]
            debug!("Decorator: {} with {} args", name, args.len());

            // 编译参数
            let _arg_vals: Vec<Value> = args.iter().map(|arg| {
                compile_expr(arg, ctx, builder)
            }).collect();

            // 调用 js_decorator_apply
            if let Some(func_ref) = declare_import(ctx, builder, "js_decorator_apply",
                &[types::F64, types::F64, types::F64], types::F64) {

                let dec_hash = fnv1a_64(name);
                let dec_val = builder.ins().f64const(f64::from_bits(
                    STRING_TAG | (dec_hash & 0x0000_FFFF_FFFF_FFFF)));
                let target_val = builder.ins().f64const(0.0);
                let context_val = builder.ins().f64const(0.0);

                let call = builder.ins().call(func_ref, &[dec_val, target_val, context_val]);
                builder.inst_results(call)[0]
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        // === Generator 表达式 ===
        HirExpr::Yield(value) => {
            debug!("Yield (not fully supported)");
            let val = compile_expr(value, ctx, builder);
            val  // 直接返回值
        }

        HirExpr::YieldFrom(value) => {
            // yield*: 委托到另一个生成器/迭代器
            // 编译委托表达式并作为当前 yield 的值返回
            // 完整迭代语义需要运行时 .next() 支持
            compile_expr(value, ctx, builder)
        }

        // === Async 表达式 ===
        HirExpr::Await(promise) => {
            let promise_val = compile_expr(promise, ctx, builder);

            // 调用 js_await：如果 promise 已解析则直接返回值
            call_import(ctx, builder, "js_await", &[promise_val])
        }

        // === 函数表达式（匿名函数/闭包/箭头函数） ===
        HirExpr::Function { name, .. } => {
            // 嵌套函数已在第一遍重命名为 $anon_N 并注册
            // 此处返回 FUNCTION_TAG 标记的函数指针
            if let Some(&func_id) = ctx.function_ids.get(name) {
                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                let func_addr = builder.ins().func_addr(types::I64, func_ref);
                let tag = builder.ins().iconst(types::I64, FUNCTION_TAG as i64);
                let tagged = builder.ins().bor(tag, func_addr);
                builder.ins().bitcast(types::F64, MemFlags::new(), tagged)
            } else {
                #[cfg(debug_assertions)]
                debug!("Function expression '{}' not found in function_ids", name);
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        // === Async 函数表达式 ===
        HirExpr::AsyncFunction { name, .. } => {
            if let Some(&func_id) = ctx.function_ids.get(name) {
                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                let func_addr = builder.ins().func_addr(types::I64, func_ref);
                let tag = builder.ins().iconst(types::I64, FUNCTION_TAG as i64);
                let tagged = builder.ins().bor(tag, func_addr);
                builder.ins().bitcast(types::F64, MemFlags::new(), tagged)
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        // === Generator 函数表达式 ===
        HirExpr::Generator { name, .. } => {
            if let Some(&func_id) = ctx.function_ids.get(name) {
                let func_ref = ctx.module.declare_func_in_func(func_id, &mut builder.func);
                let func_addr = builder.ins().func_addr(types::I64, func_ref);
                let tag = builder.ins().iconst(types::I64, FUNCTION_TAG as i64);
                let tagged = builder.ins().bor(tag, func_addr);
                builder.ins().bitcast(types::F64, MemFlags::new(), tagged)
            } else {
                builder.ins().f64const(f64::from_bits(UNDEFINED))
            }
        }

        _ => builder.ins().f64const(f64::from_bits(UNDEFINED)),
    }
}

impl Default for CodeGen {
    fn default() -> Self {
        Self::new()
    }
}

// === 从原生 ObjectProduct 提取原始模块数据 ===

/// 从 Cranelift 原生 ObjectProduct 提取机器码、符号和重定位。
///
/// 策略：先 write() 序列化为字节流，再用 object::read 解析。
/// read 端 API 完整公开（sections/symbols/relocations 迭代器），
/// 避免直接使用 write 端的私有字段。
fn extract_from_object(product: &ObjectProduct) -> RawModuleData {
    let mut raw = RawModuleData {
        functions: std::collections::HashMap::new(),
        data_items: std::collections::HashMap::new(),
        symbols: Vec::new(),
        relocations: Vec::new(),
    };

    // 1. 序列化为 COFF 字节流（write() 只读不消耗）
    let coff_bytes = product.object.write().unwrap_or_default();

    // 2. 用 object::read 解析
    let object_file = match object::read::coff::CoffFile::parse(coff_bytes.as_slice()) {
        Ok(f) => f,
        Err(_) => return raw, // 解析失败则返回空数据
    };

    // 3. 遍历所有 section，提取数据和分类
    let mut section_map: std::collections::HashMap<usize, u8> = std::collections::HashMap::new();
    let mut section_data_map: std::collections::HashMap<usize, &[u8]> = std::collections::HashMap::new();

    for section in object_file.sections() {
        let index = section.index().0;
        let kind = section.kind();
        let data = section.data().unwrap_or(&[]);

        let our_section = match kind {
            object::SectionKind::Text => 0u8,
            object::SectionKind::Data => 1u8,
            object::SectionKind::ReadOnlyData | object::SectionKind::ReadOnlyString => 2u8,
            _ => {
                continue;
            }
        };

        if !data.is_empty() {
            section_data_map.insert(index, data);
            // 将整个 section 数据存入 functions 或 data_items
            if our_section == 0 {
                raw.functions.insert(format!("__text_{}", index), data.to_vec());
            } else {
                raw.data_items.insert(format!("__section_{}", index), data.to_vec());
            }
        }

        section_map.insert(index, our_section);
    }

    // 4. 遍历所有符号
    for symbol in object_file.symbols() {
        let name = symbol.name().unwrap_or("").to_string();
        let is_undefined = symbol.is_undefined();
        let section_index = symbol.section_index();

        if name.is_empty() {
            continue;
        }

        if is_undefined {
            // 外部导入符号
            raw.symbols.push(RawSymbol {
                name,
                section: 0xFF,
                offset: 0,
                is_global: true,
            });
            continue;
        }

        let our_section = section_index
            .and_then(|idx| section_map.get(&idx.0).copied())
            .unwrap_or(0xFF);

        let offset = symbol.address() as u32;
        let size = symbol.size() as u32;

        // 提取符号对应的数据
        if let Some(sec_idx) = section_index {
            if let Ok(section) = object_file.section_by_index(sec_idx) {
                let data = section.data().unwrap_or(&[]);
                let start = offset as usize;
                let end = (offset + size) as usize;
                if end <= data.len() && size > 0 {
                    if our_section == 0 {
                        raw.functions.insert(name.clone(), data[start..end].to_vec());
                    } else {
                        raw.data_items.insert(name.clone(), data[start..end].to_vec());
                    }
                }
            }
        }

        raw.symbols.push(RawSymbol {
            name,
            section: our_section,
            offset,
            is_global: true,
        });
    }

    // 5. 遍历所有 section 的重定位
    for section in object_file.sections() {
        let index = section.index().0;
        let our_section = match section_map.get(&index) {
            Some(&s) => s,
            None => continue,
        };

        for (offset, reloc) in section.relocations() {
            // 获取重定位目标符号名
            let target_name = match reloc.target() {
                object::RelocationTarget::Symbol(sym_idx) => {
                    if let Ok(target_sym) = object_file.symbol_by_index(sym_idx) {
                        let n = target_sym.name().unwrap_or("unknown");
                        n.to_string()
                    } else {
                        "unknown".to_string()
                    }
                }
                object::RelocationTarget::Section(_) => "section".to_string(),
                object::RelocationTarget::Absolute => "absolute".to_string(),
                _ => "unknown".to_string(),
            };

            // 转换重定位类型
            let reloc_type = match (reloc.kind(), reloc.size()) {
                (object::RelocationKind::Relative, 32) => 0, // REL32
                (object::RelocationKind::Absolute, 64) => 1, // ADDR64
                (object::RelocationKind::Absolute, 32) => 1, // ADDR32
                _ => {
                    if reloc.size() <= 32 { 0 } else { 1 }
                }
            };

            raw.relocations.push(RawRelocation {
                section: our_section,
                offset: offset as u32,
                reloc_type,
                target_symbol: target_name,
            });
        }
    }

    raw
}
