refactor: 原子切换 emit 产出符号化 IR

This commit is contained in:
2026-08-05 17:52:42 +08:00
parent ef3cd65eb6
commit f34f791b9a
38 changed files with 720 additions and 866 deletions
+39 -24
View File
@@ -1,6 +1,8 @@
use crate::compiler::{CompileCtx, Compiler};
use crate::ir::inst::Inst;
use crate::ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::{self, OpCode};
use oxide_bytecode::opcode::OpCode;
use oxide_parser::Expression;
impl Compiler {
@@ -17,17 +19,16 @@ impl Compiler {
}
let first_arg_reg = if arg_regs.is_empty() { 0u8 } else { arg_regs[0] };
let result_reg = ctx.alloc_reg();
ctx.emit(opcode::encode(OpCode::SUPER_CALL, result_reg, first_arg_reg, 0));
ctx.emit(arg_regs.len() as u32);
ctx.inst(Inst::super_call(
Operand::Reg(result_reg as u32),
Operand::Reg(first_arg_reg as u32),
arg_regs.len() as u8,
));
if let Some(mut field_buffer) = ctx.field_buffer.take() {
let insert_pc = ctx.bytecode.len();
ctx.bytecode.append(&mut field_buffer.bytecode);
for (label, relative_pc) in field_buffer.labels {
ctx.labels.label_map.insert(label, insert_pc + relative_pc);
}
for mut fixup in field_buffer.fixups {
fixup.pc += insert_pc;
ctx.fixups.push(fixup);
let insert_inst = ctx.insts.len();
ctx.insts.append(&mut field_buffer.insts);
for (label, relative) in field_buffer.labels {
ctx.labels.set_label_pos(label, insert_inst + relative);
}
}
return Ok(result_reg);
@@ -37,14 +38,14 @@ impl Compiler {
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_private_id_reg(member.field.name.as_str(), ctx)?;
let callee_reg = ctx.alloc_reg();
ctx.emit(opcode::encode(OpCode::GET_PRIVATE, callee_reg, obj_reg, key_reg));
ctx.inst(Inst::new(OpCode::GET_PRIVATE, Operand::Reg(callee_reg as u32), Operand::Reg(obj_reg as u32), Operand::Reg(key_reg as u32)));
(callee_reg, obj_reg)
}
Expression::StaticMemberExpression(member) => {
let is_super_member = matches!(&member.object, Expression::Super(_));
let obj_reg = if is_super_member {
let this_reg = ctx.alloc_reg();
ctx.emit(opcode::encode(OpCode::LOAD_VAR, this_reg, 254, 0));
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(this_reg as u32), Operand::This, Operand::None));
this_reg
} else {
self.emit_expression(&member.object, ctx)?
@@ -52,7 +53,7 @@ impl Compiler {
let prop_name = member.property.name.as_str();
let idx = ctx.add_constant(Constant::String(prop_name.to_string()));
let key_reg = ctx.alloc_reg();
ctx.emit_load_const(key_reg, idx);
ctx.inst(Inst::load_const(Operand::Reg(key_reg as u32), idx));
let callee_reg = ctx.alloc_reg();
if is_super_member {
if !ctx.in_instance_method && !ctx.in_static_method && !ctx.in_derived_constructor {
@@ -63,13 +64,10 @@ impl Compiler {
} else {
OpCode::SUPER_GET_PROP
};
ctx.emit(opcode::encode(op, callee_reg, obj_reg, key_reg));
ctx.inst(Inst::new(op, Operand::Reg(callee_reg as u32), Operand::Reg(obj_reg as u32), Operand::Reg(key_reg as u32)));
} else {
ctx.emit(opcode::encode(OpCode::LOAD_VAR, callee_reg, obj_reg, 0));
ctx.emit(opcode::encode(OpCode::IC_GET_PROP, 0, callee_reg, key_reg));
ctx.emit(0);
ctx.emit(0);
ctx.emit(0);
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(callee_reg as u32), Operand::Reg(obj_reg as u32), Operand::None));
ctx.inst(Inst::ic_get(Operand::Reg(callee_reg as u32), Operand::Reg(key_reg as u32)));
}
(callee_reg, obj_reg)
}
@@ -77,7 +75,7 @@ impl Compiler {
let callee_reg = self.emit_expression(&call.callee, ctx)?;
let this_idx = ctx.add_constant(Constant::Undefined);
let this_reg = ctx.alloc_reg();
ctx.emit_load_const(this_reg, this_idx);
ctx.inst(Inst::load_const(Operand::Reg(this_reg as u32), this_idx));
(callee_reg, this_reg)
}
};
@@ -92,10 +90,27 @@ impl Compiler {
Expression::Identifier(ident) if ctx.is_builtin(ident.name.as_str()) => OpCode::CALL_NATIVE,
_ => OpCode::CALL,
};
ctx.emit(opcode::encode(op, callee_reg, this_reg, first_arg_reg));
ctx.emit(arg_regs.len() as u32);
match op {
OpCode::CALL => {
ctx.inst(Inst::call(
Operand::Reg(callee_reg as u32),
Operand::Reg(this_reg as u32),
Operand::Reg(first_arg_reg as u32),
arg_regs.len() as u8,
));
}
OpCode::CALL_NATIVE => {
ctx.inst(Inst::call_native(
Operand::Reg(callee_reg as u32),
Operand::Reg(this_reg as u32),
Operand::Reg(first_arg_reg as u32),
arg_regs.len() as u8,
));
}
_ => unreachable!(),
}
let result_reg = ctx.alloc_reg();
ctx.emit(opcode::encode(OpCode::LOAD_VAR, result_reg, 0, 0));
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg as u32), Operand::None, Operand::None));
Ok(result_reg)
}