From cefe0618200a11e6cbb19f0d34867948ff37be5e Mon Sep 17 00:00:00 2001 From: Harry Kalogirou Date: Fri, 8 Dec 2023 16:21:54 +0200 Subject: [PATCH] "naming things" refactor Refactored append instructions into a single append_instruction() method with named arguments for returning or not a variable --- vyper/venom/analysis.py | 4 +- vyper/venom/basicblock.py | 51 +++++-- vyper/venom/ir_node_to_venom.py | 212 +++++++++++++++------------- vyper/venom/passes/normalization.py | 2 +- 4 files changed, 158 insertions(+), 111 deletions(-) diff --git a/vyper/venom/analysis.py b/vyper/venom/analysis.py index 5980e21028..1a82ca85d0 100644 --- a/vyper/venom/analysis.py +++ b/vyper/venom/analysis.py @@ -2,7 +2,7 @@ from vyper.utils import OrderedSet from vyper.venom.basicblock import ( BB_TERMINATORS, - CFG_ALTERING_OPS, + CFG_ALTERING_INSTRUCTIONS, IRBasicBlock, IRInstruction, IRVariable, @@ -55,7 +55,7 @@ def calculate_cfg(ctx: IRFunction) -> None: assert last_inst.opcode in BB_TERMINATORS, f"Last instruction should be a terminator {bb}" for inst in bb.instructions: - if inst.opcode in CFG_ALTERING_OPS: + if inst.opcode in CFG_ALTERING_INSTRUCTIONS: ops = inst.get_label_operands() for op in ops: ctx.get_basic_block(op.value).add_cfg_in(bb) diff --git a/vyper/venom/basicblock.py b/vyper/venom/basicblock.py index 8b7089c1c7..d91aae774e 100644 --- a/vyper/venom/basicblock.py +++ b/vyper/venom/basicblock.py @@ -31,8 +31,25 @@ ] ) -CFG_ALTERING_OPS = frozenset(["jmp", "jnz", "call", "staticcall", "invoke", "deploy"]) +NO_OUTPUT_INSTRUCTIONS = frozenset( + [ + "mstore", + "sstore", + "dstore", + "calldatacopy", + "codecopy", + "return", + "ret", + "revert", + "assert", + "selfdestruct", + "stop", + "invalid", + "log", + ] +) +CFG_ALTERING_INSTRUCTIONS = frozenset(["jmp", "jnz", "call", "staticcall", "invoke", "deploy"]) if TYPE_CHECKING: from vyper.venom.function import IRFunction @@ -243,8 +260,8 @@ class IRBasicBlock: %2 = mul %1, 2 is represented as: bb = IRBasicBlock("bb", function) - r1 = bb.append_inst("add", "%0", "1") - r2 = bb.append_inst("mul", r1, "2") + r1 = bb.append_instruction("add", "%0", "1") + r2 = bb.append_instruction("mul", r1, "2") The label of a basic block is used to refer to it from other basic blocks in order to branch to it. @@ -296,13 +313,29 @@ def remove_cfg_out(self, bb: "IRBasicBlock") -> None: def is_reachable(self) -> bool: return len(self.cfg_in) > 0 - def append_inst_no_ret(self, opcode: str, *args) -> None: - inst = IRInstruction(opcode, list(args)) - inst.parent = self - self.instructions.append(inst) + def append_instruction( + self, opcode: str, *args: IROperand, output: bool = None, force: bool = False + ) -> Optional[IRVariable]: + """ + Append an instruction to basic block. If output is True, the instruction + produces an output value, which can be used as an operand in other + instructions. If output is False, the instruction does not produce an + output value, and the return value is None. If output is None, the function + will automatically determine if the instruction produces an output value based + on the opcode. + + The method will assert the output value is appropriate for the opcode, unless + force is True. This is useful for the case that you want to append an instruction + and performa manual manipulations later. + """ + if output is None: + output = opcode not in NO_OUTPUT_INSTRUCTIONS + + assert force or not ( + output is True and opcode in NO_OUTPUT_INSTRUCTIONS + ), f"output=={output} without appropriate opcode '{opcode}'" - def append_inst(self, opcode: str, *args) -> IRVariable: - ret = self.parent.get_next_variable() + ret = self.parent.get_next_variable() if output else None inst = IRInstruction(opcode, list(args), ret) inst.parent = self self.instructions.append(inst) diff --git a/vyper/venom/ir_node_to_venom.py b/vyper/venom/ir_node_to_venom.py index 47d9eb1269..a7e8e309e2 100644 --- a/vyper/venom/ir_node_to_venom.py +++ b/vyper/venom/ir_node_to_venom.py @@ -72,7 +72,7 @@ "balance", ] -SymbolTable = dict[str, IROperand] +SymbolTable = dict[str, Optional[IROperand]] def _get_symbols_common(a: dict, b: dict) -> dict: @@ -93,11 +93,11 @@ def convert_ir_basicblock(ir: IRnode) -> IRFunction: for i, bb in enumerate(global_function.basic_blocks): if not bb.is_terminated and i < len(global_function.basic_blocks) - 1: - bb.append_inst("jmp", global_function.basic_blocks[i + 1].label) + bb.append_instruction("jmp", global_function.basic_blocks[i + 1].label) revert_bb = IRBasicBlock(IRLabel("__revert"), global_function) revert_bb = global_function.append_basic_block(revert_bb) - revert_bb.append_inst_no_ret("revert", IRLiteral(0), IRLiteral(0)) + revert_bb.append_instruction("revert", IRLiteral(0), IRLiteral(0), output=False) return global_function @@ -109,16 +109,16 @@ def _convert_binary_op( variables: OrderedSet, allocated_variables: dict[str, IRVariable], swap: bool = False, -) -> IRVariable: +) -> Optional[IRVariable]: ir_args = ir.args[::-1] if swap else ir.args arg_0 = _convert_ir_basicblock(ctx, ir_args[0], symbols, variables, allocated_variables) arg_1 = _convert_ir_basicblock(ctx, ir_args[1], symbols, variables, allocated_variables) - return ctx.get_basic_block().append_inst(ir.value, arg_1, arg_0) + return ctx.get_basic_block().append_instruction(str(ir.value), arg_1, arg_0) def _append_jmp(ctx: IRFunction, label: IRLabel) -> None: - ctx.get_basic_block().append_inst_no_ret("jmp", label) + ctx.get_basic_block().append_instruction("jmp", label, output=False) label = ctx.get_next_label() bb = IRBasicBlock(label, ctx) @@ -159,7 +159,7 @@ def _handle_self_call( ) if arg.location and arg.location.load_op == "calldataload": bb = ctx.get_basic_block() - ret = bb.append_inst(arg.location.load_op, ret) + ret = bb.append_instruction(arg.location.load_op, ret) ret_args.append(ret) if return_buf.is_literal: @@ -168,11 +168,11 @@ def _handle_self_call( bb = ctx.get_basic_block() do_ret = func_t.return_type is not None if do_ret: - invoke_ret = bb.append_inst("invoke", *ret_args) + invoke_ret = bb.append_instruction("invoke", *ret_args) allocated_variables["return_buffer"] = invoke_ret # type: ignore return invoke_ret else: - bb.append_inst_no_ret("invoke", *ret_args) + bb.append_instruction("invoke", *ret_args, output=False) return None @@ -186,17 +186,17 @@ def _handle_internal_func( old_ir_mempos += 64 for arg in func_t.arguments: - symbols[f"&{old_ir_mempos}"] = bb.append_inst("param") + symbols[f"&{old_ir_mempos}"] = bb.append_instruction("param") bb.instructions[-1].annotation = arg.name old_ir_mempos += 32 # arg.typ.memory_bytes_required # return buffer if func_t.return_type is not None: - symbols["return_buffer"] = bb.append_inst("param") + symbols["return_buffer"] = bb.append_instruction("param") bb.instructions[-1].annotation = "return_buffer" # return address - symbols["return_pc"] = bb.append_inst("param") + symbols["return_pc"] = bb.append_instruction("param") bb.instructions[-1].annotation = "return_pc" return ir.args[0].args[2] @@ -212,7 +212,7 @@ def _convert_ir_simple_node( args = [ _convert_ir_basicblock(ctx, arg, symbols, variables, allocated_variables) for arg in ir.args ] - return ctx.get_basic_block().append_inst(ir.value, *args) # type: ignore + return ctx.get_basic_block().append_instruction(ir.value, *args) # type: ignore _break_target: Optional[IRBasicBlock] = None @@ -233,20 +233,20 @@ def _get_variable_from_address( def _append_return_for_stack_operand( bb: IRBasicBlock, symbols: SymbolTable, ret_ir: IRVariable, last_ir: IRVariable -) -> IRInstruction: +) -> None: if isinstance(ret_ir, IRLiteral): sym = symbols.get(f"&{ret_ir.value}", None) - new_var = bb.append_inst("alloca", IRLiteral(32), ret_ir) - bb.append_inst_no_ret("mstore", sym, new_var) # type: ignore + new_var = bb.append_instruction("alloca", IRLiteral(32), ret_ir) + bb.append_instruction("mstore", sym, new_var, output=False) # type: ignore else: sym = symbols.get(ret_ir.value, None) if sym is None: # FIXME: needs real allocations - new_var = bb.append_inst("alloca", IRLiteral(32), IRLiteral(0)) - bb.append_inst_no_ret("mstore", ret_ir, new_var) # type: ignore + new_var = bb.append_instruction("alloca", IRLiteral(32), IRLiteral(0)) + bb.append_instruction("mstore", ret_ir, new_var, output=False) # type: ignore else: new_var = ret_ir - bb.append_inst_no_ret("return", last_ir, new_var) # type: ignore + bb.append_instruction("return", last_ir, new_var, output=False) # type: ignore def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): @@ -270,7 +270,7 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): ir.value = INVERSE_MAPPED_IR_INSTRUCTIONS[ir.value] new_var = _convert_binary_op(ctx, ir, symbols, variables, allocated_variables) ir.value = org_value - return ctx.get_basic_block().append_inst("iszero", new_var) + return ctx.get_basic_block().append_instruction("iszero", new_var) elif ir.value in PASS_THROUGH_INSTRUCTIONS: return _convert_ir_simple_node(ctx, ir, symbols, variables, allocated_variables) @@ -286,8 +286,8 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): runtimeLabel = ctx.get_next_label() - ctx.get_basic_block().append_inst_no_ret( - "deploy", IRLiteral(memsize), runtimeLabel, IRLiteral(padding) + ctx.get_basic_block().append_instruction( + "deploy", IRLiteral(memsize), runtimeLabel, IRLiteral(padding), output=False ) bb = IRBasicBlock(runtimeLabel, ctx) @@ -364,10 +364,10 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if ir.value == "call": args = [retSize, retOffset, argsSize, argsOffsetVar, value, address, gas] - return bb.append_inst(ir.value, *args) + return bb.append_instruction(ir.value, *args) else: args = [retSize, retOffset, argsSize, argsOffsetVar, address, gas] - return bb.append_inst(ir.value, *args) + return bb.append_instruction(ir.value, *args) elif ir.value == "if": cond = ir.args[0] current_bb = ctx.get_basic_block() @@ -387,7 +387,7 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): ) if isinstance(else_ret_val, IRLiteral): assert isinstance(else_ret_val.value, int) # help mypy - else_ret_val = ctx.get_basic_block().append_inst( + else_ret_val = ctx.get_basic_block().append_instruction( "store", IRLiteral(else_ret_val.value) ) after_else_syms = else_syms.copy() @@ -400,9 +400,13 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): ctx, ir.args[1], symbols, variables, allocated_variables ) if isinstance(then_ret_val, IRLiteral): - then_ret_val = ctx.get_basic_block().append_inst("store", IRLiteral(then_ret_val.value)) + then_ret_val = ctx.get_basic_block().append_instruction( + "store", IRLiteral(then_ret_val.value) + ) - current_bb.append_inst_no_ret("jnz", cont_ret, then_block.label, else_block.label) + current_bb.append_instruction( + "jnz", cont_ret, then_block.label, else_block.label, output=False + ) after_then_syms = symbols.copy() @@ -413,13 +417,13 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if_ret = None if then_ret_val is not None and else_ret_val is not None: - if_ret = bb.append_inst( + if_ret = bb.append_instruction( "phi", then_block.label, then_ret_val, else_block.label, else_ret_val ) common_symbols = _get_symbols_common(after_then_syms, after_else_syms) for sym, val in common_symbols.items(): - ret = bb.append_inst("phi", then_block.label, val[0], else_block.label, val[1]) + ret = bb.append_instruction("phi", then_block.label, val[0], else_block.label, val[1]) old_var = symbols.get(sym, None) symbols[sym] = ret if old_var is not None: @@ -428,10 +432,10 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): allocated_variables[idx] = ret # type: ignore if not else_block.is_terminated: - else_block.append_inst_no_ret("jmp", bb.label) + else_block.append_instruction("jmp", bb.label, output=False) if not then_block.is_terminated: - then_block.append_inst_no_ret("jmp", bb.label) + then_block.append_instruction("jmp", bb.label, output=False) return if_ret @@ -445,7 +449,7 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): sym = ir.args[0] if isinstance(ret, IRLiteral): - new_var = ctx.get_basic_block().append_inst("store", ret) # type: ignore + new_var = ctx.get_basic_block().append_instruction("store", ret) # type: ignore with_symbols[sym.value] = new_var else: with_symbols[sym.value] = ret # type: ignore @@ -457,12 +461,12 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): _append_jmp(ctx, IRLabel(ir.args[0].value)) elif ir.value == "jump": arg_1 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) - ctx.get_basic_block().append_inst_no_ret("jmp", arg_1) + ctx.get_basic_block().append_instruction("jmp", arg_1, output=False) _new_block(ctx) elif ir.value == "set": sym = ir.args[0] arg_1 = _convert_ir_basicblock(ctx, ir.args[1], symbols, variables, allocated_variables) - new_var = ctx.get_basic_block().append_inst("store", arg_1) # type: ignore + new_var = ctx.get_basic_block().append_instruction("store", arg_1) # type: ignore symbols[sym.value] = new_var elif ir.value == "calldatacopy": @@ -479,14 +483,14 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): bb = ctx.get_basic_block() if var is not None: if allocated_variables.get(var.name, None) is None: - new_v = bb.append_inst( + new_v = bb.append_instruction( "alloca", IRLiteral(var.size), IRLiteral(var.pos) # type: ignore ) allocated_variables[var.name] = new_v # type: ignore - bb.append_inst_no_ret("calldatacopy", size, arg_1, new_v) # type: ignore + bb.append_instruction("calldatacopy", size, arg_1, new_v, output=False) # type: ignore symbols[f"&{var.pos}"] = new_v # type: ignore else: - bb.append_inst_no_ret("calldatacopy", size, arg_1, new_v) # type: ignore + bb.append_instruction("calldatacopy", size, arg_1, new_v, output=False) # type: ignore return new_v elif ir.value == "codecopy": @@ -494,7 +498,9 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): arg_1 = _convert_ir_basicblock(ctx, ir.args[1], symbols, variables, allocated_variables) size = _convert_ir_basicblock(ctx, ir.args[2], symbols, variables, allocated_variables) - ctx.get_basic_block().append_inst_no_ret("codecopy", size, arg_1, arg_0) # type: ignore + ctx.get_basic_block().append_instruction( + "codecopy", size, arg_1, arg_0, output=False + ) # type: ignore elif ir.value == "symbol": return IRLabel(ir.args[0].value, True) elif ir.value == "data": @@ -512,12 +518,12 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): elif ir.value == "assert": arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) current_bb = ctx.get_basic_block() - current_bb.append_inst_no_ret("assert", arg_0) + current_bb.append_instruction("assert", arg_0, output=False) elif ir.value == "label": label = IRLabel(ir.args[0].value, True) bb = ctx.get_basic_block() if not bb.is_terminated: - bb.append_inst_no_ret("jmp", label) + bb.append_instruction("jmp", label, output=False) bb = IRBasicBlock(label, ctx) ctx.append_basic_block(bb) _convert_ir_basicblock(ctx, ir.args[2], symbols, variables, allocated_variables) @@ -530,10 +536,10 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): bb = ctx.get_basic_block() if func_t.name == "__init__": label = IRLabel(ir.args[0].value, True) - bb.append_inst_no_ret("jmp", label) + bb.append_instruction("jmp", label, output=False) return None if func_t.return_type is None: - bb.append_inst_no_ret("stop") + bb.append_instruction("stop", output=False) return None else: last_ir = None @@ -568,32 +574,34 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if var.size and int(var.size) > 32: offset = int(ret_ir.value) - var.pos # type: ignore if offset > 0: - ptr_var = bb.append_inst("add", IRLiteral(var.pos), IRLiteral(offset)) + ptr_var = bb.append_instruction( + "add", IRLiteral(var.pos), IRLiteral(offset) + ) else: ptr_var = allocated_var - bb.append_inst_no_ret("return", last_ir, ptr_var) + bb.append_instruction("return", last_ir, ptr_var, output=False) else: _append_return_for_stack_operand(ctx, symbols, new_var, last_ir) else: if isinstance(ret_ir, IRLiteral): sym = symbols.get(f"&{ret_ir.value}", None) if sym is None: - bb.append_inst_no_ret("return", last_ir, ret_ir) + bb.append_instruction("return", last_ir, ret_ir, output=False) else: if func_t.return_type.memory_bytes_required > 32: - new_var = bb.append_inst("alloca", IRLiteral(32), ret_ir) - bb.append_inst_no_ret("mstore", sym, new_var) - bb.append_inst_no_ret("return", last_ir, new_var) + new_var = bb.append_instruction("alloca", IRLiteral(32), ret_ir) + bb.append_instruction("mstore", sym, new_var, output=False) + bb.append_instruction("return", last_ir, new_var, output=False) else: - bb.append_inst_no_ret("return", last_ir, ret_ir) + bb.append_instruction("return", last_ir, ret_ir, output=False) else: if last_ir and int(last_ir.value) > 32: - bb.append_inst_no_ret("return", last_ir, ret_ir) + bb.append_instruction("return", last_ir, ret_ir, output=False) else: ret_buf = IRLiteral(128) # TODO: need allocator - new_var = bb.append_inst("alloca", IRLiteral(32), ret_buf) - bb.append_inst_no_ret("mstore", ret_ir, new_var) - bb.append_inst_no_ret("return", last_ir, new_var) + new_var = bb.append_instruction("alloca", IRLiteral(32), ret_buf) + bb.append_instruction("mstore", ret_ir, new_var, output=False) + bb.append_instruction("return", last_ir, new_var, output=False) ctx.append_basic_block(IRBasicBlock(ctx.get_next_label(), ctx)) @@ -601,28 +609,34 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if func_t.is_internal: assert ir.args[1].value == "return_pc", "return_pc not found" if func_t.return_type is None: - bb.append_inst_no_ret("ret", symbols["return_pc"]) + bb.append_instruction("ret", symbols["return_pc"], output=False) else: if func_t.return_type.memory_bytes_required > 32: - bb.append_inst_no_ret("ret", symbols["return_buffer"], symbols["return_pc"]) + bb.append_instruction( + "ret", symbols["return_buffer"], symbols["return_pc"], output=False + ) else: - ret_by_value = bb.append_inst("mload", symbols["return_buffer"]) - bb.append_inst_no_ret("ret", ret_by_value, symbols["return_pc"]) + ret_by_value = bb.append_instruction("mload", symbols["return_buffer"]) + bb.append_instruction("ret", ret_by_value, symbols["return_pc"], output=False) elif ir.value == "revert": arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) arg_1 = _convert_ir_basicblock(ctx, ir.args[1], symbols, variables, allocated_variables) - ctx.get_basic_block().append_inst_no_ret("revert", arg_1, arg_0) + ctx.get_basic_block().append_instruction("revert", arg_1, arg_0, output=False) elif ir.value == "dload": arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) bb = ctx.get_basic_block() - src = bb.append_inst("add", arg_0, IRLabel("code_end")) - - bb.append_inst_no_ret( - "dloadbytes", IRLiteral(32), src, IRLiteral(MemoryPositions.FREE_VAR_SPACE) + src = bb.append_instruction("add", arg_0, IRLabel("code_end")) + + bb.append_instruction( + "dloadbytes", + IRLiteral(32), + src, + IRLiteral(MemoryPositions.FREE_VAR_SPACE), + output=False, ) - return bb.append_inst("mload", IRLiteral(MemoryPositions.FREE_VAR_SPACE)) + return bb.append_instruction("mload", IRLiteral(MemoryPositions.FREE_VAR_SPACE)) elif ir.value == "dloadbytes": dst = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) @@ -631,8 +645,8 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): ) len_ = _convert_ir_basicblock(ctx, ir.args[2], symbols, variables, allocated_variables) bb = ctx.get_basic_block() - src = bb.append_inst("add", src_offset, IRLabel("code_end")) - bb.append_inst_no_ret("dloadbytes", len_, src, dst) + src = bb.append_instruction("add", src_offset, IRLabel("code_end")) + bb.append_instruction("dloadbytes", len_, src, dst, output=False) return None elif ir.value == "mload": @@ -644,22 +658,22 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if var is not None: if var.size and var.size > 32: if allocated_variables.get(var.name, None) is None: - allocated_variables[var.name] = bb.append_inst( + allocated_variables[var.name] = bb.append_instruction( "alloca", IRLiteral(var.size), IRLiteral(var.pos) ) offset = int(sym_ir.value) - var.pos if offset > 0: - ptr_var = bb.append_inst("add", IRLiteral(var.pos), IRLiteral(offset)) + ptr_var = bb.append_instruction("add", IRLiteral(var.pos), IRLiteral(offset)) else: ptr_var = allocated_variables[var.name] - return bb.append_inst("mload", ptr_var) + return bb.append_instruction("mload", ptr_var) else: if sym_ir.is_literal: sym = symbols.get(f"&{sym_ir.value}", None) if sym is None: - new_var = bb.append_inst("store", sym_ir) + new_var = bb.append_instruction("store", sym_ir) symbols[f"&{sym_ir.value}"] = new_var if allocated_variables.get(var.name, None) is None: allocated_variables[var.name] = new_var @@ -674,9 +688,9 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if sym_ir.is_literal: new_var = symbols.get(f"&{sym_ir.value}", None) if new_var is not None: - return bb.append_inst("mload", new_var) + return bb.append_instruction("mload", new_var) else: - return bb.append_inst("mload", IRLiteral(sym_ir.value)) + return bb.append_instruction("mload", IRLiteral(sym_ir.value)) else: new_var = _convert_ir_basicblock( ctx, sym_ir, symbols, variables, allocated_variables @@ -689,7 +703,7 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): # if sym_ir.is_self_call: return new_var - return bb.append_inst("mload", new_var) + return bb.append_instruction("mload", new_var) elif ir.value == "mstore": sym_ir = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) @@ -704,38 +718,38 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): if var is not None and var.size is not None: if var.size and var.size > 32: if allocated_variables.get(var.name, None) is None: - allocated_variables[var.name] = bb.append_inst( + allocated_variables[var.name] = bb.append_instruction( "alloca", IRLiteral(var.size), IRLiteral(var.pos) ) offset = int(sym_ir.value) - var.pos if offset > 0: - ptr_var = bb.append_inst("add", IRLiteral(var.pos), IRLiteral(offset)) + ptr_var = bb.append_instruction("add", IRLiteral(var.pos), IRLiteral(offset)) else: ptr_var = allocated_variables[var.name] - bb.append_inst_no_ret("mstore", arg_1, ptr_var) + bb.append_instruction("mstore", arg_1, ptr_var, output=False) else: if isinstance(sym_ir, IRLiteral): - new_var = bb.append_inst("store", arg_1) + new_var = bb.append_instruction("store", arg_1) symbols[f"&{sym_ir.value}"] = new_var # if allocated_variables.get(var.name, None) is None: allocated_variables[var.name] = new_var return new_var else: if not isinstance(sym_ir, IRLiteral): - bb.append_inst_no_ret("mstore", arg_1, sym_ir) + bb.append_instruction("mstore", arg_1, sym_ir, output=False) return None sym = symbols.get(f"&{sym_ir.value}", None) if sym is None: - bb.append_inst_no_ret("mstore", arg_1, sym_ir) + bb.append_instruction("mstore", arg_1, sym_ir, output=False) if arg_1 and not isinstance(sym_ir, IRLiteral): symbols[f"&{sym_ir.value}"] = arg_1 return None if isinstance(sym_ir, IRLiteral): - bb.append_inst_no_ret("mstore", arg_1, sym) + bb.append_instruction("mstore", arg_1, sym, output=False) return None else: symbols[sym_ir.value] = arg_1 @@ -743,11 +757,11 @@ def _convert_ir_basicblock(ctx, ir, symbols, variables, allocated_variables): elif ir.value in ["sload", "iload"]: arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) - return ctx.get_basic_block().append_inst(ir.value, arg_0) + return ctx.get_basic_block().append_instruction(ir.value, arg_0) elif ir.value in ["sstore", "istore"]: arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) arg_1 = _convert_ir_basicblock(ctx, ir.args[1], symbols, variables, allocated_variables) - ctx.get_basic_block().append_inst_no_ret(ir.value, arg_1, arg_0) + ctx.get_basic_block().append_instruction(ir.value, arg_1, arg_0, output=False) elif ir.value == "unique_symbol": sym = ir.args[0] new_var = ctx.get_next_variable() @@ -787,17 +801,17 @@ def emit_body_block(): counter_inc_var = ctx.get_next_variable() ret = ctx.get_next_variable() - counter_var = ctx.get_basic_block().append_inst("store", start) + counter_var = ctx.get_basic_block().append_instruction("store", start) symbols[sym.value] = counter_var - ctx.get_basic_block().append_inst_no_ret("jmp", cond_block.label) + ctx.get_basic_block().append_instruction("jmp", cond_block.label, output=False) - ret = cond_block.append_inst( + ret = cond_block.append_instruction( "phi", entry_block.label, counter_var, increment_block.label, counter_inc_var ) symbols[sym.value] = ret - xor_ret = cond_block.append_inst("xor", ret, end) - cont_ret = cond_block.append_inst("iszero", xor_ret) + xor_ret = cond_block.append_instruction("xor", ret, end) + cont_ret = cond_block.append_instruction("iszero", xor_ret) ctx.append_basic_block(cond_block) # Do a dry run to get the symbols needing phi nodes @@ -824,45 +838,45 @@ def emit_body_block(): body_end = ctx.get_basic_block() if not body_end.is_terminated: - body_end.append_inst_no_ret("jmp", jump_up_block.label) + body_end.append_instruction("jmp", jump_up_block.label, output=False) - jump_up_block.append_inst_no_ret("jmp", increment_block.label) + jump_up_block.append_instruction("jmp", increment_block.label, output=False) ctx.append_basic_block(jump_up_block) - increment_block.append_inst_no_ret(IRInstruction("add", ret, IRLiteral(1))) + increment_block.append_instruction(IRInstruction("add", ret, IRLiteral(1)), output=False) increment_block.insert_instruction[-1].output = counter_inc_var - increment_block.append_inst_no_ret("jmp", cond_block.label) + increment_block.append_instruction("jmp", cond_block.label, output=False) ctx.append_basic_block(increment_block) ctx.append_basic_block(exit_block) - cond_block.append_inst("jnz", cont_ret, exit_block.label, body_block.label) + cond_block.append_instruction("jnz", cont_ret, exit_block.label, body_block.label) elif ir.value == "break": assert _break_target is not None, "Break with no break target" - ctx.get_basic_block().append_inst("jmp", _break_target.label) + ctx.get_basic_block().append_instruction("jmp", _break_target.label) ctx.append_basic_block(IRBasicBlock(ctx.get_next_label(), ctx)) elif ir.value == "continue": assert _continue_target is not None, "Continue with no contrinue target" - ctx.get_basic_block().append_inst("jmp", _continue_target.label) + ctx.get_basic_block().append_instruction("jmp", _continue_target.label) ctx.append_basic_block(IRBasicBlock(ctx.get_next_label(), ctx)) elif ir.value == "gas": - return ctx.get_basic_block().append_inst("gas") + return ctx.get_basic_block().append_instruction("gas") elif ir.value == "returndatasize": - return ctx.get_basic_block().append_inst("returndatasize") + return ctx.get_basic_block().append_instruction("returndatasize") elif ir.value == "returndatacopy": assert len(ir.args) == 3, "returndatacopy with wrong number of arguments" arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) arg_1 = _convert_ir_basicblock(ctx, ir.args[1], symbols, variables, allocated_variables) size = _convert_ir_basicblock(ctx, ir.args[2], symbols, variables, allocated_variables) - new_var = ctx.get_basic_block().append_inst("returndatacopy", arg_1, size) + new_var = ctx.get_basic_block().append_instruction("returndatacopy", arg_1, size) symbols[f"&{arg_0.value}"] = new_var return new_var elif ir.value == "selfdestruct": arg_0 = _convert_ir_basicblock(ctx, ir.args[0], symbols, variables, allocated_variables) - ctx.get_basic_block().append_inst_no_ret("selfdestruct", arg_0) + ctx.get_basic_block().append_instruction("selfdestruct", arg_0, output=False) elif isinstance(ir.value, str) and ir.value.startswith("log"): args = reversed( [ @@ -870,7 +884,7 @@ def emit_body_block(): for arg in ir.args ] ) - ctx.get_basic_block().append_inst_no_ret(ir.value, *args) + ctx.get_basic_block().append_instruction(ir.value, *args, output=False) elif isinstance(ir.value, str) and ir.value.upper() in get_opcodes(): _convert_ir_opcode(ctx, ir, symbols, variables, allocated_variables) elif isinstance(ir.value, str) and ir.value in symbols: @@ -897,7 +911,7 @@ def _convert_ir_opcode( inst_args.append( _convert_ir_basicblock(ctx, arg, symbols, variables, allocated_variables) ) - ctx.get_basic_block().append_inst(opcode, *inst_args) + ctx.get_basic_block().append_instruction(opcode, *inst_args) def _data_ofst_of(sym, ofst, height_): diff --git a/vyper/venom/passes/normalization.py b/vyper/venom/passes/normalization.py index 98d6146e8c..9aeaecd476 100644 --- a/vyper/venom/passes/normalization.py +++ b/vyper/venom/passes/normalization.py @@ -61,7 +61,7 @@ def _insert_split_basicblock(self, bb: IRBasicBlock, in_bb: IRBasicBlock) -> IRB source = in_bb.label.value target = bb.label.value split_bb = IRBasicBlock(IRLabel(f"{target}_split_{source}"), self.ctx) - split_bb.append_inst_no_ret("jmp", bb.label) + split_bb.append_instruction("jmp", bb.label, output=False) self.ctx.append_basic_block(split_bb) # Rewire the CFG