mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into develop_060
This commit is contained in:
@@ -5,22 +5,22 @@
|
||||
|
||||
(func $main
|
||||
(local $_1 i64)
|
||||
(local $pos i64)
|
||||
(local $_2 i64)
|
||||
(local $_3 i64)
|
||||
(local $hi i64)
|
||||
(local $y i64)
|
||||
(local $hi_1 i64)
|
||||
(set_local $_1 (i64.const 0))
|
||||
(set_local $pos (call $u256_to_i32 (get_local $_1) (get_local $_1) (get_local $_1) (i64.const 64)))
|
||||
(set_local $_2 (i64.const 65280))
|
||||
(set_local $hi (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (get_local $_1) (i64.const 8)) (get_local $_2)) (i64.and (i64.shr_u (get_local $_1) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (get_local $_1) (i64.const 16)))) (i64.const 32)))
|
||||
(set_local $y (i64.or (get_local $hi) (call $endian_swap_32 (i64.shr_u (get_local $_1) (i64.const 32)))))
|
||||
(i64.store (get_local $pos) (get_local $y))
|
||||
(i64.store (i64.add (get_local $pos) (i64.const 8)) (get_local $y))
|
||||
(i64.store (i64.add (get_local $pos) (i64.const 16)) (get_local $y))
|
||||
(set_local $hi_1 (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (i64.const 64) (i64.const 8)) (get_local $_2)) (i64.and (i64.shr_u (i64.const 64) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (i64.const 64) (i64.const 16)))) (i64.const 32)))
|
||||
(i64.store (i64.add (get_local $pos) (i64.const 24)) (i64.or (get_local $hi_1) (call $endian_swap_32 (i64.shr_u (i64.const 64) (i64.const 32)))))
|
||||
(call $eth.revert (call $u256_to_i32 (get_local $_1) (get_local $_1) (get_local $_1) (get_local $_1)) (call $u256_to_i32 (get_local $_1) (get_local $_1) (get_local $_1) (get_local $_1)))
|
||||
(local.set $_1 (i64.const 0))
|
||||
(local.set $_2 (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 64)) (i64.const 64)))
|
||||
(local.set $_3 (i64.const 65280))
|
||||
(local.set $hi (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (local.get $_1) (i64.const 8)) (local.get $_3)) (i64.and (i64.shr_u (local.get $_1) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (local.get $_1) (i64.const 16)))) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $_1) (i64.const 32)))))
|
||||
(i64.store (i32.wrap_i64 (local.get $_2)) (local.get $y))
|
||||
(i64.store (i32.wrap_i64 (i64.add (local.get $_2) (i64.const 8))) (local.get $y))
|
||||
(i64.store (i32.wrap_i64 (i64.add (local.get $_2) (i64.const 16))) (local.get $y))
|
||||
(local.set $hi_1 (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (i64.const 128) (i64.const 8)) (local.get $_3)) (i64.and (i64.shr_u (i64.const 128) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (i64.const 128) (i64.const 16)))) (i64.const 32)))
|
||||
(i64.store (i32.wrap_i64 (i64.add (local.get $_2) (i64.const 24))) (i64.or (local.get $hi_1) (call $endian_swap_32 (i64.shr_u (i64.const 128) (i64.const 32)))))
|
||||
(call $eth.revert (i32.wrap_i64 (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))))
|
||||
)
|
||||
|
||||
(func $u256_to_i32
|
||||
@@ -30,20 +30,20 @@
|
||||
(param $x4 i64)
|
||||
(result i64)
|
||||
(local $v i64)
|
||||
(if (i64.ne (get_local $v) (i64.or (i64.or (get_local $x1) (get_local $x2)) (get_local $x3))) (then
|
||||
(if (i64.ne (i64.extend_i32_u (i64.ne (local.get $v) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then
|
||||
(unreachable)))
|
||||
(if (i64.ne (get_local $v) (i64.shr_u (get_local $x4) (i64.const 32))) (then
|
||||
(if (i64.ne (i64.extend_i32_u (i64.ne (local.get $v) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then
|
||||
(unreachable)))
|
||||
(set_local $v (get_local $x4))
|
||||
(get_local $v)
|
||||
(local.set $v (local.get $x4))
|
||||
(local.get $v)
|
||||
)
|
||||
|
||||
(func $endian_swap_16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(set_local $y (i64.or (i64.and (i64.shl (get_local $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (get_local $x) (i64.const 8)) (i64.const 255))))
|
||||
(get_local $y)
|
||||
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap_32
|
||||
@@ -51,9 +51,9 @@
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(set_local $hi (i64.shl (call $endian_swap_16 (get_local $x)) (i64.const 16)))
|
||||
(set_local $y (i64.or (get_local $hi) (call $endian_swap_16 (i64.shr_u (get_local $x) (i64.const 16)))))
|
||||
(get_local $y)
|
||||
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
)
|
||||
@@ -62,51 +62,26 @@
|
||||
(import \"ethereum\" \"finish\" (func $eth.finish (param i32 i32)))
|
||||
(memory $memory (export \"memory\") 1)
|
||||
(export \"main\" (func $main))
|
||||
(global $global_ (mut i64) (i64.const 0))
|
||||
(global $global__1 (mut i64) (i64.const 0))
|
||||
(global $global__2 (mut i64) (i64.const 0))
|
||||
|
||||
(func $main
|
||||
(local $_1 i64)
|
||||
(local $pos i64)
|
||||
(local $_2 i64)
|
||||
(local $hi i64)
|
||||
(local $y i64)
|
||||
(local $hi_1 i64)
|
||||
(local $hi_2 i64)
|
||||
(local $_2 i64)
|
||||
(local $_3 i64)
|
||||
(local $_4 i64)
|
||||
(local $_5 i64)
|
||||
(local $_6 i64)
|
||||
(local $_7 i64)
|
||||
(local $_8 i64)
|
||||
(local $_9 i64)
|
||||
(set_local $_1 (i64.const 0))
|
||||
(set_local $pos (call $u256_to_i32 (get_local $_1) (get_local $_1) (get_local $_1) (i64.const 64)))
|
||||
(set_local $hi (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (get_local $_1) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (get_local $_1) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (get_local $_1) (i64.const 16)))) (i64.const 32)))
|
||||
(set_local $y (i64.or (get_local $hi) (call $endian_swap_32 (i64.shr_u (get_local $_1) (i64.const 32)))))
|
||||
(i64.store (get_local $pos) (get_local $y))
|
||||
(i64.store (i64.add (get_local $pos) (i64.const 8)) (get_local $y))
|
||||
(i64.store (i64.add (get_local $pos) (i64.const 16)) (get_local $y))
|
||||
(set_local $hi_1 (i64.shl (call $endian_swap_16 (i64.const 64)) (i64.const 16)))
|
||||
(set_local $hi_2 (i64.shl (i64.or (get_local $hi_1) (call $endian_swap_16 (i64.shr_u (i64.const 64) (i64.const 16)))) (i64.const 32)))
|
||||
(i64.store (i64.add (get_local $pos) (i64.const 24)) (i64.or (get_local $hi_2) (call $endian_swap_32 (i64.shr_u (i64.const 64) (i64.const 32)))))
|
||||
(block
|
||||
(set_local $_2 (datasize \"C_2_deployed\"))
|
||||
(set_local $_3 (get_global $global_))
|
||||
(set_local $_4 (get_global $global__1))
|
||||
(set_local $_5 (get_global $global__2))
|
||||
|
||||
)
|
||||
(block
|
||||
(set_local $_6 (dataoffset \"C_2_deployed\"))
|
||||
(set_local $_7 (get_global $global_))
|
||||
(set_local $_8 (get_global $global__1))
|
||||
(set_local $_9 (get_global $global__2))
|
||||
|
||||
)
|
||||
(call $eth.codeCopy (call $u256_to_i32 (get_local $_1) (get_local $_1) (get_local $_1) (get_local $_1)) (call $u256_to_i32 (get_local $_6) (get_local $_7) (get_local $_8) (get_local $_9)) (call $u256_to_i32 (get_local $_2) (get_local $_3) (get_local $_4) (get_local $_5)))
|
||||
(call $eth.finish (call $u256_to_i32 (get_local $_1) (get_local $_1) (get_local $_1) (get_local $_1)) (call $u256_to_i32 (get_local $_2) (get_local $_3) (get_local $_4) (get_local $_5)))
|
||||
(local.set $_1 (i64.const 0))
|
||||
(local.set $_2 (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 64)) (i64.const 64)))
|
||||
(local.set $hi (i64.shl (i64.or (i64.shl (i64.or (i64.and (i64.shl (local.get $_1) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $_1) (i64.const 8)) (i64.const 255))) (i64.const 16)) (call $endian_swap_16 (i64.shr_u (local.get $_1) (i64.const 16)))) (i64.const 32)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $_1) (i64.const 32)))))
|
||||
(i64.store (i32.wrap_i64 (local.get $_2)) (local.get $y))
|
||||
(i64.store (i32.wrap_i64 (i64.add (local.get $_2) (i64.const 8))) (local.get $y))
|
||||
(i64.store (i32.wrap_i64 (i64.add (local.get $_2) (i64.const 16))) (local.get $y))
|
||||
(local.set $hi_1 (i64.shl (call $endian_swap_32 (i64.const 128)) (i64.const 32)))
|
||||
(i64.store (i32.wrap_i64 (i64.add (local.get $_2) (i64.const 24))) (i64.or (local.get $hi_1) (call $endian_swap_32 (i64.shr_u (i64.const 128) (i64.const 32)))))
|
||||
(local.set $_3 (datasize \"C_2_deployed\"))
|
||||
(call $eth.codeCopy (i32.wrap_i64 (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\"))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))))
|
||||
(call $eth.finish (i32.wrap_i64 (i64.add (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (i64.const 64))) (i32.wrap_i64 (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))))
|
||||
)
|
||||
|
||||
(func $u256_to_i32
|
||||
@@ -116,20 +91,20 @@
|
||||
(param $x4 i64)
|
||||
(result i64)
|
||||
(local $v i64)
|
||||
(if (i64.ne (get_local $v) (i64.or (i64.or (get_local $x1) (get_local $x2)) (get_local $x3))) (then
|
||||
(if (i64.ne (i64.extend_i32_u (i64.ne (local.get $v) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3)))) (i64.const 0)) (then
|
||||
(unreachable)))
|
||||
(if (i64.ne (get_local $v) (i64.shr_u (get_local $x4) (i64.const 32))) (then
|
||||
(if (i64.ne (i64.extend_i32_u (i64.ne (local.get $v) (i64.shr_u (local.get $x4) (i64.const 32)))) (i64.const 0)) (then
|
||||
(unreachable)))
|
||||
(set_local $v (get_local $x4))
|
||||
(get_local $v)
|
||||
(local.set $v (local.get $x4))
|
||||
(local.get $v)
|
||||
)
|
||||
|
||||
(func $endian_swap_16
|
||||
(param $x i64)
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(set_local $y (i64.or (i64.and (i64.shl (get_local $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (get_local $x) (i64.const 8)) (i64.const 255))))
|
||||
(get_local $y)
|
||||
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
(func $endian_swap_32
|
||||
@@ -137,9 +112,9 @@
|
||||
(result i64)
|
||||
(local $y i64)
|
||||
(local $hi i64)
|
||||
(set_local $hi (i64.shl (call $endian_swap_16 (get_local $x)) (i64.const 16)))
|
||||
(set_local $y (i64.or (get_local $hi) (call $endian_swap_16 (i64.shr_u (get_local $x) (i64.const 16)))))
|
||||
(get_local $y)
|
||||
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
|
||||
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
|
||||
(local.get $y)
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
@@ -11,6 +11,4 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (90-97): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (115-122): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (130-149): Assertion violation happens here
|
||||
|
||||
@@ -11,6 +11,4 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (92-102): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (120-130): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (138-160): Assertion violation happens here
|
||||
|
||||
@@ -13,7 +13,3 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (90-97): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (115-122): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (138-145): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (153-172): Assertion violation happens here
|
||||
|
||||
@@ -13,7 +13,3 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (92-102): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (120-130): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (146-156): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (164-186): Assertion violation happens here
|
||||
|
||||
@@ -17,15 +17,15 @@ contract C
|
||||
// Warning: (124-130): Assertion checker does not yet support this expression.
|
||||
// Warning: (124-128): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (124-133): Assertion checker does not yet implement this expression.
|
||||
// Warning: (124-136): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (124-136): Assertion checker does not yet implement this expression.
|
||||
// Warning: (154-160): Assertion checker does not yet support this expression.
|
||||
// Warning: (154-158): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (154-163): Assertion checker does not yet implement this expression.
|
||||
// Warning: (154-166): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (154-166): Assertion checker does not yet implement this expression.
|
||||
// Warning: (182-188): Assertion checker does not yet support this expression.
|
||||
// Warning: (182-186): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (182-191): Assertion checker does not yet implement this expression.
|
||||
// Warning: (182-194): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (182-194): Assertion checker does not yet implement this expression.
|
||||
// Warning: (209-215): Assertion checker does not yet support this expression.
|
||||
// Warning: (209-213): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (209-218): Assertion checker does not yet implement this expression.
|
||||
|
||||
@@ -10,5 +10,3 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (134-145): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (154-178): Assertion violation happens here
|
||||
|
||||
@@ -10,5 +10,4 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (134-145): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (154-178): Assertion violation happens here
|
||||
|
||||
@@ -10,5 +10,3 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (152-167): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (176-204): Assertion violation happens here
|
||||
|
||||
@@ -10,5 +10,4 @@ contract C
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (152-167): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (176-204): Assertion violation happens here
|
||||
|
||||
@@ -19,15 +19,15 @@ contract C
|
||||
// Warning: (117-120): Assertion checker does not yet support this expression.
|
||||
// Warning: (117-118): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (117-123): Assertion checker does not yet implement this expression.
|
||||
// Warning: (117-126): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (117-126): Assertion checker does not yet implement this expression.
|
||||
// Warning: (144-147): Assertion checker does not yet support this expression.
|
||||
// Warning: (144-145): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (144-150): Assertion checker does not yet implement this expression.
|
||||
// Warning: (144-153): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (144-153): Assertion checker does not yet implement this expression.
|
||||
// Warning: (169-172): Assertion checker does not yet support this expression.
|
||||
// Warning: (169-170): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (169-175): Assertion checker does not yet implement this expression.
|
||||
// Warning: (169-178): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (169-178): Assertion checker does not yet implement this expression.
|
||||
// Warning: (193-196): Assertion checker does not yet support this expression.
|
||||
// Warning: (193-194): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (193-199): Assertion checker does not yet implement this expression.
|
||||
|
||||
@@ -18,15 +18,15 @@ contract C
|
||||
// Warning: (124-127): Assertion checker does not yet support this expression.
|
||||
// Warning: (124-125): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (124-130): Assertion checker does not yet implement this expression.
|
||||
// Warning: (124-136): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (124-136): Assertion checker does not yet implement this expression.
|
||||
// Warning: (154-157): Assertion checker does not yet support this expression.
|
||||
// Warning: (154-155): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (154-160): Assertion checker does not yet implement this expression.
|
||||
// Warning: (154-166): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (154-166): Assertion checker does not yet implement this expression.
|
||||
// Warning: (182-185): Assertion checker does not yet support this expression.
|
||||
// Warning: (182-183): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (182-188): Assertion checker does not yet implement this expression.
|
||||
// Warning: (182-194): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays.
|
||||
// Warning: (182-194): Assertion checker does not yet implement this expression.
|
||||
// Warning: (209-212): Assertion checker does not yet support this expression.
|
||||
// Warning: (209-210): Assertion checker does not yet implement type struct C.S memory
|
||||
// Warning: (209-215): Assertion checker does not yet implement this expression.
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <libyul/optimiser/DeadCodeEliminator.h>
|
||||
#include <libyul/optimiser/Disambiguator.h>
|
||||
#include <libyul/optimiser/CallGraphGenerator.h>
|
||||
#include <libyul/optimiser/ConditionalUnsimplifier.h>
|
||||
#include <libyul/optimiser/ConditionalSimplifier.h>
|
||||
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
||||
#include <libyul/optimiser/NameCollector.h>
|
||||
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
||||
@@ -157,6 +159,16 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
|
||||
disambiguate();
|
||||
CommonSubexpressionEliminator::run(*m_context, *m_ast);
|
||||
}
|
||||
else if (m_optimizerStep == "conditionalUnsimplifier")
|
||||
{
|
||||
disambiguate();
|
||||
ConditionalUnsimplifier::run(*m_context, *m_ast);
|
||||
}
|
||||
else if (m_optimizerStep == "conditionalSimplifier")
|
||||
{
|
||||
disambiguate();
|
||||
ConditionalSimplifier::run(*m_context, *m_ast);
|
||||
}
|
||||
else if (m_optimizerStep == "expressionSplitter")
|
||||
ExpressionSplitter::run(*m_context, *m_ast);
|
||||
else if (m_optimizerStep == "expressionJoiner")
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
let y := mload(0x20)
|
||||
for {} and(y, 8) { pop(y) } {
|
||||
if y { break }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let y := mload(0x20)
|
||||
// for { } and(y, 8) { pop(y) }
|
||||
// {
|
||||
// if y { break }
|
||||
// y := 0
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
let y := mload(0x20)
|
||||
for {} and(y, 8) { pop(y) } {
|
||||
if y { continue }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let y := mload(0x20)
|
||||
// for { } and(y, 8) { pop(y) }
|
||||
// {
|
||||
// if y { continue }
|
||||
// y := 0
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
let y := mload(0)
|
||||
if x { revert(0, 0) }
|
||||
if y { revert(0, 0) }
|
||||
for {} and(x, y) {} {
|
||||
x := 2
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// let y := mload(0)
|
||||
// if x { revert(0, 0) }
|
||||
// x := 0
|
||||
// if y { revert(0, 0) }
|
||||
// y := 0
|
||||
// for { } and(x, y) { }
|
||||
// { x := 2 }
|
||||
// }
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
let x
|
||||
for {} x { sstore(1, x) } {
|
||||
if x { continue }
|
||||
// x is 0 here, but should not be 0
|
||||
// anymore in the for loop post block
|
||||
sstore(0, x)
|
||||
}
|
||||
sstore(0, x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x
|
||||
// for { } x { sstore(1, x) }
|
||||
// {
|
||||
// if x { continue }
|
||||
// x := 0
|
||||
// sstore(0, x)
|
||||
// }
|
||||
// sstore(0, x)
|
||||
// }
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
for {} 1 {} {
|
||||
if x { sstore(7, 8) break sstore(8, 9) }
|
||||
sstore(1, x)
|
||||
if x { sstore(7, 8) break }
|
||||
sstore(10, x)
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// for { } 1 { }
|
||||
// {
|
||||
// if x
|
||||
// {
|
||||
// sstore(7, 8)
|
||||
// break
|
||||
// sstore(8, 9)
|
||||
// }
|
||||
// sstore(1, x)
|
||||
// if x
|
||||
// {
|
||||
// sstore(7, 8)
|
||||
// break
|
||||
// }
|
||||
// x := 0
|
||||
// sstore(10, x)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
if x { sstore(0, x) }
|
||||
sstore(1, x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// if x { sstore(0, x) }
|
||||
// sstore(1, x)
|
||||
// }
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
if x { sstore(0, x) revert(0, 0) }
|
||||
sstore(1, x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// if x
|
||||
// {
|
||||
// sstore(0, x)
|
||||
// revert(0, 0)
|
||||
// }
|
||||
// x := 0
|
||||
// sstore(1, x)
|
||||
// }
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
let x := calldataload(0)
|
||||
switch x
|
||||
case 0 { }
|
||||
case 1 { }
|
||||
default { }
|
||||
|
||||
pop(x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := calldataload(0)
|
||||
// switch x
|
||||
// case 0 { x := 0 }
|
||||
// case 1 { x := 1 }
|
||||
// default { }
|
||||
// pop(x)
|
||||
// }
|
||||
@@ -0,0 +1,5 @@
|
||||
{ }
|
||||
// ====
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// { }
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
let y := mload(0x20)
|
||||
for {} and(y, 8) { pop(y) } {
|
||||
if y { break }
|
||||
y := 0
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let y := mload(0x20)
|
||||
// for { } and(y, 8) { pop(y) }
|
||||
// { if y { break } }
|
||||
// }
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
let y := mload(0x20)
|
||||
for {} and(y, 8) { pop(y) } {
|
||||
if y { continue }
|
||||
y := 0
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let y := mload(0x20)
|
||||
// for { } and(y, 8) { pop(y) }
|
||||
// { if y { continue } }
|
||||
// }
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
let y := mload(0)
|
||||
if x { revert(0, 0) }
|
||||
x := 0
|
||||
if y { revert(0, 0) }
|
||||
y := 0
|
||||
for {} and(x, y) {} {
|
||||
x := 2
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// let y := mload(0)
|
||||
// if x { revert(0, 0) }
|
||||
// if y { revert(0, 0) }
|
||||
// for { } and(x, y) { }
|
||||
// { x := 2 }
|
||||
// }
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
let x
|
||||
for {} x { sstore(1, x) } {
|
||||
if x { continue }
|
||||
x := 0
|
||||
sstore(0, x)
|
||||
}
|
||||
sstore(0, x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x
|
||||
// for { } x { sstore(1, x) }
|
||||
// {
|
||||
// if x { continue }
|
||||
// sstore(0, x)
|
||||
// }
|
||||
// sstore(0, x)
|
||||
// }
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
for {} 1 {} {
|
||||
if x { sstore(7, 8) break sstore(8, 9) }
|
||||
x := 0
|
||||
sstore(1, x)
|
||||
if x { sstore(7, 8) break }
|
||||
x := 0
|
||||
sstore(10, x)
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// for { } 1 { }
|
||||
// {
|
||||
// if x
|
||||
// {
|
||||
// sstore(7, 8)
|
||||
// break
|
||||
// sstore(8, 9)
|
||||
// }
|
||||
// x := 0
|
||||
// sstore(1, x)
|
||||
// if x
|
||||
// {
|
||||
// sstore(7, 8)
|
||||
// break
|
||||
// }
|
||||
// sstore(10, x)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
if x { sstore(0, x) }
|
||||
x := 0
|
||||
sstore(1, x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// if x { sstore(0, x) }
|
||||
// x := 0
|
||||
// sstore(1, x)
|
||||
// }
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
let x := mload(0)
|
||||
if x { sstore(0, x) revert(0, 0) }
|
||||
x := 0
|
||||
sstore(1, x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := mload(0)
|
||||
// if x
|
||||
// {
|
||||
// sstore(0, x)
|
||||
// revert(0, 0)
|
||||
// }
|
||||
// sstore(1, x)
|
||||
// }
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
let x := calldataload(0)
|
||||
switch x
|
||||
case 0 { x := 0 }
|
||||
case 1 { x := 1 }
|
||||
case 2 { x := 8 /* wrong literal */ }
|
||||
default { }
|
||||
|
||||
pop(x)
|
||||
}
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// {
|
||||
// let x := calldataload(0)
|
||||
// switch x
|
||||
// case 0 { }
|
||||
// case 1 { }
|
||||
// case 2 { x := 8 }
|
||||
// default { }
|
||||
// pop(x)
|
||||
// }
|
||||
@@ -0,0 +1,5 @@
|
||||
{ }
|
||||
// ====
|
||||
// step: conditionalUnsimplifier
|
||||
// ----
|
||||
// { }
|
||||
@@ -17,8 +17,8 @@
|
||||
// { }
|
||||
// for { } 0 { }
|
||||
// { }
|
||||
// for { } 1 { }
|
||||
// { if iszero(a) { break } }
|
||||
// for { } a { }
|
||||
// { }
|
||||
// for { } 1 { }
|
||||
// {
|
||||
// if iszero(add(a, a)) { break }
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
let y := mload(0x20)
|
||||
for {} and(y, 8) { if y { revert(0, 0) } } {
|
||||
if y { continue }
|
||||
sstore(1, y)
|
||||
}
|
||||
if y { revert(0, 0) }
|
||||
}
|
||||
// ====
|
||||
// step: fullSuite
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
// let y := mload(0x20)
|
||||
// for { } and(y, 8) { if y { revert(0, 0) } }
|
||||
// {
|
||||
// if y { continue }
|
||||
// sstore(1, 0)
|
||||
// }
|
||||
// if y { revert(0, 0) }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
sstore(0, array_sum(calldataload(0)))
|
||||
|
||||
function array_sum(x) -> sum {
|
||||
let length := calldataload(x)
|
||||
for { let i := 0 } lt(i, length) { i := add(i, 1) } {
|
||||
sum := add(sum, array_load(x, i))
|
||||
}
|
||||
}
|
||||
function array_load(x, i) -> v {
|
||||
let len := calldataload(x)
|
||||
if iszero(lt(i, len)) { revert(0, 0) }
|
||||
let data := add(x, 0x20)
|
||||
v := calldataload(add(data, mul(i, 0x20)))
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: fullSuite
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
// let _1 := calldataload(0)
|
||||
// let sum := 0
|
||||
// let i := sum
|
||||
// for { } lt(i, calldataload(_1)) { i := add(i, 1) }
|
||||
// {
|
||||
// sum := add(sum, calldataload(add(add(_1, mul(i, 0x20)), 0x20)))
|
||||
// }
|
||||
// sstore(0, sum)
|
||||
// }
|
||||
// }
|
||||
@@ -21,10 +21,10 @@
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
// let _1 := mload(0x40)
|
||||
// mstore(0x40, add(_1, 0x20))
|
||||
// mstore(0x40, add(_1, 96))
|
||||
// mstore(add(_1, 128), 2)
|
||||
// let p := mload(0x40)
|
||||
// mstore(0x40, add(p, 0x20))
|
||||
// mstore(0x40, add(p, 96))
|
||||
// mstore(add(p, 128), 2)
|
||||
// mstore(0x40, 0x20)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -17,30 +17,6 @@
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
// Flattened specification of array dimension
|
||||
// If is_static is false, and this array dimension is contained
|
||||
// inside another dimension e.g., x[][2] ([2] being the outer dimension)
|
||||
// then `length` for this dimension is the length of the first dynamically
|
||||
// sized array. The other (n-1) lengths are unspecified
|
||||
message ArrayDimensionInfo {
|
||||
required uint32 length = 1;
|
||||
required bool is_static = 2;
|
||||
}
|
||||
|
||||
// TODO: Add more base types
|
||||
// See https://github.com/ethereum/solidity/issues/6749
|
||||
message ArrayType {
|
||||
oneof base_type_oneof {
|
||||
IntegerType inty = 1;
|
||||
FixedByteType byty = 2;
|
||||
AddressType adty = 3;
|
||||
StructType stty = 4;
|
||||
BoolType boolty = 5;
|
||||
DynamicByteArrayType dynbytesty = 6;
|
||||
}
|
||||
repeated ArrayDimensionInfo info = 7;
|
||||
}
|
||||
|
||||
// bool
|
||||
message BoolType {}
|
||||
|
||||
@@ -78,6 +54,16 @@ message DynamicByteArrayType {
|
||||
required DType type = 1;
|
||||
}
|
||||
|
||||
message ArrayType {
|
||||
required Type t = 1;
|
||||
required uint32 length = 2;
|
||||
required bool is_static = 3;
|
||||
}
|
||||
|
||||
message StructType {
|
||||
repeated Type t = 1;
|
||||
}
|
||||
|
||||
message NonValueType {
|
||||
oneof nonvalue_type_oneof {
|
||||
DynamicByteArrayType dynbytearray = 1;
|
||||
@@ -86,6 +72,8 @@ message NonValueType {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add more types
|
||||
// See https://github.com/ethereum/solidity/issues/6749
|
||||
message Type {
|
||||
oneof type_oneof {
|
||||
ValueType vtype = 1;
|
||||
@@ -93,9 +81,6 @@ message Type {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This must not reference itself either directly or indirectly
|
||||
message StructType {}
|
||||
|
||||
message VarDecl {
|
||||
required Type type = 1;
|
||||
}
|
||||
|
||||
+825
-731
File diff suppressed because it is too large
Load Diff
+579
-201
@@ -1,10 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <test/tools/ossfuzz/abiV2Proto.pb.h>
|
||||
|
||||
#include <libdevcore/FixedHash.h>
|
||||
#include <libdevcore/Keccak256.h>
|
||||
#include <libdevcore/StringUtils.h>
|
||||
#include <libdevcore/Whiskers.h>
|
||||
#include <test/tools/ossfuzz/abiV2Proto.pb.h>
|
||||
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
@@ -95,6 +103,8 @@ namespace test
|
||||
{
|
||||
namespace abiv2fuzzer
|
||||
{
|
||||
/// Converts a protobuf input into a Solidity program that tests
|
||||
/// abi coding.
|
||||
class ProtoConverter
|
||||
{
|
||||
public:
|
||||
@@ -103,101 +113,109 @@ public:
|
||||
m_counter(0),
|
||||
m_varCounter(0),
|
||||
m_returnValue(1),
|
||||
m_isLastDynParamRightPadded(false)
|
||||
m_isLastDynParamRightPadded(false),
|
||||
m_structCounter(0),
|
||||
m_numStructsAdded(0)
|
||||
{}
|
||||
|
||||
ProtoConverter(ProtoConverter const&) = delete;
|
||||
|
||||
ProtoConverter(ProtoConverter&&) = delete;
|
||||
|
||||
std::string contractToString(Contract const& _input);
|
||||
|
||||
private:
|
||||
using VecOfBoolUnsigned = std::vector<std::pair<bool, unsigned>>;
|
||||
|
||||
enum class Delimiter
|
||||
{
|
||||
ADD,
|
||||
SKIP
|
||||
};
|
||||
/// Enum of possible function types that decode abi
|
||||
/// encoded parameters.
|
||||
enum class CalleeType
|
||||
{
|
||||
PUBLIC,
|
||||
EXTERNAL
|
||||
};
|
||||
enum class DataType
|
||||
{
|
||||
BYTES,
|
||||
STRING,
|
||||
VALUE,
|
||||
ARRAY
|
||||
};
|
||||
|
||||
void visit(BoolType const&);
|
||||
|
||||
void visit(IntegerType const&);
|
||||
|
||||
void visit(FixedByteType const&);
|
||||
|
||||
void visit(AddressType const&);
|
||||
|
||||
void visit(ArrayType const&);
|
||||
|
||||
void visit(DynamicByteArrayType const&);
|
||||
|
||||
void visit(StructType const&);
|
||||
|
||||
void visit(ValueType const&);
|
||||
|
||||
void visit(NonValueType const&);
|
||||
|
||||
void visit(Type const&);
|
||||
|
||||
void visit(VarDecl const&);
|
||||
|
||||
void visit(TestFunction const&);
|
||||
|
||||
/// Visitors for various Protobuf types
|
||||
/// Visit top-level contract specification
|
||||
void visit(Contract const&);
|
||||
|
||||
std::string getValueByBaseType(ArrayType const&);
|
||||
/// Convert test function specification into Solidity test
|
||||
/// function
|
||||
/// @param _testSpec: Protobuf test function specification
|
||||
/// @param _storageDefs: String containing Solidity assignment
|
||||
/// statements to be placed inside the scope of the test function.
|
||||
std::string visit(TestFunction const& _testSpec, std::string const& _storageDefs);
|
||||
|
||||
DataType getDataTypeByBaseType(ArrayType const& _x);
|
||||
/// Visitors for the remaining protobuf types. They convert
|
||||
/// the input protobuf specification type into Solidity code.
|
||||
/// @return A pair of strings, first of which contains Solidity
|
||||
/// code to be placed inside contract scope, second of which contains
|
||||
/// Solidity code to be placed inside test function scope.
|
||||
std::pair<std::string, std::string> visit(VarDecl const&);
|
||||
std::pair<std::string, std::string> visit(Type const&);
|
||||
std::pair<std::string, std::string> visit(ValueType const&);
|
||||
std::pair<std::string, std::string> visit(NonValueType const&);
|
||||
std::pair<std::string, std::string> visit(BoolType const&);
|
||||
std::pair<std::string, std::string> visit(IntegerType const&);
|
||||
std::pair<std::string, std::string> visit(FixedByteType const&);
|
||||
std::pair<std::string, std::string> visit(AddressType const&);
|
||||
std::pair<std::string, std::string> visit(DynamicByteArrayType const&);
|
||||
std::pair<std::string, std::string> visit(ArrayType const&);
|
||||
std::pair<std::string, std::string> visit(StructType const&);
|
||||
|
||||
void resizeInitArray(
|
||||
ArrayType const& _x,
|
||||
std::string const& _baseType,
|
||||
std::string const& _varName,
|
||||
std::string const& _paramName
|
||||
);
|
||||
/// Convert a protobuf type @a _T into Solidity code to be placed
|
||||
/// inside contract and test function scopes.
|
||||
/// @param: _type (of parameterized type protobuf type T) is the type
|
||||
/// of protobuf input to be converted.
|
||||
/// @param: _isValueType is true if _type is a Solidity value type e.g., uint
|
||||
/// and false otherwise e.g., string
|
||||
/// @return: A pair of strings, first of which contains Solidity
|
||||
/// code to be placed inside contract scope, second of which contains
|
||||
/// Solidity code to be placed inside test function scope.
|
||||
template <typename T>
|
||||
std::pair<std::string, std::string> processType(T const& _type, bool _isValueType);
|
||||
|
||||
unsigned resizeDimension(
|
||||
bool _isStatic,
|
||||
unsigned _arrayLen,
|
||||
std::string const& _var,
|
||||
std::string const& _param,
|
||||
std::string const& _type
|
||||
);
|
||||
|
||||
void resizeHelper(
|
||||
ArrayType const& _x,
|
||||
std::vector<std::string> _arrStrVec,
|
||||
VecOfBoolUnsigned _arrInfoVec,
|
||||
std::string const& _varName,
|
||||
std::string const& _paramName
|
||||
);
|
||||
|
||||
// Utility functions
|
||||
void appendChecks(DataType _type, std::string const& _varName, std::string const& _rhs);
|
||||
|
||||
void addVarDef(std::string const& _varName, std::string const& _rhs);
|
||||
|
||||
void addCheckedVarDef(
|
||||
DataType _type,
|
||||
/// Convert a protobuf type @a _T into Solidity variable assignment and check
|
||||
/// statements to be placed inside contract and test function scopes.
|
||||
/// @param: _varName is the name of the Solidity variable
|
||||
/// @param: _paramName is the name of the Solidity parameter that is passed
|
||||
/// to the test function
|
||||
/// @param: _type (of parameterized type protobuf type T) is the type
|
||||
/// of protobuf input to be converted.
|
||||
/// @return: A pair of strings, first of which contains Solidity
|
||||
/// statements to be placed inside contract scope, second of which contains
|
||||
/// Solidity statements to be placed inside test function scope.
|
||||
template <typename T>
|
||||
std::pair<std::string, std::string> assignChecker(
|
||||
std::string const& _varName,
|
||||
std::string const& _paramName,
|
||||
std::string const& _rhs
|
||||
T _type
|
||||
);
|
||||
|
||||
/// Convert a protobuf type @a _T into Solidity variable declaration statement.
|
||||
/// @param: _varName is the name of the Solidity variable
|
||||
/// @param: _paramName is the name of the Solidity parameter that is passed
|
||||
/// to the test function
|
||||
/// @param: _type (of parameterized type protobuf type T) is the type
|
||||
/// of protobuf input to be converted.
|
||||
/// @param: _isValueType is a boolean that is true if _type is a
|
||||
/// Solidity value type e.g., uint and false otherwise e.g., string
|
||||
/// @param: _location is the Solidity location qualifier string to
|
||||
/// be used inside variable declaration statements
|
||||
/// @return: A pair of strings, first of which contains Solidity
|
||||
/// variable declaration statement to be placed inside contract scope,
|
||||
/// second of which contains Solidity variable declaration statement
|
||||
/// to be placed inside test function scope.
|
||||
template <typename T>
|
||||
std::pair<std::string, std::string> varDecl(
|
||||
std::string const& _varName,
|
||||
std::string const& _paramName,
|
||||
T _type,
|
||||
bool _isValueType,
|
||||
std::string const& _location
|
||||
);
|
||||
|
||||
/// Appends a function parameter to the function parameter stream.
|
||||
void appendTypedParams(
|
||||
CalleeType _calleeType,
|
||||
bool _isValueType,
|
||||
@@ -206,6 +224,8 @@ private:
|
||||
Delimiter _delimiter
|
||||
);
|
||||
|
||||
/// Appends a function parameter to the public test function's
|
||||
/// parameter stream.
|
||||
void appendTypedParamsPublic(
|
||||
bool _isValueType,
|
||||
std::string const& _typeString,
|
||||
@@ -213,6 +233,8 @@ private:
|
||||
Delimiter _delimiter = Delimiter::ADD
|
||||
);
|
||||
|
||||
/// Appends a function parameter to the external test function's
|
||||
/// parameter stream.
|
||||
void appendTypedParamsExternal(
|
||||
bool _isValueType,
|
||||
std::string const& _typeString,
|
||||
@@ -220,48 +242,42 @@ private:
|
||||
Delimiter _delimiter = Delimiter::ADD
|
||||
);
|
||||
|
||||
void appendVarDeclToOutput(
|
||||
/// Returns a Solidity variable declaration statement
|
||||
/// @param _type: string containing Solidity type of the
|
||||
/// variable to be declared.
|
||||
/// @param _varName: string containing Solidity variable
|
||||
/// name
|
||||
/// @param _qualifier: string containing location where
|
||||
/// the variable will be placed
|
||||
std::string getVarDecl(
|
||||
std::string const& _type,
|
||||
std::string const& _varName,
|
||||
std::string const& _qualifier
|
||||
);
|
||||
|
||||
void checkResizeOp(std::string const& _varName, unsigned _len);
|
||||
|
||||
void visitType(DataType _dataType, std::string const& _type, std::string const& _value);
|
||||
|
||||
void visitArrayType(std::string const&, ArrayType const&);
|
||||
|
||||
void createDeclAndParamList(
|
||||
std::string const& _type,
|
||||
DataType _dataType,
|
||||
std::string& _varName,
|
||||
std::string& _paramName
|
||||
);
|
||||
|
||||
/// Return checks that are encoded as Solidity if statements
|
||||
/// as string
|
||||
std::string equalityChecksAsString();
|
||||
|
||||
/// Return comma separated typed function parameters as string
|
||||
std::string typedParametersAsString(CalleeType _calleeType);
|
||||
|
||||
void writeHelperFunctions();
|
||||
/// Return Solidity helper functions as string
|
||||
std::string helperFunctions();
|
||||
|
||||
// Function definitions
|
||||
// m_counter is used to derive values for typed variables
|
||||
unsigned getNextCounter()
|
||||
{
|
||||
return m_counter++;
|
||||
}
|
||||
/// Return top-level test code as string
|
||||
std::string testCode(unsigned _invalidLength);
|
||||
|
||||
// m_varCounter is used to derive declared and parameterized variable names
|
||||
/// Return the next variable count that is used for
|
||||
/// variable naming.
|
||||
unsigned getNextVarCounter()
|
||||
{
|
||||
return m_varCounter++;
|
||||
}
|
||||
|
||||
// Accepts an unsigned counter and returns a pair of strings
|
||||
// First string is declared name (s_varNamePrefix<varcounter_value>)
|
||||
// Second string is parameterized name (s_paramPrefix<varcounter_value>)
|
||||
auto newVarNames(unsigned _varCounter)
|
||||
/// Return a pair of names for Solidity variable and the same variable when
|
||||
/// passed as a function parameter.
|
||||
static std::pair<std::string, std::string> newVarNames(unsigned _varCounter)
|
||||
{
|
||||
return std::make_pair(
|
||||
s_varNamePrefix + std::to_string(_varCounter),
|
||||
@@ -269,62 +285,80 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
std::string getQualifier(DataType _dataType)
|
||||
{
|
||||
return ((isValueType(_dataType) || m_isStateVar) ? "" : "memory");
|
||||
}
|
||||
|
||||
/// Checks if the last dynamically encoded Solidity type is right
|
||||
/// padded, returning true if it is and false otherwise.
|
||||
bool isLastDynParamRightPadded()
|
||||
{
|
||||
return m_isLastDynParamRightPadded;
|
||||
}
|
||||
|
||||
// Static declarations
|
||||
static std::string structTypeAsString(StructType const& _x);
|
||||
static std::string boolValueAsString(unsigned _counter);
|
||||
static std::string intValueAsString(unsigned _width, unsigned _counter);
|
||||
static std::string uintValueAsString(unsigned _width, unsigned _counter);
|
||||
static std::string integerValueAsString(bool _sign, unsigned _width, unsigned _counter);
|
||||
static std::string addressValueAsString(unsigned _counter);
|
||||
static std::string fixedByteValueAsString(unsigned _width, unsigned _counter);
|
||||
|
||||
/// Returns a hex literal if _isHexLiteral is true, a string literal otherwise.
|
||||
/// The size of the returned literal is _numBytes bytes.
|
||||
/// @param _decorate If true, the returned string is enclosed within double quotes
|
||||
/// if _isHexLiteral is false.
|
||||
/// @param _isHexLiteral If true, the returned string is enclosed within
|
||||
/// double quotes prefixed by the string "hex" if _decorate is true. If
|
||||
/// _decorate is false, the returned string is returned as-is.
|
||||
/// @return hex value as string
|
||||
static std::string hexValueAsString(
|
||||
unsigned _numBytes,
|
||||
unsigned _counter,
|
||||
bool _isHexLiteral,
|
||||
bool _decorate = true
|
||||
);
|
||||
|
||||
/// Concatenates the hash value obtained from monotonically increasing counter
|
||||
/// until the desired number of bytes determined by _numBytes.
|
||||
/// @param _width Desired number of bytes for hex value
|
||||
/// @param _counter A counter value used for creating a keccak256 hash
|
||||
/// @param _isHexLiteral Since this routine may be used to construct
|
||||
/// string or hex literals, this flag is used to construct a valid output.
|
||||
/// @return Valid hex or string literal of size _width bytes
|
||||
static std::string variableLengthValueAsString(
|
||||
unsigned _width,
|
||||
unsigned _counter,
|
||||
bool _isHexLiteral
|
||||
);
|
||||
static std::vector<std::pair<bool, unsigned>> arrayDimensionsAsPairVector(ArrayType const& _x);
|
||||
static std::string arrayDimInfoAsString(ArrayDimensionInfo const& _x);
|
||||
static void arrayDimensionsAsStringVector(
|
||||
ArrayType const& _x,
|
||||
std::vector<std::string>&
|
||||
);
|
||||
static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x);
|
||||
static std::string arrayTypeAsString(std::string const&, ArrayType const&);
|
||||
/// Convert delimter to a comma or null string.
|
||||
static std::string delimiterToString(Delimiter _delimiter);
|
||||
static std::string croppedString(unsigned _numBytes, unsigned _counter, bool _isHexLiteral);
|
||||
|
||||
/// Contains the test program
|
||||
std::ostringstream m_output;
|
||||
/// Contains a subset of the test program. This subset contains
|
||||
/// checks to be encoded in the test program
|
||||
std::ostringstream m_checks;
|
||||
/// Contains typed parameter list to be passed to callee functions
|
||||
std::ostringstream m_typedParamsExternal;
|
||||
std::ostringstream m_typedParamsPublic;
|
||||
/// Predicate that is true if we are in contract scope
|
||||
bool m_isStateVar;
|
||||
unsigned m_counter;
|
||||
unsigned m_varCounter;
|
||||
/// Monotonically increasing return value for error reporting
|
||||
unsigned m_returnValue;
|
||||
/// Flag that indicates if last dynamically encoded parameter
|
||||
/// passed to a function call is of a type that is going to be
|
||||
/// right padded by the ABI encoder.
|
||||
bool m_isLastDynParamRightPadded;
|
||||
/// Struct counter
|
||||
unsigned m_structCounter;
|
||||
unsigned m_numStructsAdded;
|
||||
/// Prefixes for declared and parameterized variable names
|
||||
static auto constexpr s_varNamePrefix = "x_";
|
||||
static auto constexpr s_paramNamePrefix = "c_";
|
||||
};
|
||||
|
||||
/// Visitor interface for Solidity protobuf types.
|
||||
template <typename T>
|
||||
class AbiV2ProtoVisitor
|
||||
{
|
||||
public:
|
||||
static unsigned constexpr s_maxArrayDimensions = 3;
|
||||
virtual ~AbiV2ProtoVisitor() = default;
|
||||
|
||||
virtual T visit(BoolType const& _node) = 0;
|
||||
virtual T visit(IntegerType const& _node) = 0;
|
||||
virtual T visit(FixedByteType const& _node) = 0;
|
||||
virtual T visit(AddressType const& _node) = 0;
|
||||
virtual T visit(DynamicByteArrayType const& _node) = 0;
|
||||
virtual T visit(ArrayType const& _node) = 0;
|
||||
virtual T visit(StructType const& _node) = 0;
|
||||
virtual T visit(ValueType const& _node)
|
||||
{
|
||||
return visitValueType(_node);
|
||||
}
|
||||
virtual T visit(NonValueType const& _node)
|
||||
{
|
||||
return visitNonValueType(_node);
|
||||
}
|
||||
virtual T visit(Type const& _node)
|
||||
{
|
||||
return visitType(_node);
|
||||
}
|
||||
|
||||
enum class DataType
|
||||
{
|
||||
BYTES,
|
||||
STRING,
|
||||
VALUE,
|
||||
ARRAY
|
||||
};
|
||||
|
||||
/// Prefixes for declared and parameterized variable names
|
||||
static auto constexpr s_structNamePrefix = "S";
|
||||
|
||||
// Static function definitions
|
||||
static bool isValueType(DataType _dataType)
|
||||
@@ -342,11 +376,6 @@ private:
|
||||
return _x.is_signed();
|
||||
}
|
||||
|
||||
static std::string getBoolTypeAsString()
|
||||
{
|
||||
return "bool";
|
||||
}
|
||||
|
||||
static std::string getIntTypeAsString(IntegerType const& _x)
|
||||
{
|
||||
return ((isIntSigned(_x) ? "int" : "uint") + std::to_string(getIntWidth(_x)));
|
||||
@@ -364,7 +393,7 @@ private:
|
||||
|
||||
static std::string getAddressTypeAsString(AddressType const& _x)
|
||||
{
|
||||
return (_x.payable() ? "address payable": "address");
|
||||
return (_x.payable() ? "address payable" : "address");
|
||||
}
|
||||
|
||||
static DataType getDataTypeOfDynBytesType(DynamicByteArrayType const& _x)
|
||||
@@ -375,12 +404,6 @@ private:
|
||||
return DataType::BYTES;
|
||||
}
|
||||
|
||||
/// Returns true if input is either a string or bytes, false otherwise.
|
||||
static bool isDataTypeBytesOrString(DataType _type)
|
||||
{
|
||||
return _type == DataType::STRING || _type == DataType::BYTES;
|
||||
}
|
||||
|
||||
// Convert _counter to string and return its keccak256 hash
|
||||
static u256 hashUnsignedInt(unsigned _counter)
|
||||
{
|
||||
@@ -389,7 +412,7 @@ private:
|
||||
|
||||
static u256 maskUnsignedInt(unsigned _counter, unsigned _numMaskNibbles)
|
||||
{
|
||||
return hashUnsignedInt(_counter) & u256("0x" + std::string(_numMaskNibbles, 'f'));
|
||||
return hashUnsignedInt(_counter) & u256("0x" + std::string(_numMaskNibbles, 'f'));
|
||||
}
|
||||
|
||||
// Requires caller to pass number of nibbles (twice the number of bytes) as second argument.
|
||||
@@ -414,15 +437,6 @@ private:
|
||||
return _fuzz % s_maxArrayLength + 1;
|
||||
}
|
||||
|
||||
static std::pair<bool, unsigned> arrayDimInfoAsPair(ArrayDimensionInfo const& _x)
|
||||
{
|
||||
return (
|
||||
_x.is_static() ?
|
||||
std::make_pair(true, getStaticArrayLengthFromFuzz(_x.length())) :
|
||||
std::make_pair(false, getDynArrayLengthFromFuzz(_x.length(), 0))
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a pseudo-random value for the size of a string/hex
|
||||
/// literal. Used for creating variable length hex/string literals.
|
||||
/// @param _counter Monotonically increasing counter value
|
||||
@@ -435,48 +449,412 @@ private:
|
||||
return (_counter + 879) * 32 % (s_maxDynArrayLength + 1);
|
||||
}
|
||||
|
||||
static std::string bytesArrayTypeAsString(DynamicByteArrayType const& _x)
|
||||
{
|
||||
switch (_x.type())
|
||||
{
|
||||
case DynamicByteArrayType::BYTES:
|
||||
return "bytes";
|
||||
case DynamicByteArrayType::STRING:
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
protected:
|
||||
T visitValueType(ValueType const& _type)
|
||||
{
|
||||
switch (_type.value_type_oneof_case())
|
||||
{
|
||||
case ValueType::kInty:
|
||||
return visit(_type.inty());
|
||||
case ValueType::kByty:
|
||||
return visit(_type.byty());
|
||||
case ValueType::kAdty:
|
||||
return visit(_type.adty());
|
||||
case ValueType::kBoolty:
|
||||
return visit(_type.boolty());
|
||||
case ValueType::VALUE_TYPE_ONEOF_NOT_SET:
|
||||
return T();
|
||||
}
|
||||
}
|
||||
|
||||
T visitNonValueType(NonValueType const& _type)
|
||||
{
|
||||
switch (_type.nonvalue_type_oneof_case())
|
||||
{
|
||||
case NonValueType::kDynbytearray:
|
||||
return visit(_type.dynbytearray());
|
||||
case NonValueType::kArrtype:
|
||||
return visit(_type.arrtype());
|
||||
case NonValueType::kStype:
|
||||
return visit(_type.stype());
|
||||
case NonValueType::NONVALUE_TYPE_ONEOF_NOT_SET:
|
||||
return T();
|
||||
}
|
||||
}
|
||||
|
||||
T visitType(Type const& _type)
|
||||
{
|
||||
switch (_type.type_oneof_case())
|
||||
{
|
||||
case Type::kVtype:
|
||||
return visit(_type.vtype());
|
||||
case Type::kNvtype:
|
||||
return visit(_type.nvtype());
|
||||
case Type::TYPE_ONEOF_NOT_SET:
|
||||
return T();
|
||||
}
|
||||
}
|
||||
private:
|
||||
static unsigned constexpr s_maxArrayLength = 4;
|
||||
static unsigned constexpr s_maxDynArrayLength = 256;
|
||||
};
|
||||
|
||||
/// Converts a protobuf type into a Solidity type string.
|
||||
class TypeVisitor: public AbiV2ProtoVisitor<std::string>
|
||||
{
|
||||
public:
|
||||
TypeVisitor(unsigned _structSuffix = 0):
|
||||
m_indentation(1),
|
||||
m_structCounter(_structSuffix),
|
||||
m_structStartCounter(_structSuffix),
|
||||
m_structFieldCounter(0),
|
||||
m_isLastDynParamRightPadded(false)
|
||||
{}
|
||||
|
||||
std::string visit(BoolType const&) override;
|
||||
std::string visit(IntegerType const&) override;
|
||||
std::string visit(FixedByteType const&) override;
|
||||
std::string visit(AddressType const&) override;
|
||||
std::string visit(ArrayType const&) override;
|
||||
std::string visit(DynamicByteArrayType const&) override;
|
||||
std::string visit(StructType const&) override;
|
||||
using AbiV2ProtoVisitor<std::string>::visit;
|
||||
std::string baseType()
|
||||
{
|
||||
return m_baseType;
|
||||
}
|
||||
bool isLastDynParamRightPadded()
|
||||
{
|
||||
return m_isLastDynParamRightPadded;
|
||||
}
|
||||
std::string structDef()
|
||||
{
|
||||
return m_structDef.str();
|
||||
}
|
||||
unsigned numStructs()
|
||||
{
|
||||
return m_structCounter - m_structStartCounter;
|
||||
}
|
||||
static bool arrayOfStruct(ArrayType const& _type)
|
||||
{
|
||||
Type const& baseType = _type.t();
|
||||
if (baseType.has_nvtype() && baseType.nvtype().has_stype())
|
||||
return true;
|
||||
else if (baseType.has_nvtype() && baseType.nvtype().has_arrtype())
|
||||
return arrayOfStruct(baseType.nvtype().arrtype());
|
||||
else
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
void structDefinition(StructType const&);
|
||||
|
||||
std::string indentation()
|
||||
{
|
||||
return std::string(m_indentation * 1, '\t');
|
||||
}
|
||||
std::string lineString(std::string const& _line)
|
||||
{
|
||||
return indentation() + _line + "\n";
|
||||
}
|
||||
|
||||
std::string m_baseType;
|
||||
std::ostringstream m_structDef;
|
||||
unsigned m_indentation;
|
||||
unsigned m_structCounter;
|
||||
unsigned m_structStartCounter;
|
||||
unsigned m_structFieldCounter;
|
||||
bool m_isLastDynParamRightPadded;
|
||||
|
||||
static auto constexpr s_structTypeName = "S";
|
||||
};
|
||||
|
||||
/// Returns a pair of strings, first of which contains assignment statements
|
||||
/// to initialize a given type, and second of which contains checks to be
|
||||
/// placed inside the coder function to test abi en/decoding.
|
||||
class AssignCheckVisitor: public AbiV2ProtoVisitor<std::pair<std::string, std::string>>
|
||||
{
|
||||
public:
|
||||
AssignCheckVisitor(
|
||||
std::string _varName,
|
||||
std::string _paramName,
|
||||
unsigned _errorStart,
|
||||
bool _stateVar,
|
||||
unsigned _counter,
|
||||
unsigned _structCounter
|
||||
)
|
||||
{
|
||||
m_counter = m_counterStart = _counter;
|
||||
m_varName = _varName;
|
||||
m_paramName = _paramName;
|
||||
m_errorCode = m_errorStart = _errorStart;
|
||||
m_indentation = 2;
|
||||
m_stateVar = _stateVar;
|
||||
m_structCounter = m_structStart = _structCounter;
|
||||
}
|
||||
std::pair<std::string, std::string> visit(BoolType const&) override;
|
||||
std::pair<std::string, std::string> visit(IntegerType const&) override;
|
||||
std::pair<std::string, std::string> visit(FixedByteType const&) override;
|
||||
std::pair<std::string, std::string> visit(AddressType const&) override;
|
||||
std::pair<std::string, std::string> visit(ArrayType const&) override;
|
||||
std::pair<std::string, std::string> visit(DynamicByteArrayType const&) override;
|
||||
std::pair<std::string, std::string> visit(StructType const&) override;
|
||||
using AbiV2ProtoVisitor<std::pair<std::string, std::string>>::visit;
|
||||
|
||||
unsigned errorStmts()
|
||||
{
|
||||
return m_errorCode - m_errorStart;
|
||||
}
|
||||
|
||||
unsigned counted()
|
||||
{
|
||||
return m_counter - m_counterStart;
|
||||
}
|
||||
|
||||
unsigned structs()
|
||||
{
|
||||
return m_structCounter - m_structStart;
|
||||
}
|
||||
private:
|
||||
std::string indentation()
|
||||
{
|
||||
return std::string(m_indentation * 1, '\t');
|
||||
}
|
||||
unsigned counter()
|
||||
{
|
||||
return m_counter++;
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> assignAndCheckStringPair(
|
||||
std::string const& _varRef,
|
||||
std::string const& _checkRef,
|
||||
std::string const& _assignValue,
|
||||
std::string const& _checkValue,
|
||||
DataType _type
|
||||
);
|
||||
std::string assignString(std::string const&, std::string const&);
|
||||
std::string checkString(std::string const&, std::string const&, DataType);
|
||||
unsigned m_counter;
|
||||
unsigned m_counterStart;
|
||||
std::string m_varName;
|
||||
std::string m_paramName;
|
||||
unsigned m_errorCode;
|
||||
unsigned m_errorStart;
|
||||
unsigned m_indentation;
|
||||
bool m_stateVar;
|
||||
unsigned m_structCounter;
|
||||
unsigned m_structStart;
|
||||
};
|
||||
|
||||
/// Returns a valid value (as a string) for a given type.
|
||||
class ValueGetterVisitor: AbiV2ProtoVisitor<std::string>
|
||||
{
|
||||
public:
|
||||
ValueGetterVisitor(unsigned _counter = 0): m_counter(_counter) {}
|
||||
|
||||
std::string visit(BoolType const&) override;
|
||||
std::string visit(IntegerType const&) override;
|
||||
std::string visit(FixedByteType const&) override;
|
||||
std::string visit(AddressType const&) override;
|
||||
std::string visit(DynamicByteArrayType const&) override;
|
||||
std::string visit(ArrayType const&) override
|
||||
{
|
||||
solAssert(false, "ABIv2 proto fuzzer: Cannot call valuegettervisitor on complex type");
|
||||
}
|
||||
std::string visit(StructType const&) override
|
||||
{
|
||||
solAssert(false, "ABIv2 proto fuzzer: Cannot call valuegettervisitor on complex type");
|
||||
}
|
||||
using AbiV2ProtoVisitor<std::string>::visit;
|
||||
private:
|
||||
unsigned counter()
|
||||
{
|
||||
return m_counter++;
|
||||
}
|
||||
|
||||
static std::string intValueAsString(unsigned _width, unsigned _counter);
|
||||
static std::string uintValueAsString(unsigned _width, unsigned _counter);
|
||||
static std::string integerValueAsString(bool _sign, unsigned _width, unsigned _counter);
|
||||
static std::string addressValueAsString(unsigned _counter);
|
||||
static std::string fixedByteValueAsString(unsigned _width, unsigned _counter);
|
||||
|
||||
/// Returns a hex literal if _isHexLiteral is true, a string literal otherwise.
|
||||
/// The size of the returned literal is _numBytes bytes.
|
||||
/// @param _decorate If true, the returned string is enclosed within double quotes
|
||||
/// if _isHexLiteral is false.
|
||||
/// @param _isHexLiteral If true, the returned string is enclosed within
|
||||
/// double quotes prefixed by the string "hex" if _decorate is true. If
|
||||
/// _decorate is false, the returned string is returned as-is.
|
||||
/// @return hex value as string
|
||||
static std::string hexValueAsString(
|
||||
unsigned _numBytes,
|
||||
unsigned _counter,
|
||||
bool _isHexLiteral,
|
||||
bool _decorate = true
|
||||
);
|
||||
|
||||
/// Returns a hex/string literal of variable length whose value and
|
||||
/// size are pseudo-randomly determined from the counter value.
|
||||
/// @param _counter A monotonically increasing counter value
|
||||
/// @param _isHexLiteral Flag that indicates whether hex (if true) or
|
||||
/// string literal (false) is desired
|
||||
/// @return A variable length hex/string value
|
||||
static std::string bytesArrayValueAsString(unsigned _counter, bool _isHexLiteral)
|
||||
static std::string bytesArrayValueAsString(unsigned _counter, bool _isHexLiteral);
|
||||
|
||||
/// Concatenates the hash value obtained from monotonically increasing counter
|
||||
/// until the desired number of bytes determined by _numBytes.
|
||||
/// @param _width Desired number of bytes for hex value
|
||||
/// @param _counter A counter value used for creating a keccak256 hash
|
||||
/// @param _isHexLiteral Since this routine may be used to construct
|
||||
/// string or hex literals, this flag is used to construct a valid output.
|
||||
/// @return Valid hex or string literal of size _width bytes
|
||||
static std::string variableLengthValueAsString(
|
||||
unsigned _width,
|
||||
unsigned _counter,
|
||||
bool _isHexLiteral
|
||||
);
|
||||
|
||||
/// Returns a value that is @a _numBytes bytes long.
|
||||
/// @param _numBytes: Number of bytes of desired value
|
||||
/// @param _counter: A counter value
|
||||
/// @param _isHexLiteral: True if desired value is a hex literal, false otherwise
|
||||
static std::string croppedString(unsigned _numBytes, unsigned _counter, bool _isHexLiteral);
|
||||
|
||||
unsigned m_counter;
|
||||
};
|
||||
|
||||
/// Returns true if protobuf array specification is well-formed, false otherwise
|
||||
class ValidityVisitor: AbiV2ProtoVisitor<bool>
|
||||
{
|
||||
public:
|
||||
ValidityVisitor(): m_arrayDimensions(0) {}
|
||||
|
||||
bool visit(BoolType const&) override
|
||||
{
|
||||
return variableLengthValueAsString(
|
||||
getVarLength(_counter),
|
||||
_counter,
|
||||
_isHexLiteral
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Contains the test program
|
||||
std::ostringstream m_output;
|
||||
/// Temporary storage for state variable definitions
|
||||
std::ostringstream m_statebuffer;
|
||||
/// Contains a subset of the test program. This subset contains
|
||||
/// checks to be encoded in the test program
|
||||
std::ostringstream m_checks;
|
||||
/// Contains typed parameter list to be passed to callee functions
|
||||
std::ostringstream m_typedParamsExternal;
|
||||
std::ostringstream m_typedParamsPublic;
|
||||
/// Predicate that is true if we are in contract scope
|
||||
bool m_isStateVar;
|
||||
unsigned m_counter;
|
||||
unsigned m_varCounter;
|
||||
/// Monotonically increasing return value for error reporting
|
||||
unsigned m_returnValue;
|
||||
/// Flag that indicates if last dynamically encoded parameter
|
||||
/// passed to a function call is of a type that is going to be
|
||||
/// right padded by the ABI encoder.
|
||||
bool m_isLastDynParamRightPadded;
|
||||
static unsigned constexpr s_maxArrayLength = 4;
|
||||
static unsigned constexpr s_maxArrayDimensions = 4;
|
||||
static unsigned constexpr s_maxDynArrayLength = 256;
|
||||
/// Prefixes for declared and parameterized variable names
|
||||
static auto constexpr s_varNamePrefix = "x_";
|
||||
static auto constexpr s_paramNamePrefix = "c_";
|
||||
bool visit(IntegerType const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(FixedByteType const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(AddressType const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(DynamicByteArrayType const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(ArrayType const& _type) override
|
||||
{
|
||||
// Mark array type as invalid in one of the following is true
|
||||
// - contains more than s_maxArrayDimensions dimensions
|
||||
// - contains an invalid base type, which happens in the
|
||||
// following cases
|
||||
// - array base type is invalid
|
||||
// - array base type is empty
|
||||
m_arrayDimensions++;
|
||||
if (m_arrayDimensions > s_maxArrayDimensions)
|
||||
return false;
|
||||
return visit(_type.t());
|
||||
}
|
||||
|
||||
bool visit(StructType const& _type) override
|
||||
{
|
||||
// A struct is marked invalid only if all of its fields
|
||||
// are invalid. This is done to prevent an empty struct
|
||||
// being defined (which is a Solidity error).
|
||||
for (auto const& t: _type.t())
|
||||
if (visit(t))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned m_arrayDimensions;
|
||||
using AbiV2ProtoVisitor<bool>::visit;
|
||||
};
|
||||
|
||||
/// Returns true if visited type is dynamically encoded by the abi coder,
|
||||
/// false otherwise.
|
||||
class DynParamVisitor: AbiV2ProtoVisitor<bool>
|
||||
{
|
||||
public:
|
||||
DynParamVisitor() = default;
|
||||
|
||||
bool visit(BoolType const&) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit(IntegerType const&) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit(FixedByteType const&) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit(AddressType const&) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit(DynamicByteArrayType const&) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit(ArrayType const& _type) override
|
||||
{
|
||||
// Return early if array spec is not well-formed
|
||||
if (!ValidityVisitor().visit(_type))
|
||||
return false;
|
||||
|
||||
// Array is dynamically encoded if it at least one of the following is true
|
||||
// - at least one dimension is dynamically sized
|
||||
// - base type is dynamically encoded
|
||||
if (!_type.is_static())
|
||||
return true;
|
||||
else
|
||||
return visit(_type.t());
|
||||
}
|
||||
|
||||
bool visit(StructType const& _type) override
|
||||
{
|
||||
// Return early if empty struct
|
||||
if (!ValidityVisitor().visit(_type))
|
||||
return false;
|
||||
|
||||
// Struct is dynamically encoded if at least one of its fields
|
||||
// is dynamically encoded.
|
||||
for (auto const& t: _type.t())
|
||||
if (visit(t))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
using AbiV2ProtoVisitor<bool>::visit;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <libyul/optimiser/Disambiguator.h>
|
||||
#include <libyul/optimiser/CallGraphGenerator.h>
|
||||
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
||||
#include <libyul/optimiser/ConditionalSimplifier.h>
|
||||
#include <libyul/optimiser/ControlFlowSimplifier.h>
|
||||
#include <libyul/optimiser/NameCollector.h>
|
||||
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
|
||||
@@ -138,7 +139,8 @@ public:
|
||||
cout << " (e)xpr inline/(i)nline/(s)implify/varname c(l)eaner/(u)nusedprune/ss(a) transform/" << endl;
|
||||
cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-init-rewriter/for-loop-condition-(I)nto-body/" << endl;
|
||||
cout << " for-loop-condition-(O)ut-of-body/s(t)ructural simplifier/equi(v)alent function combiner/ssa re(V)erser/" << endl;
|
||||
cout << " co(n)trol flow simplifier/stack com(p)ressor/(D)ead code eliminator/(L)oad resolver/? " << endl;
|
||||
cout << " co(n)trol flow simplifier/stack com(p)ressor/(D)ead code eliminator/(L)oad resolver/ " << endl;
|
||||
cout << " (C)onditional simplifier?" << endl;
|
||||
cout.flush();
|
||||
int option = readStandardInputChar();
|
||||
cout << ' ' << char(option) << endl;
|
||||
@@ -163,6 +165,9 @@ public:
|
||||
case 'c':
|
||||
CommonSubexpressionEliminator::run(context, *m_ast);
|
||||
break;
|
||||
case 'C':
|
||||
ConditionalSimplifier::run(context, *m_ast);
|
||||
break;
|
||||
case 'd':
|
||||
VarDeclInitializer::run(context, *m_ast);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user