Fix nested compound assignment

This commit is contained in:
Andrew Morris
2023-03-01 17:26:33 +11:00
parent 266ff3a611
commit ef265451f2
3 changed files with 26 additions and 25 deletions

View File

@@ -1,23 +0,0 @@
// test_output! [14,14,14]
// This is not correct - it should be [1,5,14]. The problem is that the compound
// *value* is supposed to be the result of the assignment, but when these values
// are compiled %x is used to store the result directly (e.g. op+ %x %_tmp0 %x),
// and so %x is then used as the result of the expression.
//
// This could be easily fixed by simply creating an extra register for the rhs
// of each assignment and doing an extra mov to get it into the variable
// register. However, that makes the assembly extremely verbose. I'm hoping
// there's a nice way to generate relatively neat and tidy assembly directly,
// but it might make sense in the end, and just deal with it in assembly-level
// optimization.
export default function main() {
let x = 0;
return [
x += 1 * 1,
x += 2 * 2,
x += 3 * 3,
];
}

View File

@@ -0,0 +1,11 @@
// test_output! [1,5,14]
export default function main() {
let x = 0;
return [
x += 1 * 1,
x += 2 * 2,
x += 3 * 3,
];
}

View File

@@ -370,7 +370,7 @@ impl<'a> ExpressionCompiler<'a> {
) -> CompiledExpression {
match get_assign_op_str(assign_expr.op) {
None => self.assign_expr_eq(assign_expr, is_top_level, target_register),
Some(op_str) => self.assign_expr_compound(assign_expr, op_str, target_register),
Some(op_str) => self.assign_expr_compound(assign_expr, is_top_level, op_str, target_register),
}
}
@@ -501,6 +501,7 @@ impl<'a> ExpressionCompiler<'a> {
pub fn assign_expr_compound(
&mut self,
assign_expr: &swc_ecma_ast::AssignExpr,
is_top_level: bool,
op_str: &str,
target_register: Option<String>,
) -> CompiledExpression {
@@ -563,7 +564,19 @@ impl<'a> ExpressionCompiler<'a> {
}
}
treg.clone()
if is_top_level {
treg.clone()
} else {
let result_reg = self.fnc.reg_allocator.allocate(&"_tmp".to_string());
self
.fnc
.definition
.push(format!(" mov %{} %{}", treg, result_reg));
nested_registers.push(result_reg.clone());
result_reg
}
}
TargetAccessor::Nested(nta) => {
let res_reg = match target_register {