def update_lvalue(new_ir, node, local_variables_instances, all_local_variables_instances, state_variables_instances, all_state_variables_instances): if isinstance(new_ir, OperationWithLValue): lvalue = new_ir.lvalue update_through_ref = False if isinstance(new_ir, (Assignment, Binary)): if isinstance(lvalue, ReferenceVariable): update_through_ref = True while isinstance(lvalue, ReferenceVariable): lvalue = lvalue.points_to if isinstance(lvalue, (LocalIRVariable, StateIRVariable)): if isinstance(lvalue, LocalIRVariable): new_var = LocalIRVariable(lvalue) new_var.index = all_local_variables_instances[ lvalue.name].index + 1 all_local_variables_instances[lvalue.name] = new_var local_variables_instances[lvalue.name] = new_var else: new_var = StateIRVariable(lvalue) new_var.index = all_state_variables_instances[ lvalue.canonical_name].index + 1 all_state_variables_instances[lvalue.canonical_name] = new_var state_variables_instances[lvalue.canonical_name] = new_var if update_through_ref: phi_operation = Phi(new_var, {node}) phi_operation.rvalues = [lvalue] node.add_ssa_ir(phi_operation) if not isinstance(new_ir.lvalue, ReferenceVariable): new_ir.lvalue = new_var else: to_update = new_ir.lvalue while isinstance(to_update.points_to, ReferenceVariable): to_update = to_update.points_to to_update.points_to = new_var
def initiate_all_local_variables_instances(nodes, local_variables_instances, all_local_variables_instances): for node in nodes: if node.variable_declaration: new_var = LocalIRVariable(node.variable_declaration) if new_var.name in all_local_variables_instances: new_var.index = all_local_variables_instances[new_var.name].index + 1 local_variables_instances[node.variable_declaration.name] = new_var all_local_variables_instances[node.variable_declaration.name] = new_var
def get(variable): if isinstance(variable, LocalVariable): if variable.name in local_variables_instances: return local_variables_instances[variable.name] new_var = LocalIRVariable(variable) local_variables_instances[variable.name] = new_var all_local_variables_instances[variable.name] = new_var return new_var if isinstance( variable, StateVariable ) and variable.canonical_name in state_variables_instances: return state_variables_instances[variable.canonical_name] elif isinstance(variable, ReferenceVariable): if not variable.index in reference_variables_instances: new_variable = ReferenceVariable(variable.node, index=variable.index) if variable.points_to: new_variable.points_to = get(variable.points_to) new_variable.set_type(variable.type) reference_variables_instances[variable.index] = new_variable return reference_variables_instances[variable.index] elif isinstance(variable, TemporaryVariable): if not variable.index in temporary_variables_instances: new_variable = TemporaryVariable(variable.node, index=variable.index) new_variable.set_type(variable.type) temporary_variables_instances[variable.index] = new_variable return temporary_variables_instances[variable.index] return variable
def get(variable, local_variables_instances, state_variables_instances, temporary_variables_instances, reference_variables_instances, tuple_variables_instances, all_local_variables_instances): # variable can be None # for example, on LowLevelCall, ir.lvalue can be none if variable is None: return None if isinstance(variable, LocalVariable): if variable.name in local_variables_instances: return local_variables_instances[variable.name] new_var = LocalIRVariable(variable) local_variables_instances[variable.name] = new_var all_local_variables_instances[variable.name] = new_var return new_var if isinstance(variable, StateVariable) and variable.canonical_name in state_variables_instances: return state_variables_instances[variable.canonical_name] elif isinstance(variable, ReferenceVariable): if not variable.index in reference_variables_instances: new_variable = ReferenceVariableSSA(variable) if variable.points_to: new_variable.points_to = get(variable.points_to, local_variables_instances, state_variables_instances, temporary_variables_instances, reference_variables_instances, tuple_variables_instances, all_local_variables_instances) new_variable.set_type(variable.type) reference_variables_instances[variable.index] = new_variable return reference_variables_instances[variable.index] elif isinstance(variable, TemporaryVariable): if not variable.index in temporary_variables_instances: new_variable = TemporaryVariableSSA(variable) new_variable.set_type(variable.type) temporary_variables_instances[variable.index] = new_variable return temporary_variables_instances[variable.index] elif isinstance(variable, TupleVariable): if not variable.index in tuple_variables_instances: new_variable = TupleVariableSSA(variable) new_variable.set_type(variable.type) tuple_variables_instances[variable.index] = new_variable return tuple_variables_instances[variable.index] assert isinstance(variable, (Constant, SolidityVariable, Contract, Enum, SolidityFunction, Structure, Function, Type)) # type for abi.decode(.., t) return variable
def last_name(n, var, init_vars): candidates = [] # Todo optimize by creating a variables_ssa_written attribute for ir_ssa in n.irs_ssa: if isinstance(ir_ssa, OperationWithLValue): lvalue = ir_ssa.lvalue while isinstance(lvalue, ReferenceVariable): lvalue = lvalue.points_to if lvalue and lvalue.name == var.name: candidates.append(lvalue) if n.variable_declaration and n.variable_declaration.name == var.name: candidates.append(LocalIRVariable(n.variable_declaration)) if n.type == NodeType.ENTRYPOINT: if var.name in init_vars: candidates.append(init_vars[var.name]) assert candidates return max(candidates, key=lambda v: v.index)
def add_ssa_ir(function, all_state_variables_instances): ''' Add SSA version of the IR Args: function all_state_variables_instances ''' if not function.is_implemented: return init_definition = dict() for v in function.parameters + function.returns: if v.name: init_definition[v.name] = (v, function.entry_point) # We only add phi function for state variable at entry node if # The state variable is used # And if the state variables is written in another function (otherwise its stay at index 0) for (_, variable_instance) in all_state_variables_instances.items(): if is_used_later(function.entry_point, variable_instance): # rvalues are fixed in solc_parsing.declaration.function function.entry_point.add_ssa_ir( Phi(StateIRVariable(variable_instance), set())) add_phi_origins(function.entry_point, init_definition, dict()) for node in function.nodes: for (variable, nodes) in node.phi_origins_local_variables.values(): if len(nodes) < 2: continue if not is_used_later(node, variable): continue node.add_ssa_ir(Phi(LocalIRVariable(variable), nodes)) for (variable, nodes) in node.phi_origins_state_variables.values(): if len(nodes) < 2: continue #if not is_used_later(node, variable.name, []): # continue node.add_ssa_ir(Phi(StateIRVariable(variable), nodes)) init_local_variables_instances = dict() for v in function.parameters: if v.name: new_var = LocalIRVariable(v) function.add_parameter_ssa(new_var) if new_var.is_storage: fake_variable = LocalIRVariable(v) fake_variable.name = 'STORAGE_' + fake_variable.name fake_variable.set_location('reference_to_storage') new_var.refers_to = {fake_variable} init_local_variables_instances[ fake_variable.name] = fake_variable init_local_variables_instances[v.name] = new_var for v in function.returns: if v.name: new_var = LocalIRVariable(v) function.add_return_ssa(new_var) if new_var.is_storage: fake_variable = LocalIRVariable(v) fake_variable.name = 'STORAGE_' + fake_variable.name fake_variable.set_location('reference_to_storage') new_var.refers_to = {fake_variable} init_local_variables_instances[ fake_variable.name] = fake_variable init_local_variables_instances[v.name] = new_var all_init_local_variables_instances = dict(init_local_variables_instances) init_state_variables_instances = dict(all_state_variables_instances) initiate_all_local_variables_instances(function.nodes, init_local_variables_instances, all_init_local_variables_instances) generate_ssa_irs(function.entry_point, dict(init_local_variables_instances), all_init_local_variables_instances, dict(init_state_variables_instances), all_state_variables_instances, init_local_variables_instances, []) fix_phi_rvalues_and_storage_ref(function.entry_point, dict(init_local_variables_instances), all_init_local_variables_instances, dict(init_state_variables_instances), all_state_variables_instances, init_local_variables_instances)