|
@@ -363,39 +363,12 @@ def propagate_type_and_convert_call(result, node):
|
|
|
new_ins = propagate_types(ins, node)
|
|
|
if new_ins:
|
|
|
if isinstance(new_ins, (list,)):
|
|
|
- if len(new_ins) == 2:
|
|
|
- new_ins[0].set_node(ins.node)
|
|
|
- new_ins[1].set_node(ins.node)
|
|
|
- del result[idx]
|
|
|
- result.insert(idx, new_ins[0])
|
|
|
- result.insert(idx + 1, new_ins[1])
|
|
|
- idx = idx + 1
|
|
|
- elif len(new_ins) == 3:
|
|
|
- new_ins[0].set_node(ins.node)
|
|
|
- new_ins[1].set_node(ins.node)
|
|
|
- new_ins[2].set_node(ins.node)
|
|
|
- del result[idx]
|
|
|
- result.insert(idx, new_ins[0])
|
|
|
- result.insert(idx + 1, new_ins[1])
|
|
|
- result.insert(idx + 2, new_ins[2])
|
|
|
- idx = idx + 2
|
|
|
- else:
|
|
|
- # Pop conversion
|
|
|
- assert len(new_ins) == 6
|
|
|
- new_ins[0].set_node(ins.node)
|
|
|
- new_ins[1].set_node(ins.node)
|
|
|
- new_ins[2].set_node(ins.node)
|
|
|
- new_ins[3].set_node(ins.node)
|
|
|
- new_ins[4].set_node(ins.node)
|
|
|
- new_ins[5].set_node(ins.node)
|
|
|
- del result[idx]
|
|
|
- result.insert(idx, new_ins[0])
|
|
|
- result.insert(idx + 1, new_ins[1])
|
|
|
- result.insert(idx + 2, new_ins[2])
|
|
|
- result.insert(idx + 3, new_ins[3])
|
|
|
- result.insert(idx + 4, new_ins[4])
|
|
|
- result.insert(idx + 5, new_ins[5])
|
|
|
- idx = idx + 5
|
|
|
+ for new_ins_ in new_ins:
|
|
|
+ new_ins_.set_node(ins.node)
|
|
|
+ del result[idx]
|
|
|
+ for i, ins in enumerate(new_ins):
|
|
|
+ result.insert(idx + i, ins)
|
|
|
+ idx = idx + len(new_ins) - 1
|
|
|
else:
|
|
|
new_ins.set_node(ins.node)
|
|
|
result[idx] = new_ins
|
|
@@ -518,7 +491,7 @@ def propagate_types(ir, node): # pylint: disable=too-many-locals
|
|
|
if isinstance(t, ArrayType) or (
|
|
|
isinstance(t, ElementaryType) and t.type == "bytes"
|
|
|
):
|
|
|
- if ir.function_name == "push" and len(ir.arguments) == 1:
|
|
|
+ if ir.function_name == "push" and len(ir.arguments) <= 1:
|
|
|
return convert_to_push(ir, node)
|
|
|
if ir.function_name == "pop" and len(ir.arguments) == 0:
|
|
|
return convert_to_pop(ir, node)
|
|
@@ -1024,67 +997,94 @@ def convert_to_solidity_func(ir):
|
|
|
return new_ir
|
|
|
|
|
|
|
|
|
-def convert_to_push(ir, node):
|
|
|
- """
|
|
|
- Convert a call to a PUSH operaiton
|
|
|
+def convert_to_push_expand_arr(ir, node, ret):
|
|
|
+ arr = ir.destination
|
|
|
|
|
|
- The funciton assume to receive a correct IR
|
|
|
- The checks must be done by the caller
|
|
|
+ length = ReferenceVariable(node)
|
|
|
+ length.set_type(ElementaryType("uint256"))
|
|
|
|
|
|
- May necessitate to create an intermediate operation (InitArray)
|
|
|
- Necessitate to return the lenght (see push documentation)
|
|
|
- As a result, the function return may return a list
|
|
|
- """
|
|
|
+ ir_length = Length(arr, length)
|
|
|
+ ir_length.set_expression(ir.expression)
|
|
|
+ ir_length.set_node(ir.node)
|
|
|
+ ir_length.lvalue.points_to = arr
|
|
|
+ ret.append(ir_length)
|
|
|
|
|
|
- # TODO remove Push Operator, and change this to existing operators
|
|
|
+ length_val = TemporaryVariable(node)
|
|
|
+ length_val.set_type(ElementaryType("uint256"))
|
|
|
+ ir_get_length = Assignment(length_val, length, ElementaryType("uint256"))
|
|
|
+ ir_get_length.set_expression(ir.expression)
|
|
|
+ ir_get_length.set_node(ir.node)
|
|
|
+ ret.append(ir_get_length)
|
|
|
|
|
|
- lvalue = ir.lvalue
|
|
|
- if isinstance(ir.arguments[0], list):
|
|
|
- ret = []
|
|
|
+ new_length_val = TemporaryVariable(node)
|
|
|
+ ir_add_1 = Binary(
|
|
|
+ new_length_val, length_val, Constant("1", ElementaryType("uint256")), BinaryType.ADDITION
|
|
|
+ )
|
|
|
+ ir_add_1.set_expression(ir.expression)
|
|
|
+ ir_add_1.set_node(ir.node)
|
|
|
+ ret.append(ir_add_1)
|
|
|
+
|
|
|
+ ir_assign_length = Assignment(length, new_length_val, ElementaryType("uint256"))
|
|
|
+ ir_assign_length.set_expression(ir.expression)
|
|
|
+ ir_assign_length.set_node(ir.node)
|
|
|
+ ret.append(ir_assign_length)
|
|
|
|
|
|
- val = TemporaryVariable(node)
|
|
|
- operation = InitArray(ir.arguments[0], val)
|
|
|
- operation.set_expression(ir.expression)
|
|
|
- operation.set_node(ir.node)
|
|
|
- ret.append(operation)
|
|
|
+ return length_val
|
|
|
|
|
|
- prev_ir = ir
|
|
|
- ir = Push(ir.destination, val)
|
|
|
- ir.set_expression(prev_ir.expression)
|
|
|
- ir.set_node(prev_ir.node)
|
|
|
|
|
|
- length = Literal(len(operation.init_values), "uint256")
|
|
|
- t = operation.init_values[0].type
|
|
|
- ir.lvalue.set_type(ArrayType(t, length))
|
|
|
+def convert_to_push_set_val(ir, node, length_val, ret):
|
|
|
+ arr = ir.destination
|
|
|
|
|
|
- ret.append(ir)
|
|
|
+ new_type = ir.destination.type.type
|
|
|
+
|
|
|
+ element_to_add = ReferenceVariable(node)
|
|
|
+ element_to_add.set_type(new_type)
|
|
|
+ ir_assign_element_to_add = Index(element_to_add, arr, length_val, ElementaryType("uint256"))
|
|
|
+ ir_assign_element_to_add.set_expression(ir.expression)
|
|
|
+ ir_assign_element_to_add.set_node(ir.node)
|
|
|
+ ret.append(ir_assign_element_to_add)
|
|
|
+
|
|
|
+ if len(ir.arguments) > 0:
|
|
|
+ assign_value = ir.arguments[0]
|
|
|
+ if isinstance(assign_value, list):
|
|
|
+ assign_value = TemporaryVariable(node)
|
|
|
+ assign_value.set_type(element_to_add.type)
|
|
|
+ ir_assign_value = InitArray(ir.arguments[0], assign_value)
|
|
|
+ ir_assign_value.set_expression(ir.expression)
|
|
|
+ ir_assign_value.set_node(ir.node)
|
|
|
+ ret.append(ir_assign_value)
|
|
|
+
|
|
|
+ ir_assign_value = Assignment(element_to_add, assign_value, assign_value.type)
|
|
|
+ ir_assign_value.set_expression(ir.expression)
|
|
|
+ ir_assign_value.set_node(ir.node)
|
|
|
+ ret.append(ir_assign_value)
|
|
|
+ else:
|
|
|
+ new_element = ir.lvalue
|
|
|
+ new_element.set_type(new_type)
|
|
|
+ ir_assign_value = Assignment(new_element, element_to_add, new_type)
|
|
|
+ ir_assign_value.set_expression(ir.expression)
|
|
|
+ ir_assign_value.set_node(ir.node)
|
|
|
+ ret.append(ir_assign_value)
|
|
|
|
|
|
- if lvalue:
|
|
|
- length = Length(ir.array, lvalue)
|
|
|
- length.set_expression(ir.expression)
|
|
|
- length.lvalue.points_to = ir.lvalue
|
|
|
- length.set_node(ir.node)
|
|
|
- ret.append(length)
|
|
|
|
|
|
- return ret
|
|
|
+def convert_to_push(ir, node):
|
|
|
+ """
|
|
|
+ Convert a call to a series of operations to push a new value onto the array
|
|
|
|
|
|
- prev_ir = ir
|
|
|
- ir = Push(ir.destination, ir.arguments[0])
|
|
|
- ir.set_expression(prev_ir.expression)
|
|
|
- ir.set_node(prev_ir.node)
|
|
|
+ The function assume to receive a correct IR
|
|
|
+ The checks must be done by the caller
|
|
|
|
|
|
- if lvalue:
|
|
|
- ret = []
|
|
|
- ret.append(ir)
|
|
|
+ May necessitate to create an intermediate operation (InitArray)
|
|
|
+ Necessitate to return the length (see push documentation)
|
|
|
+ As a result, the function return may return a list
|
|
|
+ """
|
|
|
|
|
|
- length = Length(ir.array, lvalue)
|
|
|
- length.set_expression(ir.expression)
|
|
|
- length.lvalue.points_to = ir.lvalue
|
|
|
- length.set_node(ir.node)
|
|
|
- ret.append(length)
|
|
|
- return ret
|
|
|
+ ret = []
|
|
|
|
|
|
- return ir
|
|
|
+ length_val = convert_to_push_expand_arr(ir, node, ret)
|
|
|
+ convert_to_push_set_val(ir, node, length_val, ret)
|
|
|
+
|
|
|
+ return ret
|
|
|
|
|
|
|
|
|
def convert_to_pop(ir, node):
|