Skip to main content

luaur_compiler/methods/
compiler_resolve_assign_conflicts.rs

1use crate::enums::kind::Kind;
2use crate::records::assignment::Assignment;
3use crate::records::compiler::Compiler;
4use crate::records::visitor::Visitor;
5use luaur_ast::records::ast_array::AstArray;
6use luaur_ast::records::ast_expr::AstExpr;
7use luaur_ast::records::ast_stat::AstStat;
8use luaur_ast::visit::ast_expr_visit;
9
10impl Compiler {
11    pub fn resolve_assign_conflicts(
12        &mut self,
13        stat: *mut AstStat,
14        vars: &mut Vec<Assignment>,
15        values: &AstArray<*mut AstExpr>,
16    ) {
17        let mut visitor = self.visitor_visitor();
18
19        for i in 0..vars.len() {
20            let li = &vars[i].lvalue;
21            if li.kind == Kind::Kind_Local {
22                if i < values.size {
23                    unsafe {
24                        ast_expr_visit(*values.data.add(i), &mut visitor);
25                    }
26                }
27                let reg = li.reg as usize;
28                visitor.assigned[reg / 64] |= 1 << (reg % 64);
29            }
30        }
31
32        for i in 0..vars.len() {
33            let li = &vars[i].lvalue;
34            if li.kind != Kind::Kind_Local && i < values.size {
35                unsafe {
36                    ast_expr_visit(*values.data.add(i), &mut visitor);
37                }
38            }
39        }
40
41        for i in vars.len()..values.size {
42            unsafe {
43                ast_expr_visit(*values.data.add(i), &mut visitor);
44            }
45        }
46
47        for var in vars.iter() {
48            let li = &var.lvalue;
49            if (li.kind == Kind::Kind_IndexName
50                || li.kind == Kind::Kind_IndexNumber
51                || li.kind == Kind::Kind_IndexExpr)
52            {
53                let reg = li.reg as usize;
54                if (visitor.assigned[reg / 64] & (1 << (reg % 64))) != 0 {
55                    visitor.conflict[reg / 64] |= 1 << (reg % 64);
56                }
57            }
58            if li.kind == Kind::Kind_IndexExpr {
59                let idx = li.index as usize;
60                if (visitor.assigned[idx / 64] & (1 << (idx % 64))) != 0 {
61                    visitor.conflict[idx / 64] |= 1 << (idx % 64);
62                }
63            }
64        }
65
66        for var in vars.iter_mut() {
67            let li = &var.lvalue;
68            if li.kind == Kind::Kind_Local {
69                let reg = li.reg as usize;
70                if (visitor.conflict[reg / 64] & (1 << (reg % 64))) != 0 {
71                    var.conflict_reg =
72                        self.alloc_reg(stat as *mut luaur_ast::records::ast_node::AstNode, 1);
73                }
74            }
75        }
76    }
77}