aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/assembly.rst6
-rw-r--r--libevmasm/Instruction.cpp6
-rw-r--r--libevmasm/Instruction.h5
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp14
-rw-r--r--test/libsolidity/InlineAssembly.cpp14
5 files changed, 44 insertions, 1 deletions
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 46416142..cf9bf840 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -206,6 +206,12 @@ In the grammar, opcodes are represented as pre-defined identifiers.
+-------------------------+-----+---+-----------------------------------------------------------------+
| byte(n, x) | | F | nth byte of x, where the most significant byte is the 0th byte |
+-------------------------+-----+---+-----------------------------------------------------------------+
+| shl(x, y) | | C | logical shift left y by x bits |
++-------------------------+-----+---+-----------------------------------------------------------------+
+| shr(x, y) | | C | logical shift right y by x bits |
++-------------------------+-----+---+-----------------------------------------------------------------+
+| sar(x, y) | | C | arithmetic shift right y by x bits |
++-------------------------+-----+---+-----------------------------------------------------------------+
| addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetics |
+-------------------------+-----+---+-----------------------------------------------------------------+
| mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetics |
diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp
index b38981d2..a677a631 100644
--- a/libevmasm/Instruction.cpp
+++ b/libevmasm/Instruction.cpp
@@ -50,6 +50,9 @@ const std::map<std::string, Instruction> dev::solidity::c_instructions =
{ "OR", Instruction::OR },
{ "XOR", Instruction::XOR },
{ "BYTE", Instruction::BYTE },
+ { "SHL", Instruction::SHL },
+ { "SHR", Instruction::SHR },
+ { "SAR", Instruction::SAR },
{ "ADDMOD", Instruction::ADDMOD },
{ "MULMOD", Instruction::MULMOD },
{ "SIGNEXTEND", Instruction::SIGNEXTEND },
@@ -190,6 +193,9 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::OR, { "OR", 0, 2, 1, false, Tier::VeryLow } },
{ Instruction::XOR, { "XOR", 0, 2, 1, false, Tier::VeryLow } },
{ Instruction::BYTE, { "BYTE", 0, 2, 1, false, Tier::VeryLow } },
+ { Instruction::SHL, { "SHL", 0, 2, 1, false, Tier::VeryLow } },
+ { Instruction::SHR, { "SHR", 0, 2, 1, false, Tier::VeryLow } },
+ { Instruction::SAR, { "SAR", 0, 2, 1, false, Tier::VeryLow } },
{ Instruction::ADDMOD, { "ADDMOD", 0, 3, 1, false, Tier::Mid } },
{ Instruction::MULMOD, { "MULMOD", 0, 3, 1, false, Tier::Mid } },
{ Instruction::SIGNEXTEND, { "SIGNEXTEND", 0, 2, 1, false, Tier::Low } },
diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h
index d9c53900..be788ddb 100644
--- a/libevmasm/Instruction.h
+++ b/libevmasm/Instruction.h
@@ -59,8 +59,11 @@ enum class Instruction: uint8_t
AND, ///< bitwise AND operation
OR, ///< bitwise OR operation
XOR, ///< bitwise XOR operation
- NOT, ///< bitwise NOT opertation
+ NOT, ///< bitwise NOT operation
BYTE, ///< retrieve single byte from word
+ SHL, ///< bitwise SHL operation
+ SHR, ///< bitwise SHR operation
+ SAR, ///< bitwise SAR operation
KECCAK256 = 0x20, ///< compute KECCAK-256 hash
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index a05ac57d..1030523a 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -548,6 +548,20 @@ void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocatio
"the Metropolis hard fork. Before that it acts as an invalid instruction."
);
+ static set<solidity::Instruction> experimentalInstructions{
+ solidity::Instruction::SHL,
+ solidity::Instruction::SHR,
+ solidity::Instruction::SAR
+ };
+ if (experimentalInstructions.count(_instr))
+ m_errorReporter.warning(
+ _location,
+ "The \"" +
+ boost::to_lower_copy(instructionInfo(_instr).name)
+ + "\" instruction is only available after " +
+ "the Constantinople hard fork. Before that it acts as an invalid instruction."
+ );
+
if (_instr == solidity::Instruction::JUMP || _instr == solidity::Instruction::JUMPI || _instr == solidity::Instruction::JUMPDEST)
m_errorReporter.warning(
_location,
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index 45fb54f8..ea120657 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -774,6 +774,20 @@ BOOST_AUTO_TEST_CASE(create2)
BOOST_CHECK(successAssemble("{ pop(create2(10, 0x123, 32, 64)) }"));
}
+BOOST_AUTO_TEST_CASE(shift)
+{
+ BOOST_CHECK(successAssemble("{ pop(shl(10, 32)) }"));
+ BOOST_CHECK(successAssemble("{ pop(shr(10, 32)) }"));
+ BOOST_CHECK(successAssemble("{ pop(sar(10, 32)) }"));
+}
+
+BOOST_AUTO_TEST_CASE(shift_constantinople_warning)
+{
+ CHECK_PARSE_WARNING("{ pop(shl(10, 32)) }", Warning, "The \"shl\" instruction is only available after the Constantinople hard fork");
+ CHECK_PARSE_WARNING("{ pop(shr(10, 32)) }", Warning, "The \"shr\" instruction is only available after the Constantinople hard fork");
+ CHECK_PARSE_WARNING("{ pop(sar(10, 32)) }", Warning, "The \"sar\" instruction is only available after the Constantinople hard fork");
+}
+
BOOST_AUTO_TEST_CASE(jump_warning)
{
CHECK_PARSE_WARNING("{ 1 jump }", Warning, "Jump instructions");