From db7cc0a716492b964deac8a04227359db6e1e153 Mon Sep 17 00:00:00 2001 From: Larry Xue Date: Tue, 25 Aug 2020 21:56:30 -0400 Subject: [PATCH] added goto --- c2logic/compiler.py | 25 +++++++++++++++++++------ c2logic/instructions.py | 11 ++++++++++- examples/goto.c | 16 ++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 examples/goto.c diff --git a/c2logic/compiler.py b/c2logic/compiler.py index d1bb232..b7b672a 100644 --- a/c2logic/compiler.py +++ b/c2logic/compiler.py @@ -10,7 +10,7 @@ from pycparser.c_ast import ( from .consts import builtins, draw_funcs, func_binary_ops, func_unary_ops from .instructions import ( - BinaryOp, Draw, DrawFlush, Enable, End, FunctionCall, GetLink, Instruction, JumpCondition, + BinaryOp, Draw, DrawFlush, Enable, End, FunctionCall, GetLink, Goto, Instruction, JumpCondition, Print, PrintFlush, Radar, RawAsm, Read, RelativeJump, Return, Sensor, Set, Shoot, UnaryOp, Write ) @@ -24,7 +24,7 @@ class Function(): start: int = dataclasses.field(default=None, init=False) callees: set = dataclasses.field(init=False, default_factory=set) callers: set = dataclasses.field(init=False, default_factory=set) - labels: list = dataclasses.field(init=False, default_factory=list) + labels: dict = dataclasses.field(init=False, default_factory=dict) def __post_init__(self): self.locals = self.params[:] @@ -65,7 +65,10 @@ class Compiler(c_ast.NodeVisitor): self.remove_uncalled_funcs() init_call = FunctionCall("main") if self.opt_level >= 3: - preamble = [init_call] + if len(self.functions) == 1: + preamble = [] + else: + preamble = [init_call] else: preamble = [Set("__retaddr_main", "2"), init_call, End()] @@ -85,9 +88,14 @@ class Compiler(c_ast.NodeVisitor): instruction.func_start = function.start elif isinstance(instruction, FunctionCall): instruction.func_start = self.functions[instruction.func_name].start + elif isinstance(instruction, Goto): + instruction.offset = function.labels[instruction.label] + instruction.func_start = function.start elif isinstance(instruction, Set) and instruction.dest.startswith("__retaddr"): instruction.src += function.start - out = ["\n".join(map(str, preamble))] + out = [] + if preamble: + out.append("\n".join(map(str, preamble))) out.extend( "\n".join(map(str, function.instructions)) for function in self.functions.values() ) @@ -96,7 +104,6 @@ class Compiler(c_ast.NodeVisitor): def remove_uncalled_funcs(self): to_remove = set() for name, function in list(self.functions.items()): - print(function) if name in to_remove: continue callers = set() @@ -225,7 +232,6 @@ class Compiler(c_ast.NodeVisitor): self.curr_function = self.functions[func_name] else: func_decl = node.decl.type - print(func_decl) params = [param_decl.name for param_decl in func_decl.args.params] self.curr_function = Function(func_name, params) self.visit(node.body) @@ -377,6 +383,13 @@ class Compiler(c_ast.NodeVisitor): self.visit(node.expr) self.push_ret() + def visit_Label(self, node): + self.curr_function.labels[node.name] = self.curr_offset() + 1 + self.visit(node.stmt) + + def visit_Goto(self, node): + self.push(Goto(node.name)) + def visit_FuncCall(self, node): name = node.name.name if node.args is not None: diff --git a/c2logic/instructions.py b/c2logic/instructions.py index d08f601..d54491e 100644 --- a/c2logic/instructions.py +++ b/c2logic/instructions.py @@ -62,7 +62,7 @@ class RelativeJump(Instruction): self.cond = cond def __str__(self): - return f"jump {self.func_start+self.offset} {self.cond}" + return f"jump {self.func_start + self.offset} {self.cond}" class FunctionCall(Instruction): def __init__(self, func_name: str): @@ -79,6 +79,15 @@ class Return(Instruction): def __str__(self): return f"set @counter __retaddr_{self.func_name}" +class Goto(Instruction): + def __init__(self, label: str): + self.label = label + self.offset: int = None + self.func_start: int = None + + def __str__(self): + return f"jump {self.func_start + self.offset} {JumpCondition.always}" + class Print(Instruction): def __init__(self, val: str): self.val = val diff --git a/examples/goto.c b/examples/goto.c new file mode 100644 index 0000000..4830248 --- /dev/null +++ b/examples/goto.c @@ -0,0 +1,16 @@ +#include "c2logic/builtins.h" +extern struct MindustryObject message1; +void main(void) { + goto b; +a: + goto e; +b: + goto d; +c: + goto a; +d: + goto c; +e: + print("end"); + printflush(message1); +} \ No newline at end of file