Beispiel #1
0
def convert_assignment(left, right, t, return_type):
    if t == AssignmentOperationType.ASSIGN:
        return Assignment(left, right, return_type)
    elif t == AssignmentOperationType.ASSIGN_OR:
        return Binary(left, left, right, BinaryType.OR)
    elif t == AssignmentOperationType.ASSIGN_CARET:
        return Binary(left, left, right, BinaryType.CARET)
    elif t == AssignmentOperationType.ASSIGN_AND:
        return Binary(left, left, right, BinaryType.AND)
    elif t == AssignmentOperationType.ASSIGN_LEFT_SHIFT:
        return Binary(left, left, right, BinaryType.LEFT_SHIFT)
    elif t == AssignmentOperationType.ASSIGN_RIGHT_SHIFT:
        return Binary(left, left, right, BinaryType.RIGHT_SHIFT)
    elif t == AssignmentOperationType.ASSIGN_ADDITION:
        return Binary(left, left, right, BinaryType.ADDITION)
    elif t == AssignmentOperationType.ASSIGN_SUBTRACTION:
        return Binary(left, left, right, BinaryType.SUBTRACTION)
    elif t == AssignmentOperationType.ASSIGN_MULTIPLICATION:
        return Binary(left, left, right, BinaryType.MULTIPLICATION)
    elif t == AssignmentOperationType.ASSIGN_DIVISION:
        return Binary(left, left, right, BinaryType.DIVISION)
    elif t == AssignmentOperationType.ASSIGN_MODULO:
        return Binary(left, left, right, BinaryType.MODULO)

    raise SlithIRError('Missing type during assignment conversion')
Beispiel #2
0
 def _post_unary_operation(self, expression):
     value = get(expression.expression)
     if expression.type in [
             UnaryOperationType.BANG, UnaryOperationType.TILD
     ]:
         lvalue = TemporaryVariable(self._node)
         operation = Unary(lvalue, value, expression.type)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, lvalue)
     elif expression.type in [UnaryOperationType.DELETE]:
         operation = Delete(value, value)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, value)
     elif expression.type in [UnaryOperationType.PLUSPLUS_PRE]:
         operation = Binary(value, value, Constant("1", value.type),
                            BinaryType.ADDITION)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, value)
     elif expression.type in [UnaryOperationType.MINUSMINUS_PRE]:
         operation = Binary(value, value, Constant("1", value.type),
                            BinaryType.SUBTRACTION)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, value)
     elif expression.type in [UnaryOperationType.PLUSPLUS_POST]:
         lvalue = TemporaryVariable(self._node)
         operation = Assignment(lvalue, value, value.type)
         operation.set_expression(expression)
         self._result.append(operation)
         operation = Binary(value, value, Constant("1", value.type),
                            BinaryType.ADDITION)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, lvalue)
     elif expression.type in [UnaryOperationType.MINUSMINUS_POST]:
         lvalue = TemporaryVariable(self._node)
         operation = Assignment(lvalue, value, value.type)
         operation.set_expression(expression)
         self._result.append(operation)
         operation = Binary(value, value, Constant("1", value.type),
                            BinaryType.SUBTRACTION)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, lvalue)
     elif expression.type in [UnaryOperationType.PLUS_PRE]:
         set_val(expression, value)
     elif expression.type in [UnaryOperationType.MINUS_PRE]:
         lvalue = TemporaryVariable(self._node)
         operation = Binary(lvalue, Constant("0", value.type), value,
                            BinaryType.SUBTRACTION)
         operation.set_expression(expression)
         self._result.append(operation)
         set_val(expression, lvalue)
     else:
         raise SlithIRError(
             'Unary operation to IR not supported {}'.format(expression))
    def _post_binary_operation(self, expression):
        left = get(expression.expression_left)
        right = get(expression.expression_right)
        val = TemporaryVariable(self._node)

        operation = Binary(val, left, right, expression.type)
        operation.set_expression(expression)
        self._result.append(operation)
        set_val(expression, val)
