mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8161 from ethereum/yulTypeChecking
Yul type checking
This commit is contained in:
@@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(simple_inside_structures)
|
||||
BOOST_CHECK_EQUAL(inlinableFunctions("{"
|
||||
"function g(a:u256) -> b:u256 { b := a }"
|
||||
"for {"
|
||||
"} 1:u256 {"
|
||||
"} true {"
|
||||
"function f() -> x:u256 { x := g(2:u256) }"
|
||||
"}"
|
||||
"{"
|
||||
|
||||
+2
-20
@@ -245,16 +245,6 @@ BOOST_AUTO_TEST_CASE(optional_types)
|
||||
BOOST_CHECK(successParse("{ function f(a:u256) -> b {} }"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_types)
|
||||
{
|
||||
/// testing invalid literal
|
||||
/// NOTE: these will need to change when types are compared
|
||||
CHECK_ERROR("{ let x:bool := 1:invalid }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported).");
|
||||
/// testing invalid variable declaration
|
||||
CHECK_ERROR("{ let x:invalid := 1:bool }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported).");
|
||||
CHECK_ERROR("{ function f(a:invalid) {} }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported).");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(number_literals)
|
||||
{
|
||||
BOOST_CHECK(successParse("{ let x:u256 := 1:u256 }"));
|
||||
@@ -268,7 +258,7 @@ BOOST_AUTO_TEST_CASE(builtin_types)
|
||||
{
|
||||
BOOST_CHECK(successParse("{ let x:bool := true:bool }"));
|
||||
BOOST_CHECK(successParse("{ let x:u8 := 1:u8 }"));
|
||||
BOOST_CHECK(successParse("{ let x:s8 := 1:u8 }"));
|
||||
BOOST_CHECK(successParse("{ let x:s8 := 1:s8 }"));
|
||||
BOOST_CHECK(successParse("{ let x:u32 := 1:u32 }"));
|
||||
BOOST_CHECK(successParse("{ let x:s32 := 1:s32 }"));
|
||||
BOOST_CHECK(successParse("{ let x:u64 := 1:u64 }"));
|
||||
@@ -495,15 +485,7 @@ BOOST_AUTO_TEST_CASE(if_statement_invalid)
|
||||
{
|
||||
CHECK_ERROR("{ if let x:u256 {} }", ParserError, "Literal or identifier expected.");
|
||||
CHECK_ERROR("{ if true:bool let x:u256 := 3:u256 }", ParserError, "Expected '{' but got reserved keyword 'let'");
|
||||
// TODO change this to an error once we check types.
|
||||
BOOST_CHECK(successParse("{ if 42:u256 { } }"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(switch_case_types)
|
||||
{
|
||||
CHECK_ERROR("{ switch 0:u256 case 0:u256 {} case 1:u32 {} }", TypeError, "Switch cases have non-matching types.");
|
||||
// The following should be an error in the future, but this is not yet detected.
|
||||
BOOST_CHECK(successParse("{ switch 0:u256 case 0:u32 {} case 1:u32 {} }"));
|
||||
CHECK_ERROR("{ if 42:u256 { } }", TypeError, "Expected a value of boolean type");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(switch_duplicate_case)
|
||||
|
||||
@@ -111,6 +111,8 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename)
|
||||
m_dialect = &WasmDialect::instance();
|
||||
else if (dialectName == "evm")
|
||||
m_dialect = &EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion());
|
||||
else if (dialectName == "evmTyped")
|
||||
m_dialect = &EVMDialectTyped::instance(solidity::test::CommonOptions::get().evmVersion());
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Invalid dialect " + dialectName));
|
||||
|
||||
@@ -357,7 +359,7 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
|
||||
{
|
||||
disambiguate();
|
||||
ExpressionSplitter::run(*m_context, *m_ast);
|
||||
WordSizeTransform::run(*m_dialect, ""_yulstring, *m_ast, *m_nameDispenser);
|
||||
WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser);
|
||||
}
|
||||
else if (m_optimizerStep == "fullSuite")
|
||||
{
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
let y:bool := false
|
||||
for {} true { } {
|
||||
if y { break }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// dialect: yul
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let y:bool := false
|
||||
// for { } true { }
|
||||
// {
|
||||
// if y { break }
|
||||
// y := false
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
let y:i32 := 0:i32
|
||||
for {} true { } {
|
||||
if y { break }
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// step: conditionalSimplifier
|
||||
// ----
|
||||
// {
|
||||
// let y:i32 := 0:i32
|
||||
// for { } true { }
|
||||
// {
|
||||
// if y { break }
|
||||
// y := false
|
||||
// }
|
||||
// }
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
{ let a:u256, b:u256 }
|
||||
{
|
||||
for { let a:u256 } a { a := a } {
|
||||
function eq(x: u256, y: u256) -> z: bool {}
|
||||
for { let a:u256 } eq(a, a) { a := a } {
|
||||
let b:u256 := a
|
||||
}
|
||||
}
|
||||
@@ -13,7 +14,9 @@
|
||||
// {
|
||||
// { let a, b }
|
||||
// {
|
||||
// for { let a_1 } a_1 { a_1 := a_1 }
|
||||
// function eq(x, y) -> z:bool
|
||||
// { }
|
||||
// for { let a_1 } eq(a_1, a_1) { a_1 := a_1 }
|
||||
// { let b_2 := a_1 }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
function fun(x: i32, y) -> t: i32, z: i32 {
|
||||
z := i32.add(x, i32.add(z, z))
|
||||
|
||||
}
|
||||
i64.store(i32.load(5:i32), i64.load(8:i32))
|
||||
let i := 0
|
||||
for {} i32.eqz(i32.load(9:i32)) { i := i64.add(i, 1) } {
|
||||
let f: i32, g: i32 := fun(i32.load(1:i32), i64.load(i32.load(0: i32)))
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// step: expressionSplitter
|
||||
// ----
|
||||
// {
|
||||
// function fun(x:i32, y) -> t:i32, z:i32
|
||||
// {
|
||||
// let _1:i32 := i32.add(z, z)
|
||||
// z := i32.add(x, _1)
|
||||
// }
|
||||
// let _2:i32 := 8:i32
|
||||
// let _3 := i64.load(_2)
|
||||
// let _4:i32 := 5:i32
|
||||
// let _5:i32 := i32.load(_4)
|
||||
// i64.store(_5, _3)
|
||||
// let i := 0
|
||||
// for { }
|
||||
// i32.eqz(i32.load(9:i32))
|
||||
// {
|
||||
// let _6 := 1
|
||||
// i := i64.add(i, _6)
|
||||
// }
|
||||
// {
|
||||
// let _7:i32 := 0:i32
|
||||
// let _8:i32 := i32.load(_7)
|
||||
// let _9 := i64.load(_8)
|
||||
// let _10:i32 := 1:i32
|
||||
// let _11:i32 := i32.load(_10)
|
||||
// let f:i32, g:i32 := fun(_11, _9)
|
||||
// }
|
||||
// }
|
||||
@@ -19,7 +19,7 @@
|
||||
// { }
|
||||
// for { } a { }
|
||||
// { }
|
||||
// for { } 1 { }
|
||||
// for { } true { }
|
||||
// {
|
||||
// if iszero(add(a, a)) { break }
|
||||
// }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// step: forLoopConditionIntoBody
|
||||
// ----
|
||||
// {
|
||||
// for { let a := 1 } 1 { a := add(a, 1) }
|
||||
// for { let a := 1 } true { a := add(a, 1) }
|
||||
// {
|
||||
// if iszero(iszero(eq(a, 10))) { break }
|
||||
// }
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
// {
|
||||
// let random := 42
|
||||
// for {
|
||||
// for { let a := 1 } 1 { }
|
||||
// for { let a := 1 } true { }
|
||||
// {
|
||||
// if iszero(iszero(eq(a, 10))) { break }
|
||||
// a := add(a, 1)
|
||||
// }
|
||||
// let b := 1
|
||||
// }
|
||||
// 1
|
||||
// true
|
||||
// {
|
||||
// for { let c := 1 } 1 { c := add(c, 1) }
|
||||
// for { let c := 1 } true { c := add(c, 1) }
|
||||
// {
|
||||
// if iszero(iszero(eq(c, 2))) { break }
|
||||
// b := add(b, 1)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// ----
|
||||
// {
|
||||
// let random := 42
|
||||
// for { let a := 1 } 1 { a := add(a, 1) }
|
||||
// for { let a := 1 } true { a := add(a, 1) }
|
||||
// {
|
||||
// if iszero(iszero(eq(a, 10))) { break }
|
||||
// a := add(a, 1)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
function f(a: u256) -> x: bool, y:u256 {
|
||||
y := mul(a, a)
|
||||
}
|
||||
let r: bool, s: u256 := f(mload(3))
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// step: fullInliner
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
// let a_3 := mload(3)
|
||||
// let x_4:bool := false
|
||||
// let y_5 := 0
|
||||
// y_5 := mul(a_3, a_3)
|
||||
// let r:bool := x_4
|
||||
// let s := y_5
|
||||
// }
|
||||
// function f(a) -> x:bool, y
|
||||
// { y := mul(a, a) }
|
||||
// }
|
||||
@@ -14,7 +14,7 @@
|
||||
// {
|
||||
// let _1 := iszero(caller())
|
||||
// for { }
|
||||
// 1
|
||||
// true
|
||||
// {
|
||||
// for { } iszero(_1) { }
|
||||
// { }
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
let b:bool := true
|
||||
let c:bool := false
|
||||
c := b
|
||||
b := false
|
||||
|
||||
let a:u256 := 1
|
||||
a := add(a, 1)
|
||||
if c {
|
||||
a := add(a, 1)
|
||||
}
|
||||
a := add(a, 1)
|
||||
mstore(a, 1)
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// step: ssaTransform
|
||||
// ----
|
||||
// {
|
||||
// let b_1:bool := true
|
||||
// let b:bool := b_1
|
||||
// let c_2:bool := false
|
||||
// let c:bool := c_2
|
||||
// let c_3:bool := b_1
|
||||
// c := c_3
|
||||
// let b_4:bool := false
|
||||
// b := b_4
|
||||
// let a_5 := 1
|
||||
// let a := a_5
|
||||
// let a_6 := add(a_5, 1)
|
||||
// a := a_6
|
||||
// if c_3
|
||||
// {
|
||||
// let a_7 := add(a_6, 1)
|
||||
// a := a_7
|
||||
// }
|
||||
// let a_9 := a
|
||||
// let a_8 := add(a_9, 1)
|
||||
// a := a_8
|
||||
// mstore(a_8, 1)
|
||||
// }
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
let b:bool := true
|
||||
let c:bool := false
|
||||
for {} b {} {
|
||||
c := true
|
||||
}
|
||||
let d: bool := c
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// step: ssaTransform
|
||||
// ----
|
||||
// {
|
||||
// let b:bool := true
|
||||
// let c_1:bool := false
|
||||
// let c:bool := c_1
|
||||
// for { } b { }
|
||||
// {
|
||||
// let c_3:bool := c
|
||||
// let c_2:bool := true
|
||||
// c := c_2
|
||||
// }
|
||||
// let c_4:bool := c
|
||||
// let d:bool := c_4
|
||||
// }
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
let b:bool := true
|
||||
let c:bool := false
|
||||
switch b
|
||||
case true { c := true}
|
||||
case false { }
|
||||
let d: bool := c
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// step: ssaTransform
|
||||
// ----
|
||||
// {
|
||||
// let b:bool := true
|
||||
// let c_1:bool := false
|
||||
// let c:bool := c_1
|
||||
// switch b
|
||||
// case true {
|
||||
// let c_2:bool := true
|
||||
// c := c_2
|
||||
// }
|
||||
// case false { }
|
||||
// let c_3:bool := c
|
||||
// let d:bool := c_3
|
||||
// }
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
let a1
|
||||
let a2: bool
|
||||
let b1, b2: bool
|
||||
function f(a:u256, b:u256, c:bool) -> r:bool, t {
|
||||
let x1: bool, x2
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// step: varDeclInitializer
|
||||
// ----
|
||||
// {
|
||||
// let a1 := 0
|
||||
// let a2:bool := false
|
||||
// let b1 := 0
|
||||
// let b2:bool := false
|
||||
// function f(a, b, c:bool) -> r:bool, t
|
||||
// {
|
||||
// let x1:bool := false
|
||||
// let x2 := 0
|
||||
// }
|
||||
// }
|
||||
@@ -67,13 +67,13 @@
|
||||
// let _10_3 := 3
|
||||
// sstore(_10_0, _10_1, _10_2, _10_3, _9_0, _9_1, _9_2, _9_3)
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// if run_default
|
||||
// {
|
||||
// let _11_0 := 0
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
// let _8_3 := 2
|
||||
// sstore(_8_0, _8_1, _8_2, _8_3, _7_0, _7_1, _7_2, _7_3)
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// case 536870912 {
|
||||
// switch _2_2
|
||||
@@ -75,13 +75,13 @@
|
||||
// let _10_3 := 3
|
||||
// sstore(_10_0, _10_1, _10_2, _10_3, _9_0, _9_1, _9_2, _9_3)
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// }
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// if run_default
|
||||
// {
|
||||
// let _11_0 := 0
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// let _2_0, _2_1, _2_2, _2_3 := calldataload(_1_0, _1_1, _1_2, _1_3)
|
||||
// let run_default
|
||||
// switch _2_0
|
||||
// default { run_default := 1 }
|
||||
// default { run_default := true }
|
||||
// if run_default
|
||||
// {
|
||||
// let _3_0 := 0
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
let x:u256
|
||||
let y := x
|
||||
let z:bool
|
||||
z := y
|
||||
y := z
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (51-52): Assigning a value of type "u256" to a variable of type "bool".
|
||||
// TypeError: (62-63): Assigning a value of type "bool" to a variable of type "u256".
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
let x:bool
|
||||
for {} x {} {}
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
let x
|
||||
for {} x {} {}
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (23-24): Expected a value of boolean type "bool" but got "u256"
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
let x
|
||||
for {} x {} {}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// ----
|
||||
// TypeError: (23-24): Expected a value of boolean type "i32" but got "i64"
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
let x: invalidType
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (10-24): "invalidType" is not a valid type (user defined types are not yet supported).
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
let x := 1:invalidType
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (15-28): "invalidType" is not a valid type (user defined types are not yet supported).
|
||||
// TypeError: (10-11): Assigning value of type "invalidType" to variable of type "u256.
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
function f(a: invalidType) -> b: invalidType {}
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (17-31): "invalidType" is not a valid type (user defined types are not yet supported).
|
||||
// TypeError: (36-50): "invalidType" is not a valid type (user defined types are not yet supported).
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
switch 1
|
||||
case 8: invalidType {}
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (24-38): Expected a value of type "u256" but got "invalidType"
|
||||
// TypeError: (24-38): "invalidType" is not a valid type (user defined types are not yet supported).
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
switch 7:i64
|
||||
case 0:i64 {}
|
||||
case 2:i64 {}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// ----
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
switch 7:i32
|
||||
case 0:i64 {}
|
||||
case 2:i64 {}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// ----
|
||||
// TypeError: (28-33): Expected a value of type "i32" but got "i64"
|
||||
// TypeError: (46-51): Expected a value of type "i32" but got "i64"
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
switch 7
|
||||
case true:bool {}
|
||||
case true:bool {}
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (24-33): Expected a value of type "u256" but got "bool"
|
||||
// TypeError: (46-55): Expected a value of type "u256" but got "bool"
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
let x:i32
|
||||
if x {}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// ----
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
let x:i64
|
||||
if x {}
|
||||
}
|
||||
// ====
|
||||
// dialect: ewasm
|
||||
// ----
|
||||
// TypeError: (23-24): Expected a value of boolean type "i32" but got "i64"
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
function f(a:u256, b:u256, c:bool) -> r:bool, t {
|
||||
r := lt(a, b)
|
||||
t := bool_to_u256(not(c))
|
||||
}
|
||||
let x, y: bool := f(1, 2: u256, true)
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
// TypeError: (126-127): Assigning value of type "bool" to variable of type "u256.
|
||||
// TypeError: (129-136): Assigning value of type "u256" to variable of type "bool.
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
function f(a:u256, b:u256, c:bool) -> r:bool, t {
|
||||
r := lt(a, b)
|
||||
t := bool_to_u256(not(c))
|
||||
}
|
||||
let x: bool, y: u256 := f(1, 2: u256, true)
|
||||
}
|
||||
// ====
|
||||
// dialect: evmTyped
|
||||
// ----
|
||||
Reference in New Issue
Block a user