diff --git a/compiler.py b/compiler.py index 7a5102f..ce606c1 100644 --- a/compiler.py +++ b/compiler.py @@ -3,6 +3,8 @@ from re import T from utils import * from x86_ast import * +from collections import deque +from functools import reduce import os from graph import UndirectedAdjList, transpose, topological_sort from priority_queue import PriorityQueue @@ -92,6 +94,10 @@ def shrink_stmt(self, s: stmt) -> stmt: body = [self.shrink_stmt(s) for s in body] orelse = [self.shrink_stmt(s) for s in orelse] result = If(test_expr, body, orelse) + case While(test, body, []): + test_expr = self.shrink_exp(test) + body = [self.shrink_stmt(s) for s in body] + result = While(test_expr, body, []) case _: raise Exception('error in rco_stmt, unexpected ' + repr(s)) return result @@ -173,6 +179,7 @@ def rco_exp(self, e: expr, need_atomic: bool) -> Tuple[expr, Temporaries]: return tmp, test_tmps else: return return_expr, test_tmps + case _: raise Exception('error in rco_exp, unexpected ' + repr(e)) @@ -209,6 +216,14 @@ def rco_stmt(self, s: stmt) -> List[stmt]: for s in orelse: orelse_stmts.extend(self.rco_stmt(s)) result.append(If(test_expr, body_stmts, orelse_stmts)) + case While(test, body, []): + test_expr, test_tmps = self.rco_exp(test, False) + body_stmts = [] + for name, t_expr in test_tmps: + result.append(Assign([name], t_expr)) + for s in body: + body_stmts.extend(self.rco_stmt(s)) + result.append(While(test_expr, body_stmts, [])) case _: raise Exception('error in rco_stmt, unexpected ' + repr(s)) return result @@ -331,6 +346,17 @@ def explicate_stmt(self, s: stmt, cont: List[stmt], new_orelse = self.explicate_stmt(s, new_orelse, basic_blocks) return self.explicate_pred(test, new_body, new_orelse, basic_blocks) + case While(test, body, []): + # after_while = create_block(cont, basic_blocks) + # goto_after_while = [after_while] + test_label = label_name(generate_name('block')) + new_body = [Goto(test_label)] + for s in reversed(body): + # the new_body was after s we need do the new_body + new_body = self.explicate_stmt(s, new_body, basic_blocks) + test_stmts = self.explicate_pred(test, new_body, cont, basic_blocks) + basic_blocks[test_label] = test_stmts + return [Goto(test_label)] # case Expr(Call(Name('print'), [arg])): # return [s] + cont @@ -338,6 +364,9 @@ def explicate_control(self, p): match p: case Module(body): new_body = [Return(Constant(0))] + # 也许这里是一个 newblock conclude = block(Return(Constant(0))]) + # create_block 是 goto 那个 bloc + # conclude 这里是从那里 goto 到这里 basic_blocks = {} for s in reversed(body): # the new_body was after s we need do the new_body @@ -375,7 +404,7 @@ def select_compare(self, expr, then_label, else_label) -> List[instr]: x = self.select_arg(x) y = self.select_arg(y) return [ - Instr('cmpq', [x, y]), + Instr('cmpq', [y, x]), # Instr('j{}'.format(op_dict[str(op)]), [then_label]), JumpIf(op_dict[str(op)], then_label), Jump(else_label) @@ -598,6 +627,18 @@ def uncover_live(self, ss: List[instr], live_before_block) -> Dict[instr, Set[lo return live_after + def analyze_dataflow(self, G, transfer, bottom, join): + trans_G = transpose(G) + mapping = dict((v, bottom) for v in G.vertices()) + worklist = deque(G.vertices) + while worklist: + node = worklist.pop() + inputs = [mapping[v] for v in trans_G.adjacent(node)] + input = reduce(join, inputs, bottom) + output = transfer(node, input) + if output != mapping[node]: + worklist.extend(G.adjacent(node)) + def build_interference(self, blocks) -> UndirectedAdjList: cfg = UndirectedAdjList() for label, body in blocks.items(): @@ -611,9 +652,13 @@ def build_interference(self, blocks) -> UndirectedAdjList: self.sort_cfg = topological_sort(cfg) live_before_block = {} live_after = {} + for label in reversed(self.sort_cfg): ss = blocks[label] tmp = self.uncover_live(ss, live_before_block) + # live update bind instr with + # flow 分析解决的是 block 的分析问题。 + # 在解决 block 的 live_before_block[label] = tmp[ss[0]] live_after.update(tmp) diff --git a/interp_Cif.py b/interp_Cif.py index b20dde2..44ce414 100644 --- a/interp_Cif.py +++ b/interp_Cif.py @@ -7,7 +7,7 @@ class InterpCif(InterpLif): def interp_stmts(self, ss, env): if len(ss) == 0: return - trace("trace {}".format(ss[0])) + # trace("trace {}".format(ss[0])) match ss[0]: case Return(value): diff --git a/run-tests.py b/run-tests.py index 39bd9d7..da1b210 100644 --- a/run-tests.py +++ b/run-tests.py @@ -4,6 +4,7 @@ import interp_Pvar import interp_Lvar import interp_Lif +import interp_Lwhile import type_check_Pvar import type_check_Lvar import interp_Cif @@ -21,8 +22,9 @@ interp_dict = { "var": interp_Lvar.InterpLvar().interp, "cond": interp_Lif.InterpLif().interp, - "shrink": interp_Lif.InterpLif().interp, - "remove_complex_operands": interp_Lif.InterpLif().interp, + "while": interp_Lwhile.InterpLwhile().interp, + "shrink": interp_Lwhile.InterpLwhile().interp, + "remove_complex_operands": interp_Lwhile.InterpLwhile().interp, "explicate_control": interp_Cif.InterpCif().interp, "select_instructions": interp_x86, "assign_homes": interp_x86, @@ -33,8 +35,8 @@ if len(sys.argv) == 2: one_test_file = sys.argv[1] - run_one_test(one_test_file, 'cond', - compiler, 'cond', + run_one_test(one_test_file, 'while', + compiler, 'while', #type_check_Pvar.TypeCheckPvar().type_check_P, type_check_dict, # interp_Pvar.InterpPvar().interp_P, diff --git a/tests/while/add.golden b/tests/while/add.golden new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/tests/while/add.golden @@ -0,0 +1 @@ +42 diff --git a/tests/while/add.in b/tests/while/add.in new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/while/add.in @@ -0,0 +1 @@ + diff --git a/tests/while/add.py b/tests/while/add.py new file mode 100644 index 0000000..f1752de --- /dev/null +++ b/tests/while/add.py @@ -0,0 +1,7 @@ +x = 2 +y = 2 +g = x == y +if g: + print(42) +else: + print(1) \ No newline at end of file diff --git a/tests/while/add1.golden b/tests/while/add1.golden new file mode 100644 index 0000000..c3f407c --- /dev/null +++ b/tests/while/add1.golden @@ -0,0 +1 @@ +55 diff --git a/tests/while/add1.in b/tests/while/add1.in new file mode 100644 index 0000000..a4a9fc3 --- /dev/null +++ b/tests/while/add1.in @@ -0,0 +1,2 @@ +10 +32 diff --git a/tests/while/add1.py b/tests/while/add1.py new file mode 100644 index 0000000..c6d9c2c --- /dev/null +++ b/tests/while/add1.py @@ -0,0 +1,6 @@ +sum = 0 +i = 10 +while i > 0: + sum = sum + i + i = i - 1 +print(sum) \ No newline at end of file diff --git a/tests/while/input.golden b/tests/while/input.golden new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/tests/while/input.golden @@ -0,0 +1 @@ +42 diff --git a/tests/while/input.in b/tests/while/input.in new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/tests/while/input.in @@ -0,0 +1 @@ +42 diff --git a/tests/while/input.py b/tests/while/input.py new file mode 100644 index 0000000..fc4c096 --- /dev/null +++ b/tests/while/input.py @@ -0,0 +1 @@ +print(input_int()) diff --git a/tests/while/zero.golden b/tests/while/zero.golden new file mode 100644 index 0000000..573541a --- /dev/null +++ b/tests/while/zero.golden @@ -0,0 +1 @@ +0 diff --git a/tests/while/zero.in b/tests/while/zero.in new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/while/zero.in @@ -0,0 +1 @@ + diff --git a/tests/while/zero.py b/tests/while/zero.py new file mode 100644 index 0000000..6d841e9 --- /dev/null +++ b/tests/while/zero.py @@ -0,0 +1,6 @@ +var = True +var = not False +if var: + print(0) +else: + print(0) \ No newline at end of file