Beispiel #4
0
    def _post_binary_operation(self, expression):
        left = get(expression.expression_left)
        right = get(expression.expression_right)
        val = TemporaryVariable(self._node)

        if expression.type in _signed_to_unsigned:
            new_left = TemporaryVariable(self._node)
            conv_left = TypeConversion(new_left, left, ElementaryType('int256'))
            conv_left.set_expression(expression)
            self._result.append(conv_left)

            if expression.type != BinaryOperationType.RIGHT_SHIFT_ARITHMETIC:
                new_right = TemporaryVariable(self._node)
                conv_right = TypeConversion(new_right, right, ElementaryType('int256'))
                conv_right.set_expression(expression)
                self._result.append(conv_right)
            else:
                new_right = right

            new_final = TemporaryVariable(self._node)
            operation = Binary(new_final, new_left, new_right, _signed_to_unsigned[expression.type])
            operation.set_expression(expression)
            self._result.append(operation)

            conv_final = TypeConversion(val, new_final, ElementaryType('uint256'))
            conv_final.set_expression(expression)
            self._result.append(conv_final)
        else:
            operation = Binary(val, left, right, _binary_to_binary[expression.type])
            operation.set_expression(expression)
            self._result.append(operation)

        set_val(expression, val)
Beispiel #5
0
def convert_to_pop(ir, node):
    """
    Convert pop operators
    Return a list of 6 operations
    """

    ret = []

    arr = ir.destination
    length = ReferenceVariable(node)
    length.set_type(ElementaryType('uint256'))

    ir_length = Length(arr, length)
    ir_length.set_expression(ir.expression)
    ir_length.lvalue.points_to = arr
    ret.append(ir_length)

    val = TemporaryVariable(node)

    ir_sub_1 = Binary(val, length, Constant("1", ElementaryType('uint256')),
                      BinaryType.SUBTRACTION)
    ir_sub_1.set_expression(ir.expression)
    ret.append(ir_sub_1)

    element_to_delete = ReferenceVariable(node)
    ir_assign_element_to_delete = Index(element_to_delete, arr, val,
                                        ElementaryType('uint256'))
    ir_length.lvalue.points_to = arr
    element_to_delete.set_type(ElementaryType('uint256'))
    ir_assign_element_to_delete.set_expression(ir.expression)
    ret.append(ir_assign_element_to_delete)

    ir_delete = Delete(element_to_delete, element_to_delete)
    ir_delete.set_expression(ir.expression)
    ret.append(ir_delete)

    length_to_assign = ReferenceVariable(node)
    length_to_assign.set_type(ElementaryType('uint256'))
    ir_length = Length(arr, length_to_assign)
    ir_length.set_expression(ir.expression)
    ir_length.lvalue.points_to = arr
    ret.append(ir_length)

    ir_assign_length = Assignment(length_to_assign, val,
                                  ElementaryType('uint256'))
    ir_assign_length.set_expression(ir.expression)
    ret.append(ir_assign_length)

    return ret
