Struct rslua_march1917::compiler::Reg
source · Fields§
§reg: u32§temp: bool§mutable: boolImplementations§
source§impl Reg
impl Reg
sourcepub fn is_const(&self) -> bool
pub fn is_const(&self) -> bool
Examples found in repository?
src/compiler.rs (line 512)
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
fn code_test(
&mut self,
input: Option<u32>,
left: ExprResult,
right: &Expr,
) -> Result<ExprResult, CompileError> {
match &left {
ExprResult::Reg(r) => {
let proto = self.proto();
proto.code_test_set(NO_REG, r.reg, 0);
let jump = proto.code_jmp(NO_JUMP, 0);
let right_input = self.get_right_input(input, &left);
let right_result = self.expr(right, right_input)?;
let mut jump = Jump::new(self.alloc_reg(&input), jump);
match &right_result {
ExprResult::Reg(r) if r.is_const() => jump.set_reg_should_move(r.reg),
_ => (),
};
Ok(ExprResult::Jump(jump))
}
_ => unreachable!(),
}
}
fn code_un_op(
&mut self,
op: UnOp,
input: Option<u32>,
expr: ExprResult,
) -> Result<ExprResult, CompileError> {
let src = expr.get_rk(self.context());
// resolve previous result
expr.resolve(self.context());
let alloc_reg = self.alloc_reg(&input);
let reg = alloc_reg.reg;
let result = ExprResult::Reg(alloc_reg);
// gennerate opcode of unop
let proto = self.proto();
proto.code_un_op(op, reg, src);
Ok(result)
}
fn code_not(&mut self, input: Option<u32>, expr: &Expr) -> Result<ExprResult, CompileError> {
if let Some(_) = self.try_const_folding(expr)? {
Ok(ExprResult::False)
} else {
let result = self.expr(expr, input)?;
match &result {
ExprResult::Jump(j) => {
j.inverse_cond(self.context());
Ok(result)
}
ExprResult::Nil | ExprResult::False => Ok(ExprResult::True),
ExprResult::Const(_) | ExprResult::True => Ok(ExprResult::False),
_ => self.code_un_op(UnOp::Not, input, result),
}
}
}
// process expr and save to register
fn expr_and_save(&mut self, expr: &Expr, save_reg: Option<u32>) -> Result<u32, CompileError> {
let reg = save_reg.unwrap_or_else(|| self.context().reserve_regs(1));
// use a register to store temp result
let temp_reg = if Some(reg) != save_reg {
reg
} else {
self.context().reserve_regs(1)
};
let result = self.expr(expr, Some(temp_reg))?;
let proto = self.proto();
match result {
ExprResult::Const(k) => {
let index = proto.add_const(k);
proto.code_const(reg, index)
}
ExprResult::Reg(src) if src.is_const() => proto.code_move(reg, src.reg),
ExprResult::Reg(_) => proto.save(reg),
ExprResult::True => proto.code_bool(reg, true, 0),
ExprResult::False => proto.code_bool(reg, false, 0),
ExprResult::Nil => proto.code_nil(reg, 1),
ExprResult::Jump(j) => {
j.free(self.context());
0
}
};
if temp_reg != reg {
self.context().free_reg(1);
}
Ok(reg)
}sourcepub fn free(&self, context: &mut ProtoContext)
pub fn free(&self, context: &mut ProtoContext)
Examples found in repository?
src/compiler.rs (line 97)
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
pub fn free(&self, context: &mut ProtoContext) {
let proto = &mut context.proto;
let target = self.reg.reg;
if let Some(from) = self.reg_should_move {
proto.code_move(target, from);
}
let false_pos = proto.code_bool(target, false, 1);
let true_pos = proto.code_bool(target, true, 0);
self.fix(true_pos, false_pos, proto);
self.reg.free(context);
}
pub fn free_reg(&self, context: &mut ProtoContext) {
self.reg.free(context);
}
pub fn inverse_cond(&self, context: &mut ProtoContext) {
let proto = &mut context.proto;
let cond = self.pc - 1;
let instruction = proto.get_instruction(cond);
instruction.set_arg_A(1 - instruction.get_arg_A());
}
pub fn concat_true_jumps(&mut self, other: &mut Jump) {
self.true_jumps.append(&mut other.true_jumps);
self.true_jumps.push(other.pc);
}
pub fn concat_false_jumps(&mut self, other: &mut Jump) {
self.false_jumps.append(&mut other.false_jumps);
self.false_jumps.push(other.pc);
}
pub fn set_reg_should_move(&mut self, from: u32) {
self.reg_should_move = Some(from)
}
fn fix(&self, true_pos: usize, false_pos: usize, proto: &mut Proto) {
proto.fix_cond_jump_pos(true_pos, false_pos, self.pc);
for pc in self.true_jumps.iter() {
proto.fix_jump_pos(true_pos, *pc)
}
for pc in self.false_jumps.iter() {
proto.fix_jump_pos(false_pos, *pc)
}
}
}
pub enum ExprResult {
Const(Const),
Reg(Reg),
Jump(Jump),
Nil,
True,
False,
}
impl ExprResult {
pub fn new_const(k: Const) -> Self {
ExprResult::Const(k)
}
pub fn new_const_reg(reg: u32) -> Self {
ExprResult::Reg(Reg {
reg,
temp: false,
mutable: false,
})
}
pub fn new_jump(reg: Reg, pc: usize) -> Self {
ExprResult::Jump(Jump::new(reg, pc))
}
pub fn get_rk(&self, context: &mut ProtoContext) -> u32 {
match self {
ExprResult::Const(k) => {
let index = context.proto.add_const(k.clone());
MASK_K | index
}
ExprResult::Reg(i) => i.reg,
ExprResult::Jump(j) => j.reg.reg,
_ => unreachable!(),
}
}
pub fn resolve(&self, context: &mut ProtoContext) {
match self {
ExprResult::Reg(r) => r.free(context),
ExprResult::Jump(j) => j.free(context),
_ => (),
};
}