mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Initial EVM1.5 assembly implementation.
This commit is contained in:
@@ -21,11 +21,13 @@
|
||||
|
||||
#include "../TestHelper.h"
|
||||
|
||||
#include <test/libsolidity/ErrorCheck.h>
|
||||
|
||||
#include <libsolidity/inlineasm/AsmParser.h>
|
||||
#include <libsolidity/inlineasm/AsmAnalysis.h>
|
||||
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
|
||||
#include <libsolidity/parsing/Scanner.h>
|
||||
#include <test/libsolidity/ErrorCheck.h>
|
||||
#include <libsolidity/interface/ErrorReporter.h>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
@@ -481,6 +481,42 @@ BOOST_AUTO_TEST_CASE(revert)
|
||||
BOOST_CHECK(successAssemble("{ revert(0, 0) }"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(function_calls)
|
||||
{
|
||||
BOOST_CHECK(successAssemble("{ function f() {} }"));
|
||||
BOOST_CHECK(successAssemble("{ function f() { let y := 2 } }"));
|
||||
BOOST_CHECK(successAssemble("{ function f() -> z { let y := 2 } }"));
|
||||
BOOST_CHECK(successAssemble("{ function f(a) { let y := 2 } }"));
|
||||
BOOST_CHECK(successAssemble("{ function f(a) { let y := a } }"));
|
||||
BOOST_CHECK(successAssemble("{ function f() -> x, y, z {} }"));
|
||||
BOOST_CHECK(successAssemble("{ function f(x, y, z) {} }"));
|
||||
BOOST_CHECK(successAssemble("{ function f(a, b) -> x, y, z { y := a } }"));
|
||||
BOOST_CHECK(successAssemble("{ function f() {} f() }"));
|
||||
BOOST_CHECK(successAssemble("{ function f() -> x, y { x := 1 y := 2} let a, b := f() }"));
|
||||
BOOST_CHECK(successAssemble("{ function f(a, b) -> x, y { x := b y := a } let a, b := f(2, 3) }"));
|
||||
BOOST_CHECK(successAssemble("{ function rec(a) { rec(sub(a, 1)) } rec(2) }"));
|
||||
BOOST_CHECK(successAssemble("{ let r := 2 function f() -> x, y { x := 1 y := 2} let a, b := f() b := r }"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(switch_statement)
|
||||
{
|
||||
BOOST_CHECK(successAssemble("{ switch 1 default {} }"));
|
||||
BOOST_CHECK(successAssemble("{ switch 1 case 1 {} default {} }"));
|
||||
BOOST_CHECK(successAssemble("{ switch 1 case 1 {} }"));
|
||||
BOOST_CHECK(successAssemble("{ let a := 3 switch a case 1 { a := 1 } case 2 { a := 5 } a := 9}"));
|
||||
BOOST_CHECK(successAssemble("{ let a := 2 switch calldataload(0) case 1 { a := 1 } case 2 { a := 5 } }"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(large_constant)
|
||||
{
|
||||
auto source = R"({
|
||||
switch mul(1, 2)
|
||||
case 0x0000000000000000000000000000000000000000000000000000000026121ff0 {
|
||||
}
|
||||
})";
|
||||
BOOST_CHECK(successAssemble(source));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(keccak256)
|
||||
{
|
||||
BOOST_CHECK(successAssemble("{ 0 0 keccak256 pop }"));
|
||||
|
||||
@@ -7535,6 +7535,102 @@ BOOST_AUTO_TEST_CASE(inline_assembly_function_access)
|
||||
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(10)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_assembly_function_call)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f() {
|
||||
assembly {
|
||||
function asmfun(a, b, c) -> x, y, z {
|
||||
x := a
|
||||
y := b
|
||||
z := 7
|
||||
}
|
||||
let a1, b1, c1 := asmfun(1, 2, 3)
|
||||
mstore(0x00, a1)
|
||||
mstore(0x20, b1)
|
||||
mstore(0x40, c1)
|
||||
return(0, 0x60)
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_assembly_function_call2)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f() {
|
||||
assembly {
|
||||
let d := 0x10
|
||||
function asmfun(a, b, c) -> x, y, z {
|
||||
x := a
|
||||
y := b
|
||||
z := 7
|
||||
}
|
||||
let a1, b1, c1 := asmfun(1, 2, 3)
|
||||
mstore(0x00, a1)
|
||||
mstore(0x20, b1)
|
||||
mstore(0x40, c1)
|
||||
mstore(0x60, d)
|
||||
return(0, 0x80)
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1), u256(2), u256(7), u256(0x10)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_assembly_switch)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(uint a) returns (uint b) {
|
||||
assembly {
|
||||
switch a
|
||||
case 1 { b := 8 }
|
||||
case 2 { b := 9 }
|
||||
default { b := 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(2)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(8)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(9)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(2)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_assembly_recursion)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(uint a) returns (uint b) {
|
||||
assembly {
|
||||
function fac(n) -> nf {
|
||||
switch n
|
||||
case 0 { nf := 1 }
|
||||
case 1 { nf := 1 }
|
||||
default { nf := mul(n, fac(sub(n, 1))) }
|
||||
}
|
||||
b := fac(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(1)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(1)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(2)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(6)));
|
||||
BOOST_CHECK(callContractFunction("f(uint256)", u256(4)) == encodeArgs(u256(24)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(index_access_with_type_conversion)
|
||||
{
|
||||
// Test for a bug where higher order bits cleanup was not done for array index access.
|
||||
|
||||
@@ -5159,6 +5159,21 @@ BOOST_AUTO_TEST_CASE(inline_assembly_constant_access)
|
||||
CHECK_ERROR(text, TypeError, "Constant variables not supported by inline assembly");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_assembly_variable_access_out_of_functions)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
uint a;
|
||||
assembly {
|
||||
function g() -> x { x := a }
|
||||
}
|
||||
}
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, DeclarationError, "Inline assembly functions cannot access their outer scope.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_mobile_type)
|
||||
{
|
||||
char const* text = R"(
|
||||
|
||||
Reference in New Issue
Block a user