Beispiel #6
0
def copy_ir(ir, local_variables_instances, state_variables_instances,
            temporary_variables_instances, reference_variables_instances,
            all_local_variables_instances):
    '''
    Args:
        ir (Operation)
        local_variables_instances(dict(str -> LocalVariable))
        state_variables_instances(dict(str -> StateVariable))
        temporary_variables_instances(dict(int -> Variable))
        reference_variables_instances(dict(int -> Variable))

    Note: temporary and reference can be indexed by int, as they dont need phi functions
    '''
    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(ir, f):
        variable = f(ir)
        variable = get(variable)
        return variable

    def get_arguments(ir):
        arguments = []
        for arg in ir.arguments:
            arg = get(arg)
            arguments.append(arg)
        return arguments

    def get_rec_values(ir, f):
        # Use by InitArray and NewArray
        # Potential recursive array(s)
        ori_init_values = f(ir)

        def traversal(values):
            ret = []
            for v in values:
                if isinstance(v, list):
                    v = traversal(v)
                else:
                    v = get(v)
                ret.append(v)
            return ret

        return traversal(ori_init_values)

    if isinstance(ir, Assignment):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        rvalue = get_variable(ir, lambda x: ir.rvalue)
        variable_return_type = ir.variable_return_type
        return Assignment(lvalue, rvalue, variable_return_type)
    elif isinstance(ir, Balance):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        value = get_variable(ir, lambda x: ir.value)
        return Balance(value, lvalue)
    elif isinstance(ir, Binary):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        variable_left = get_variable(ir, lambda x: ir.variable_left)
        variable_right = get_variable(ir, lambda x: ir.variable_right)
        operation_type = ir.type
        return Binary(lvalue, variable_left, variable_right, operation_type)
    elif isinstance(ir, Condition):
        val = get_variable(ir, lambda x: ir.value)
        return Condition(val)
    elif isinstance(ir, Delete):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        variable = get_variable(ir, lambda x: ir.variable)
        return Delete(lvalue, variable)
    elif isinstance(ir, EventCall):
        name = ir.name
        return EventCall(name)
    elif isinstance(ir, HighLevelCall):  # include LibraryCall
        destination = get_variable(ir, lambda x: ir.destination)
        function_name = ir.function_name
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        type_call = ir.type_call
        if isinstance(ir, LibraryCall):
            new_ir = LibraryCall(destination, function_name, nbr_arguments,
                                 lvalue, type_call)
        else:
            new_ir = HighLevelCall(destination, function_name, nbr_arguments,
                                   lvalue, type_call)
        new_ir.call_id = ir.call_id
        new_ir.call_value = get_variable(ir, lambda x: ir.call_value)
        new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas)
        new_ir.arguments = get_arguments(ir)
        new_ir.function = ir.function
        return new_ir
    elif isinstance(ir, Index):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        variable_left = get_variable(ir, lambda x: ir.variable_left)
        variable_right = get_variable(ir, lambda x: ir.variable_right)
        index_type = ir.index_type
        return Index(lvalue, variable_left, variable_right, index_type)
    elif isinstance(ir, InitArray):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        init_values = get_rec_values(ir, lambda x: ir.init_values)
        return InitArray(init_values, lvalue)
    elif isinstance(ir, InternalCall):
        function = ir.function
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        type_call = ir.type_call
        new_ir = InternalCall(function, nbr_arguments, lvalue, type_call)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, InternalDynamicCall):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        function = ir.function
        function_type = ir.function_type
        new_ir = InternalDynamicCall(lvalue, function, function_type)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, LowLevelCall):
        destination = get_variable(ir, lambda x: x.destination)
        function_name = ir.function_name
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        type_call = ir.type_call
        new_ir = LowLevelCall(destination, function_name, nbr_arguments,
                              lvalue, type_call)
        new_ir.call_id = ir.call_id
        new_ir.call_value = get_variable(ir, lambda x: ir.call_value)
        new_ir.call_gas = get_variable(ir, lambda x: ir.call_gas)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, Member):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        variable_left = get_variable(ir, lambda x: ir.variable_left)
        variable_right = get_variable(ir, lambda x: ir.variable_right)
        return Member(variable_left, variable_right, lvalue)
    elif isinstance(ir, NewArray):
        depth = ir.depth
        array_type = ir.array_type
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        new_ir = NewArray(depth, array_type, lvalue)
        new_ir.arguments = get_rec_values(ir, lambda x: ir.arguments)
        return new_ir
    elif isinstance(ir, NewElementaryType):
        new_type = ir.type
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        new_ir = NewElementaryType(new_type, lvalue)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, NewContract):
        contract_name = ir.contract_name
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        new_ir = NewContract(contract_name, lvalue)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, NewStructure):
        structure = ir.structure
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        new_ir = NewStructure(structure, lvalue)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, Push):
        array = get_variable(ir, lambda x: ir.array)
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        return Push(array, lvalue)
    elif isinstance(ir, Return):
        value = [get_variable(x, lambda y: y) for x in ir.values]
        return Return(value)
    elif isinstance(ir, Send):
        destination = get_variable(ir, lambda x: ir.destination)
        value = get_variable(ir, lambda x: ir.call_value)
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        return Send(destination, value, lvalue)
    elif isinstance(ir, SolidityCall):
        function = ir.function
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        type_call = ir.type_call
        new_ir = SolidityCall(function, nbr_arguments, lvalue, type_call)
        new_ir.arguments = get_arguments(ir)
        return new_ir
    elif isinstance(ir, Transfer):
        destination = get_variable(ir, lambda x: ir.destination)
        value = get_variable(ir, lambda x: ir.call_value)
        return Transfer(destination, value)
    elif isinstance(ir, TypeConversion):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        variable = get_variable(ir, lambda x: ir.variable)
        variable_type = ir.type
        return TypeConversion(lvalue, variable, variable_type)
    elif isinstance(ir, Unary):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        rvalue = get_variable(ir, lambda x: ir.rvalue)
        operation_type = ir.type
        return Unary(lvalue, rvalue, operation_type)
    elif isinstance(ir, Unpack):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        tuple_var = ir.tuple
        idx = ir.index
        return Unpack(lvalue, tuple_var, idx)
    elif isinstance(ir, Length):
        lvalue = get_variable(ir, lambda x: ir.lvalue)
        value = get_variable(ir, lambda x: ir.value)
        return Length(value, lvalue)

    logger.error('Impossible ir copy on {} ({})'.format(ir, type(ir)))
    exit(-1)
