aboutsummaryrefslogtreecommitdiffstats
path: root/libevmasm/ConstantOptimiser.cpp
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-05-03 20:36:32 +0800
committerGitHub <noreply@github.com>2017-05-03 20:36:32 +0800
commit68ef5810593e7c8092ed41d5f474dd43141624eb (patch)
tree36453acfef9495095dc47305d9b40c2cd3b63813 /libevmasm/ConstantOptimiser.cpp
parentf0d539ae05739e35336cc9cc8f44bd9798a95c28 (diff)
parent34b28ed760e8ba9b86f661c819fe489fb8403235 (diff)
downloaddexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar
dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.gz
dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.bz2
dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.lz
dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.xz
dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.zst
dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.zip
Merge pull request #2219 from ethereum/develop
Release for version 0.4.11
Diffstat (limited to 'libevmasm/ConstantOptimiser.cpp')
-rw-r--r--libevmasm/ConstantOptimiser.cpp57
1 files changed, 55 insertions, 2 deletions
diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp
index a1dfd21c..0c093ebf 100644
--- a/libevmasm/ConstantOptimiser.cpp
+++ b/libevmasm/ConstantOptimiser.cpp
@@ -203,8 +203,13 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
u256 powerOfTwo = u256(1) << bits;
u256 upperPart = _value >> bits;
bigint lowerPart = _value & (powerOfTwo - 1);
- if (abs(powerOfTwo - lowerPart) < lowerPart)
+ if ((powerOfTwo - lowerPart) < lowerPart)
+ {
lowerPart = lowerPart - powerOfTwo; // make it negative
+ upperPart++;
+ }
+ if (upperPart == 0)
+ continue;
if (abs(lowerPart) >= (powerOfTwo >> 8))
continue;
@@ -212,7 +217,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
if (lowerPart != 0)
newRoutine += findRepresentation(u256(abs(lowerPart)));
newRoutine += AssemblyItems{u256(bits), u256(2), Instruction::EXP};
- if (upperPart != 1 && upperPart != 0)
+ if (upperPart != 1)
newRoutine += findRepresentation(upperPart) + AssemblyItems{Instruction::MUL};
if (lowerPart > 0)
newRoutine += AssemblyItems{Instruction::ADD};
@@ -232,6 +237,54 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
}
}
+bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine)
+{
+ // This is a tiny EVM that can only evaluate some instructions.
+ vector<u256> stack;
+ for (AssemblyItem const& item: _routine)
+ {
+ switch (item.type())
+ {
+ case Operation:
+ {
+ if (stack.size() < size_t(item.arguments()))
+ return false;
+ u256* sp = &stack.back();
+ switch (item.instruction())
+ {
+ case Instruction::MUL:
+ sp[-1] = sp[0] * sp[-1];
+ break;
+ case Instruction::EXP:
+ if (sp[-1] > 0xff)
+ return false;
+ sp[-1] = boost::multiprecision::pow(sp[0], unsigned(sp[-1]));
+ break;
+ case Instruction::ADD:
+ sp[-1] = sp[0] + sp[-1];
+ break;
+ case Instruction::SUB:
+ sp[-1] = sp[0] - sp[-1];
+ break;
+ case Instruction::NOT:
+ sp[0] = ~sp[0];
+ break;
+ default:
+ return false;
+ }
+ stack.resize(stack.size() + item.deposit());
+ break;
+ }
+ case Push:
+ stack.push_back(item.data());
+ break;
+ default:
+ return false;
+ }
+ }
+ return stack.size() == 1 && stack.front() == _value;
+}
+
bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
{
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);