Beispiel #7
0
def copy_ir(ir, *instances):
    '''
    Args:
        ir (Operation)
        local_variables_instances(dict(str -> LocalVariable))
        state_variables_instances(dict(str -> StateVariable))
        temporary_variables_instances(dict(int -> Variable))
        reference_variables_instances(dict(int -> Variable))

    Note: temporary and reference can be indexed by int, as they dont need phi functions
    '''
    if isinstance(ir, Assignment):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
        variable_return_type = ir.variable_return_type
        return Assignment(lvalue, rvalue, variable_return_type)
    elif isinstance(ir, Balance):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        value = get_variable(ir, lambda x: x.value, *instances)
        return Balance(value, lvalue)
    elif isinstance(ir, Binary):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
        variable_right = get_variable(ir, lambda x: x.variable_right,
                                      *instances)
        operation_type = ir.type
        return Binary(lvalue, variable_left, variable_right, operation_type)
    elif isinstance(ir, Condition):
        val = get_variable(ir, lambda x: x.value, *instances)
        return Condition(val)
    elif isinstance(ir, Delete):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        variable = get_variable(ir, lambda x: x.variable, *instances)
        return Delete(lvalue, variable)
    elif isinstance(ir, EventCall):
        name = ir.name
        return EventCall(name)
    elif isinstance(ir, HighLevelCall):  # include LibraryCall
        destination = get_variable(ir, lambda x: x.destination, *instances)
        function_name = ir.function_name
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        type_call = ir.type_call
        if isinstance(ir, LibraryCall):
            new_ir = LibraryCall(destination, function_name, nbr_arguments,
                                 lvalue, type_call)
        else:
            new_ir = HighLevelCall(destination, function_name, nbr_arguments,
                                   lvalue, type_call)
        new_ir.call_id = ir.call_id
        new_ir.call_value = get_variable(ir, lambda x: x.call_value,
                                         *instances)
        new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances)
        new_ir.arguments = get_arguments(ir, *instances)
        new_ir.function = ir.function
        return new_ir
    elif isinstance(ir, Index):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
        variable_right = get_variable(ir, lambda x: x.variable_right,
                                      *instances)
        index_type = ir.index_type
        return Index(lvalue, variable_left, variable_right, index_type)
    elif isinstance(ir, InitArray):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        init_values = get_rec_values(ir, lambda x: x.init_values, *instances)
        return InitArray(init_values, lvalue)
    elif isinstance(ir, InternalCall):
        function = ir.function
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        type_call = ir.type_call
        new_ir = InternalCall(function, nbr_arguments, lvalue, type_call)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, InternalDynamicCall):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        function = get_variable(ir, lambda x: x.function, *instances)
        function_type = ir.function_type
        new_ir = InternalDynamicCall(lvalue, function, function_type)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, LowLevelCall):
        destination = get_variable(ir, lambda x: x.destination, *instances)
        function_name = ir.function_name
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        type_call = ir.type_call
        new_ir = LowLevelCall(destination, function_name, nbr_arguments,
                              lvalue, type_call)
        new_ir.call_id = ir.call_id
        new_ir.call_value = get_variable(ir, lambda x: x.call_value,
                                         *instances)
        new_ir.call_gas = get_variable(ir, lambda x: x.call_gas, *instances)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, Member):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        variable_left = get_variable(ir, lambda x: x.variable_left, *instances)
        variable_right = get_variable(ir, lambda x: x.variable_right,
                                      *instances)
        return Member(variable_left, variable_right, lvalue)
    elif isinstance(ir, NewArray):
        depth = ir.depth
        array_type = ir.array_type
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        new_ir = NewArray(depth, array_type, lvalue)
        new_ir.arguments = get_rec_values(ir, lambda x: x.arguments,
                                          *instances)
        return new_ir
    elif isinstance(ir, NewElementaryType):
        new_type = ir.type
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        new_ir = NewElementaryType(new_type, lvalue)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, NewContract):
        contract_name = ir.contract_name
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        new_ir = NewContract(contract_name, lvalue)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, NewStructure):
        structure = ir.structure
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        new_ir = NewStructure(structure, lvalue)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, Push):
        array = get_variable(ir, lambda x: x.array, *instances)
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        return Push(array, lvalue)
    elif isinstance(ir, Return):
        values = get_rec_values(ir, lambda x: x.values, *instances)
        return Return(values)
    elif isinstance(ir, Send):
        destination = get_variable(ir, lambda x: x.destination, *instances)
        value = get_variable(ir, lambda x: x.call_value, *instances)
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        return Send(destination, value, lvalue)
    elif isinstance(ir, SolidityCall):
        function = ir.function
        nbr_arguments = ir.nbr_arguments
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        type_call = ir.type_call
        new_ir = SolidityCall(function, nbr_arguments, lvalue, type_call)
        new_ir.arguments = get_arguments(ir, *instances)
        return new_ir
    elif isinstance(ir, Transfer):
        destination = get_variable(ir, lambda x: x.destination, *instances)
        value = get_variable(ir, lambda x: x.call_value, *instances)
        return Transfer(destination, value)
    elif isinstance(ir, TypeConversion):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        variable = get_variable(ir, lambda x: x.variable, *instances)
        variable_type = ir.type
        return TypeConversion(lvalue, variable, variable_type)
    elif isinstance(ir, Unary):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
        operation_type = ir.type
        return Unary(lvalue, rvalue, operation_type)
    elif isinstance(ir, Unpack):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        tuple_var = get_variable(ir, lambda x: x.tuple, *instances)
        idx = ir.index
        return Unpack(lvalue, tuple_var, idx)
    elif isinstance(ir, Length):
        lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
        value = get_variable(ir, lambda x: x.value, *instances)
        return Length(value, lvalue)

    logger.error('Impossible ir copy on {} ({})'.format(ir, type(ir)))
    exit(-1)