Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
c6b036e2e6
  1. 11
      cmake/EthCompilerSettings.cmake
  2. 2
      evmjit/libevmjit-cpp/CMakeLists.txt
  3. 6
      libdevcore/CMakeLists.txt
  4. 6
      libdevcrypto/CMakeLists.txt
  5. 6
      libethcore/CMakeLists.txt
  6. 6
      libethereum/CMakeLists.txt
  7. 6
      libethereumx/CMakeLists.txt
  8. 6
      libevm/CMakeLists.txt
  9. 13
      libevmcore/AssemblyItem.h
  10. 6
      libevmcore/CMakeLists.txt
  11. 176
      libevmcore/CommonSubexpressionEliminator.cpp
  12. 20
      libevmcore/CommonSubexpressionEliminator.h
  13. 24
      libevmcore/ExpressionClasses.cpp
  14. 10
      libevmcore/ExpressionClasses.h
  15. 6
      liblll/CMakeLists.txt
  16. 6
      libnatspec/CMakeLists.txt
  17. 6
      libp2p/CMakeLists.txt
  18. 6
      libserpent/CMakeLists.txt
  19. 6
      libsolidity/AST.cpp
  20. 6
      libsolidity/CMakeLists.txt
  21. 16
      libsolidity/ExpressionCompiler.cpp
  22. 18
      libsolidity/InterfaceHandler.cpp
  23. 43
      libsolidity/Types.cpp
  24. 23
      libsolidity/Types.h
  25. 6
      libtestutils/CMakeLists.txt
  26. 6
      libweb3jsonrpc/CMakeLists.txt
  27. 18
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  28. 6
      libwebthree/CMakeLists.txt
  29. 6
      libwhisper/CMakeLists.txt
  30. 1
      mix/qml/QBoolTypeView.qml
  31. 1
      mix/qml/QHashTypeView.qml
  32. 11
      mix/qml/QIntTypeView.qml
  33. 10
      mix/qml/QStringTypeView.qml
  34. 13
      mix/qml/StructView.qml
  35. 2
      mix/qml/VariablesView.qml
  36. 18
      secp256k1/CMakeLists.txt
  37. 6
      solc/CMakeLists.txt
  38. 30
      test/libsolidity/SolidityABIJSON.cpp
  39. 16
      test/libsolidity/SolidityOptimizer.cpp

11
cmake/EthCompilerSettings.cmake

@ -8,7 +8,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_RELEASE")
set(ETH_SHARED 1)
if (PROFILING) if (PROFILING)
set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
@ -31,7 +30,6 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DETH_RELEASE")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -DETH_DEBUG")
set(ETH_SHARED 1)
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++ -fcolor-diagnostics -Qunused-arguments -DBOOST_ASIO_HAS_CLANG_LIBCXX")
@ -55,8 +53,10 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# stack size 16MB # stack size 16MB
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216")
# windows likes static # windows likes static
if (NOT ETH_STATIC)
message("Forcing static linkage for MSVC.")
set(ETH_STATIC 1) set(ETH_STATIC 1)
endif ()
else () else ()
message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.")
endif () endif ()
@ -72,3 +72,8 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
endif () endif ()
endif () endif ()
if(ETH_STATIC)
set(BUILD_SHARED_LIBS OFF)
else()
set(BUILD_SHARED_LIBS ON)
endif(ETH_STATIC)

2
evmjit/libevmjit-cpp/CMakeLists.txt

@ -15,7 +15,7 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # add PIC for archive set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # add PIC for archive
endif() endif()
add_library(${TARGET_NAME} ${SOURCES}) add_library(${TARGET_NAME} STATIC ${SOURCES})
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs") set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "libs")
include_directories(../..) include_directories(../..)

6
libdevcore/CMakeLists.txt

@ -20,11 +20,7 @@ set(EXECUTABLE devcore)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_THREAD_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_SYSTEM_LIBRARIES})

6
libdevcrypto/CMakeLists.txt

@ -17,11 +17,7 @@ include_directories(${LEVELDB_INCLUDE_DIRS})
set(EXECUTABLE devcrypto) set(EXECUTABLE devcrypto)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})

6
libethcore/CMakeLists.txt

@ -24,11 +24,7 @@ set(EXECUTABLE ethcore)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ethash) target_link_libraries(${EXECUTABLE} ethash)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)

6
libethereum/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE ethereum)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} evm) target_link_libraries(${EXECUTABLE} evm)
target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} lll)

6
libethereumx/CMakeLists.txt

@ -11,11 +11,7 @@ set(EXECUTABLE ethereumx)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LS}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LS})
target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS}) target_link_libraries(${EXECUTABLE} ${CRYPTOPP_LS})

6
libevm/CMakeLists.txt

@ -20,11 +20,7 @@ set(EXECUTABLE evm)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ethcore) target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)

13
libevmcore/AssemblyItem.h

@ -43,9 +43,16 @@ class AssemblyItem
public: public:
enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; enum class JumpType { Ordinary, IntoFunction, OutOfFunction };
AssemblyItem(u256 _push): m_type(Push), m_data(_push) {} AssemblyItem(u256 _push, SourceLocation const& _location = SourceLocation()):
AssemblyItem(Instruction _i): m_type(Operation), m_data((byte)_i) {} AssemblyItem(Push, _push, _location) { }
AssemblyItem(AssemblyItemType _type, u256 _data = 0): m_type(_type), m_data(_data) {} AssemblyItem(Instruction _i, SourceLocation const& _location = SourceLocation()):
AssemblyItem(Operation, byte(_i), _location) { }
AssemblyItem(AssemblyItemType _type, u256 _data = 0, SourceLocation const& _location = SourceLocation()):
m_type(_type),
m_data(_data),
m_location(_location)
{
}
AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); } AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); }
AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); } AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); }

6
libevmcore/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE evmcore)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} devcrypto) target_link_libraries(${EXECUTABLE} devcrypto)

176
libevmcore/CommonSubexpressionEliminator.cpp

@ -41,9 +41,9 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
if (!m_stackElements.empty()) if (!m_stackElements.empty())
minHeight = min(minHeight, m_stackElements.begin()->first); minHeight = min(minHeight, m_stackElements.begin()->first);
for (int height = minHeight; height <= 0; ++height) for (int height = minHeight; height <= 0; ++height)
initialStackContents[height] = initialStackElement(height); initialStackContents[height] = initialStackElement(height, SourceLocation());
for (int height = minHeight; height <= m_stackHeight; ++height) for (int height = minHeight; height <= m_stackHeight; ++height)
targetStackContents[height] = stackElement(height); targetStackContents[height] = stackElement(height, SourceLocation());
// Debug info: // Debug info:
//stream(cout, initialStackContents, targetStackContents); //stream(cout, initialStackContents, targetStackContents);
@ -111,30 +111,46 @@ void CommonSubexpressionEliminator::feedItem(AssemblyItem const& _item, bool _co
if (SemanticInformation::isDupInstruction(_item)) if (SemanticInformation::isDupInstruction(_item))
setStackElement( setStackElement(
m_stackHeight + 1, m_stackHeight + 1,
stackElement(m_stackHeight - int(instruction) + int(Instruction::DUP1)) stackElement(
m_stackHeight - int(instruction) + int(Instruction::DUP1),
_item.getLocation()
)
); );
else if (SemanticInformation::isSwapInstruction(_item)) else if (SemanticInformation::isSwapInstruction(_item))
swapStackElements( swapStackElements(
m_stackHeight, m_stackHeight,
m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1) m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1),
_item.getLocation()
); );
else if (instruction != Instruction::POP) else if (instruction != Instruction::POP)
{ {
vector<Id> arguments(info.args); vector<Id> arguments(info.args);
for (int i = 0; i < info.args; ++i) for (int i = 0; i < info.args; ++i)
arguments[i] = stackElement(m_stackHeight - i); arguments[i] = stackElement(m_stackHeight - i, _item.getLocation());
if (_item.instruction() == Instruction::SSTORE) if (_item.instruction() == Instruction::SSTORE)
storeInStorage(arguments[0], arguments[1]); storeInStorage(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::SLOAD) else if (_item.instruction() == Instruction::SLOAD)
setStackElement(m_stackHeight + _item.deposit(), loadFromStorage(arguments[0])); setStackElement(
m_stackHeight + _item.deposit(),
loadFromStorage(arguments[0], _item.getLocation())
);
else if (_item.instruction() == Instruction::MSTORE) else if (_item.instruction() == Instruction::MSTORE)
storeInMemory(arguments[0], arguments[1]); storeInMemory(arguments[0], arguments[1], _item.getLocation());
else if (_item.instruction() == Instruction::MLOAD) else if (_item.instruction() == Instruction::MLOAD)
setStackElement(m_stackHeight + _item.deposit(), loadFromMemory(arguments[0])); setStackElement(
m_stackHeight + _item.deposit(),
loadFromMemory(arguments[0], _item.getLocation())
);
else if (_item.instruction() == Instruction::SHA3) else if (_item.instruction() == Instruction::SHA3)
setStackElement(m_stackHeight + _item.deposit(), applySha3(arguments.at(0), arguments.at(1))); setStackElement(
m_stackHeight + _item.deposit(),
applySha3(arguments.at(0), arguments.at(1), _item.getLocation())
);
else else
setStackElement(m_stackHeight + _item.deposit(), m_expressionClasses.find(_item, arguments, _copyItem)); setStackElement(
m_stackHeight + _item.deposit(),
m_expressionClasses.find(_item, arguments, _copyItem)
);
} }
m_stackHeight += _item.deposit(); m_stackHeight += _item.deposit();
} }
@ -145,22 +161,27 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
if (!m_breakingItem || *m_breakingItem != AssemblyItem(Instruction::JUMPI)) if (!m_breakingItem || *m_breakingItem != AssemblyItem(Instruction::JUMPI))
return; return;
static AssemblyItem s_jump = Instruction::JUMP; SourceLocation const& location = m_breakingItem->getLocation();
AssemblyItem::JumpType jumpType = m_breakingItem->getJumpType();
Id condition = stackElement(m_stackHeight - 1); Id condition = stackElement(m_stackHeight - 1, location);
Id zero = m_expressionClasses.find(u256(0)); Id zero = m_expressionClasses.find(u256(0));
if (m_expressionClasses.knownToBeDifferent(condition, zero)) if (m_expressionClasses.knownToBeDifferent(condition, zero))
{ {
feedItem(Instruction::SWAP1, true); feedItem(AssemblyItem(Instruction::SWAP1, location), true);
feedItem(Instruction::POP, true); feedItem(AssemblyItem(Instruction::POP, location), true);
m_breakingItem = &s_jump;
AssemblyItem item(Instruction::JUMP, location);
item.setJumpType(jumpType);
m_breakingItem = m_expressionClasses.storeItem(item);
return; return;
} }
Id negatedCondition = m_expressionClasses.find(Instruction::ISZERO, {condition}); Id negatedCondition = m_expressionClasses.find(Instruction::ISZERO, {condition});
if (m_expressionClasses.knownToBeDifferent(negatedCondition, zero)) if (m_expressionClasses.knownToBeDifferent(negatedCondition, zero))
{ {
feedItem(Instruction::POP, true); AssemblyItem it(Instruction::POP, location);
feedItem(Instruction::POP, true); feedItem(it, true);
feedItem(it, true);
m_breakingItem = nullptr; m_breakingItem = nullptr;
} }
} }
@ -170,33 +191,43 @@ void CommonSubexpressionEliminator::setStackElement(int _stackHeight, Id _class)
m_stackElements[_stackHeight] = _class; m_stackElements[_stackHeight] = _class;
} }
void CommonSubexpressionEliminator::swapStackElements(int _stackHeightA, int _stackHeightB) void CommonSubexpressionEliminator::swapStackElements(
int _stackHeightA,
int _stackHeightB,
SourceLocation const& _location
)
{ {
assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements."); assertThrow(_stackHeightA != _stackHeightB, OptimizerException, "Swap on same stack elements.");
// ensure they are created // ensure they are created
stackElement(_stackHeightA); stackElement(_stackHeightA, _location);
stackElement(_stackHeightB); stackElement(_stackHeightB, _location);
swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]); swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]);
} }
ExpressionClasses::Id CommonSubexpressionEliminator::stackElement(int _stackHeight) ExpressionClasses::Id CommonSubexpressionEliminator::stackElement(
int _stackHeight,
SourceLocation const& _location
)
{ {
if (m_stackElements.count(_stackHeight)) if (m_stackElements.count(_stackHeight))
return m_stackElements.at(_stackHeight); return m_stackElements.at(_stackHeight);
// Stack element not found (not assigned yet), create new equivalence class. // Stack element not found (not assigned yet), create new equivalence class.
return m_stackElements[_stackHeight] = initialStackElement(_stackHeight); return m_stackElements[_stackHeight] = initialStackElement(_stackHeight, _location);
} }
ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement(int _stackHeight) ExpressionClasses::Id CommonSubexpressionEliminator::initialStackElement(
int _stackHeight,
SourceLocation const& _location
)
{ {
assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested."); assertThrow(_stackHeight <= 0, OptimizerException, "Initial stack element of positive height requested.");
assertThrow(_stackHeight > -16, StackTooDeepException, ""); assertThrow(_stackHeight > -16, StackTooDeepException, "");
// This is a special assembly item that refers to elements pre-existing on the initial stack. // This is a special assembly item that refers to elements pre-existing on the initial stack.
return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight))); return m_expressionClasses.find(AssemblyItem(dupInstruction(1 - _stackHeight), _location));
} }
void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value) void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value, SourceLocation const& _location)
{ {
if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value) if (m_storageContent.count(_slot) && m_storageContent[_slot] == _value)
// do not execute the storage if we know that the value is already there // do not execute the storage if we know that the value is already there
@ -210,22 +241,25 @@ void CommonSubexpressionEliminator::storeInStorage(Id _slot, Id _value)
if (m_expressionClasses.knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value) if (m_expressionClasses.knownToBeDifferent(storageItem.first, _slot) || storageItem.second == _value)
storageContents.insert(storageItem); storageContents.insert(storageItem);
m_storageContent = move(storageContents); m_storageContent = move(storageContents);
Id id = m_expressionClasses.find(Instruction::SSTORE, {_slot, _value}, true, m_sequenceNumber);
AssemblyItem item(Instruction::SSTORE, _location);
Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber);
m_storeOperations.push_back(StoreOperation(StoreOperation::Storage, _slot, m_sequenceNumber, id)); m_storeOperations.push_back(StoreOperation(StoreOperation::Storage, _slot, m_sequenceNumber, id));
m_storageContent[_slot] = _value; m_storageContent[_slot] = _value;
// increment a second time so that we get unique sequence numbers for writes // increment a second time so that we get unique sequence numbers for writes
m_sequenceNumber++; m_sequenceNumber++;
} }
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot) ExpressionClasses::Id CommonSubexpressionEliminator::loadFromStorage(Id _slot, SourceLocation const& _location)
{ {
if (m_storageContent.count(_slot)) if (m_storageContent.count(_slot))
return m_storageContent.at(_slot); return m_storageContent.at(_slot);
else
return m_storageContent[_slot] = m_expressionClasses.find(Instruction::SLOAD, {_slot}, true, m_sequenceNumber); AssemblyItem item(Instruction::SLOAD, _location);
return m_storageContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber);
} }
void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value) void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value, SourceLocation const& _location)
{ {
if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value) if (m_memoryContent.count(_slot) && m_memoryContent[_slot] == _value)
// do not execute the store if we know that the value is already there // do not execute the store if we know that the value is already there
@ -237,34 +271,45 @@ void CommonSubexpressionEliminator::storeInMemory(Id _slot, Id _value)
if (m_expressionClasses.knownToBeDifferentBy32(memoryItem.first, _slot)) if (m_expressionClasses.knownToBeDifferentBy32(memoryItem.first, _slot))
memoryContents.insert(memoryItem); memoryContents.insert(memoryItem);
m_memoryContent = move(memoryContents); m_memoryContent = move(memoryContents);
Id id = m_expressionClasses.find(Instruction::MSTORE, {_slot, _value}, true, m_sequenceNumber);
AssemblyItem item(Instruction::MSTORE, _location);
Id id = m_expressionClasses.find(item, {_slot, _value}, true, m_sequenceNumber);
m_storeOperations.push_back(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id)); m_storeOperations.push_back(StoreOperation(StoreOperation::Memory, _slot, m_sequenceNumber, id));
m_memoryContent[_slot] = _value; m_memoryContent[_slot] = _value;
// increment a second time so that we get unique sequence numbers for writes // increment a second time so that we get unique sequence numbers for writes
m_sequenceNumber++; m_sequenceNumber++;
} }
ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot) ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(Id _slot, SourceLocation const& _location)
{ {
if (m_memoryContent.count(_slot)) if (m_memoryContent.count(_slot))
return m_memoryContent.at(_slot); return m_memoryContent.at(_slot);
else
return m_memoryContent[_slot] = m_expressionClasses.find(Instruction::MLOAD, {_slot}, true, m_sequenceNumber); AssemblyItem item(Instruction::MLOAD, _location);
return m_memoryContent[_slot] = m_expressionClasses.find(item, {_slot}, true, m_sequenceNumber);
} }
CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(Id _start, Id _length) CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(
Id _start,
Id _length,
SourceLocation const& _location
)
{ {
AssemblyItem sha3Item(Instruction::SHA3, _location);
// Special logic if length is a short constant, otherwise we cannot tell. // Special logic if length is a short constant, otherwise we cannot tell.
u256 const* l = m_expressionClasses.knownConstant(_length); u256 const* l = m_expressionClasses.knownConstant(_length);
// unknown or too large length // unknown or too large length
if (!l || *l > 128) if (!l || *l > 128)
return m_expressionClasses.find(Instruction::SHA3, {_start, _length}, true, m_sequenceNumber); return m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber);
vector<Id> arguments; vector<Id> arguments;
for (u256 i = 0; i < *l; i += 32) for (u256 i = 0; i < *l; i += 32)
{ {
Id slot = m_expressionClasses.find(Instruction::ADD, {_start, m_expressionClasses.find(i)}); Id slot = m_expressionClasses.find(
arguments.push_back(loadFromMemory(slot)); AssemblyItem(Instruction::ADD, _location),
{_start, m_expressionClasses.find(i)}
);
arguments.push_back(loadFromMemory(slot, _location));
} }
if (m_knownSha3Hashes.count(arguments)) if (m_knownSha3Hashes.count(arguments))
return m_knownSha3Hashes.at(arguments); return m_knownSha3Hashes.at(arguments);
@ -276,10 +321,10 @@ CommonSubexpressionEliminator::Id CommonSubexpressionEliminator::applySha3(Id _s
for (Id a: arguments) for (Id a: arguments)
data += toBigEndian(*m_expressionClasses.knownConstant(a)); data += toBigEndian(*m_expressionClasses.knownConstant(a));
data.resize(size_t(*l)); data.resize(size_t(*l));
v = m_expressionClasses.find(u256(sha3(data))); v = m_expressionClasses.find(AssemblyItem(u256(sha3(data)), _location));
} }
else else
v = m_expressionClasses.find(Instruction::SHA3, {_start, _length}, true, m_sequenceNumber); v = m_expressionClasses.find(sha3Item, {_start, _length}, true, m_sequenceNumber);
return m_knownSha3Hashes[arguments] = v; return m_knownSha3Hashes[arguments] = v;
} }
@ -333,12 +378,13 @@ AssemblyItems CSECodeGenerator::generateCode(
assertThrow(position != c_invalidPosition, OptimizerException, ""); assertThrow(position != c_invalidPosition, OptimizerException, "");
if (position == targetItem.first) if (position == targetItem.first)
continue; continue;
SourceLocation const& location = m_expressionClasses.representative(targetItem.second).item->getLocation();
if (position < targetItem.first) if (position < targetItem.first)
// it is already at its target, we need another copy // it is already at its target, we need another copy
appendDup(position); appendDup(position, location);
else else
appendOrRemoveSwap(position); appendOrRemoveSwap(position, location);
appendOrRemoveSwap(targetItem.first); appendOrRemoveSwap(targetItem.first, location);
} }
// remove surplus elements // remove surplus elements
@ -404,7 +450,8 @@ void CSECodeGenerator::addDependencies(Id _c)
case Instruction::SHA3: case Instruction::SHA3:
{ {
Id length = expr.arguments.at(1); Id length = expr.arguments.at(1);
Id offsetToStart = m_expressionClasses.find(Instruction::SUB, {slot, slotToLoadFrom}); AssemblyItem offsetInstr(Instruction::SUB, expr.item->getLocation());
Id offsetToStart = m_expressionClasses.find(offsetInstr, {slot, slotToLoadFrom});
u256 const* o = m_expressionClasses.knownConstant(offsetToStart); u256 const* o = m_expressionClasses.knownConstant(offsetToStart);
u256 const* l = m_expressionClasses.knownConstant(length); u256 const* l = m_expressionClasses.knownConstant(length);
if (l && *l == 0) if (l && *l == 0)
@ -462,6 +509,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
for (Id arg: boost::adaptors::reverse(arguments)) for (Id arg: boost::adaptors::reverse(arguments))
generateClassElement(arg); generateClassElement(arg);
SourceLocation const& location = expr.item->getLocation();
// The arguments are somewhere on the stack now, so it remains to move them at the correct place. // The arguments are somewhere on the stack now, so it remains to move them at the correct place.
// This is quite difficult as sometimes, the values also have to removed in this process // This is quite difficult as sometimes, the values also have to removed in this process
// (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is // (if canBeRemoved() returns true) and the two arguments can be equal. For now, this is
@ -469,42 +517,42 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
if (arguments.size() == 1) if (arguments.size() == 1)
{ {
if (canBeRemoved(arguments[0], _c)) if (canBeRemoved(arguments[0], _c))
appendOrRemoveSwap(classElementPosition(arguments[0])); appendOrRemoveSwap(classElementPosition(arguments[0]), location);
else else
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
} }
else if (arguments.size() == 2) else if (arguments.size() == 2)
{ {
if (canBeRemoved(arguments[1], _c)) if (canBeRemoved(arguments[1], _c))
{ {
appendOrRemoveSwap(classElementPosition(arguments[1])); appendOrRemoveSwap(classElementPosition(arguments[1]), location);
if (arguments[0] == arguments[1]) if (arguments[0] == arguments[1])
appendDup(m_stackHeight); appendDup(m_stackHeight, location);
else if (canBeRemoved(arguments[0], _c)) else if (canBeRemoved(arguments[0], _c))
{ {
appendOrRemoveSwap(m_stackHeight - 1); appendOrRemoveSwap(m_stackHeight - 1, location);
appendOrRemoveSwap(classElementPosition(arguments[0])); appendOrRemoveSwap(classElementPosition(arguments[0]), location);
} }
else else
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
} }
else else
{ {
if (arguments[0] == arguments[1]) if (arguments[0] == arguments[1])
{ {
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
appendDup(m_stackHeight); appendDup(m_stackHeight, location);
} }
else if (canBeRemoved(arguments[0], _c)) else if (canBeRemoved(arguments[0], _c))
{ {
appendOrRemoveSwap(classElementPosition(arguments[0])); appendOrRemoveSwap(classElementPosition(arguments[0]), location);
appendDup(classElementPosition(arguments[1])); appendDup(classElementPosition(arguments[1]), location);
appendOrRemoveSwap(m_stackHeight - 1); appendOrRemoveSwap(m_stackHeight - 1, location);
} }
else else
{ {
appendDup(classElementPosition(arguments[1])); appendDup(classElementPosition(arguments[1]), location);
appendDup(classElementPosition(arguments[0])); appendDup(classElementPosition(arguments[0]), location);
} }
} }
} }
@ -521,7 +569,7 @@ int CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
!m_generatedItems.empty() && !m_generatedItems.empty() &&
m_generatedItems.back() == AssemblyItem(Instruction::SWAP1)) m_generatedItems.back() == AssemblyItem(Instruction::SWAP1))
// this will not append a swap but remove the one that is already there // this will not append a swap but remove the one that is already there
appendOrRemoveSwap(m_stackHeight - 1); appendOrRemoveSwap(m_stackHeight - 1, location);
for (auto arg: arguments) for (auto arg: arguments)
if (canBeRemoved(arg, _c)) if (canBeRemoved(arg, _c))
m_classPositions[arg] = c_invalidPosition; m_classPositions[arg] = c_invalidPosition;
@ -582,17 +630,17 @@ bool CSECodeGenerator::removeStackTopIfPossible()
return true; return true;
} }
void CSECodeGenerator::appendDup(int _fromPosition) void CSECodeGenerator::appendDup(int _fromPosition, SourceLocation const& _location)
{ {
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
int instructionNum = 1 + m_stackHeight - _fromPosition; int instructionNum = 1 + m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep."); assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(dupInstruction(instructionNum))); appendItem(AssemblyItem(dupInstruction(instructionNum), _location));
m_stack[m_stackHeight] = m_stack[_fromPosition]; m_stack[m_stackHeight] = m_stack[_fromPosition];
} }
void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition) void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location)
{ {
assertThrow(_fromPosition != c_invalidPosition, OptimizerException, ""); assertThrow(_fromPosition != c_invalidPosition, OptimizerException, "");
if (_fromPosition == m_stackHeight) if (_fromPosition == m_stackHeight)
@ -600,7 +648,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition)
int instructionNum = m_stackHeight - _fromPosition; int instructionNum = m_stackHeight - _fromPosition;
assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep."); assertThrow(instructionNum <= 16, StackTooDeepException, "Stack too deep.");
assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access."); assertThrow(1 <= instructionNum, OptimizerException, "Invalid stack access.");
appendItem(AssemblyItem(swapInstruction(instructionNum))); appendItem(AssemblyItem(swapInstruction(instructionNum), _location));
// The value of a class can be present in multiple locations on the stack. We only update the // The value of a class can be present in multiple locations on the stack. We only update the
// "canonical" one that is tracked by m_classPositions // "canonical" one that is tracked by m_classPositions
if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight) if (m_classPositions[m_stack[m_stackHeight]] == m_stackHeight)

20
libevmcore/CommonSubexpressionEliminator.h

@ -99,26 +99,26 @@ private:
/// Assigns a new equivalence class to the next sequence number of the given stack element. /// Assigns a new equivalence class to the next sequence number of the given stack element.
void setStackElement(int _stackHeight, Id _class); void setStackElement(int _stackHeight, Id _class);
/// Swaps the given stack elements in their next sequence number. /// Swaps the given stack elements in their next sequence number.
void swapStackElements(int _stackHeightA, int _stackHeightB); void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location);
/// Retrieves the current equivalence class fo the given stack element (or generates a new /// Retrieves the current equivalence class fo the given stack element (or generates a new
/// one if it does not exist yet). /// one if it does not exist yet).
Id stackElement(int _stackHeight); Id stackElement(int _stackHeight, SourceLocation const& _location);
/// @returns the equivalence class id of the special initial stack element at the given height /// @returns the equivalence class id of the special initial stack element at the given height
/// (must not be positive). /// (must not be positive).
Id initialStackElement(int _stackHeight); Id initialStackElement(int _stackHeight, SourceLocation const& _location);
/// Increments the sequence number, deletes all storage information that might be overwritten /// Increments the sequence number, deletes all storage information that might be overwritten
/// and stores the new value at the given slot. /// and stores the new value at the given slot.
void storeInStorage(Id _slot, Id _value); void storeInStorage(Id _slot, Id _value, SourceLocation const& _location);
/// Retrieves the current value at the given slot in storage or creates a new special sload class. /// Retrieves the current value at the given slot in storage or creates a new special sload class.
Id loadFromStorage(Id _slot); Id loadFromStorage(Id _slot, SourceLocation const& _location);
/// Increments the sequence number, deletes all memory information that might be overwritten /// Increments the sequence number, deletes all memory information that might be overwritten
/// and stores the new value at the given slot. /// and stores the new value at the given slot.
void storeInMemory(Id _slot, Id _value); void storeInMemory(Id _slot, Id _value, SourceLocation const& _location);
/// Retrieves the current value at the given slot in memory or creates a new special mload class. /// Retrieves the current value at the given slot in memory or creates a new special mload class.
Id loadFromMemory(Id _slot); Id loadFromMemory(Id _slot, SourceLocation const& _location);
/// Finds or creates a new expression that applies the sha3 hash function to the contents in memory. /// Finds or creates a new expression that applies the sha3 hash function to the contents in memory.
Id applySha3(Id _start, Id _length); Id applySha3(Id _start, Id _length, SourceLocation const& _location);
/// Current stack height, can be negative. /// Current stack height, can be negative.
int m_stackHeight = 0; int m_stackHeight = 0;
@ -188,10 +188,10 @@ private:
bool removeStackTopIfPossible(); bool removeStackTopIfPossible();
/// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position. /// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position.
void appendDup(int _fromPosition); void appendDup(int _fromPosition, SourceLocation const& _location);
/// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position. /// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position.
/// @note this might also remove the last item if it exactly the same swap instruction. /// @note this might also remove the last item if it exactly the same swap instruction.
void appendOrRemoveSwap(int _fromPosition); void appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location);
/// Appends the given assembly item. /// Appends the given assembly item.
void appendItem(AssemblyItem const& _item); void appendItem(AssemblyItem const& _item);

24
libevmcore/ExpressionClasses.cpp

@ -64,10 +64,7 @@ ExpressionClasses::Id ExpressionClasses::find(
return it->id; return it->id;
if (_copyItem) if (_copyItem)
{ exp.item = storeItem(_item);
m_spareAssemblyItem.push_back(make_shared<AssemblyItem>(_item));
exp.item = m_spareAssemblyItem.back().get();
}
ExpressionClasses::Id id = tryToSimplify(exp); ExpressionClasses::Id id = tryToSimplify(exp);
if (id < m_representatives.size()) if (id < m_representatives.size())
@ -115,6 +112,12 @@ u256 const* ExpressionClasses::knownConstant(Id _c)
return &constant.d(); return &constant.d();
} }
AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item)
{
m_spareAssemblyItems.push_back(make_shared<AssemblyItem>(_item));
return m_spareAssemblyItems.back().get();
}
string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
{ {
Expression const& expr = representative(_id); Expression const& expr = representative(_id);
@ -292,7 +295,7 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr,
//cout << "with rule " << rule.first.toString() << endl; //cout << "with rule " << rule.first.toString() << endl;
//ExpressionTemplate t(rule.second()); //ExpressionTemplate t(rule.second());
//cout << "to " << rule.second().toString() << endl; //cout << "to " << rule.second().toString() << endl;
return rebuildExpression(ExpressionTemplate(rule.second())); return rebuildExpression(ExpressionTemplate(rule.second(), _expr.item->getLocation()));
} }
} }
@ -350,6 +353,11 @@ bool Pattern::matches(Expression const& _expr, ExpressionClasses const& _classes
return true; return true;
} }
AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const
{
return AssemblyItem(m_type, m_data, _location);
}
string Pattern::toString() const string Pattern::toString() const
{ {
stringstream s; stringstream s;
@ -399,7 +407,7 @@ Pattern::Expression const& Pattern::matchGroupValue() const
} }
ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern) ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location)
{ {
if (_pattern.matchGroup()) if (_pattern.matchGroup())
{ {
@ -409,10 +417,10 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern)
else else
{ {
hasId = false; hasId = false;
item = _pattern.toAssemblyItem(); item = _pattern.toAssemblyItem(_location);
} }
for (auto const& arg: _pattern.arguments()) for (auto const& arg: _pattern.arguments())
arguments.push_back(ExpressionTemplate(arg)); arguments.push_back(ExpressionTemplate(arg, _location));
} }
string ExpressionTemplate::toString() const string ExpressionTemplate::toString() const

10
libevmcore/ExpressionClasses.h

@ -88,6 +88,10 @@ public:
/// and a nullptr otherwise. /// and a nullptr otherwise.
u256 const* knownConstant(Id _c); u256 const* knownConstant(Id _c);
/// Stores a copy of the given AssemblyItem and returns a pointer to the copy that is valid for
/// the lifetime of the ExpressionClasses object.
AssemblyItem const* storeItem(AssemblyItem const& _item);
std::string fullDAGToString(Id _id) const; std::string fullDAGToString(Id _id) const;
private: private:
@ -105,7 +109,7 @@ private:
std::vector<Expression> m_representatives; std::vector<Expression> m_representatives;
/// All expression ever encountered. /// All expression ever encountered.
std::set<Expression> m_expressions; std::set<Expression> m_expressions;
std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItem; std::vector<std::shared_ptr<AssemblyItem>> m_spareAssemblyItems;
}; };
/** /**
@ -134,7 +138,7 @@ public:
unsigned matchGroup() const { return m_matchGroup; } unsigned matchGroup() const { return m_matchGroup; }
bool matches(Expression const& _expr, ExpressionClasses const& _classes) const; bool matches(Expression const& _expr, ExpressionClasses const& _classes) const;
AssemblyItem toAssemblyItem() const { return AssemblyItem(m_type, m_data); } AssemblyItem toAssemblyItem(SourceLocation const& _location) const;
std::vector<Pattern> arguments() const { return m_arguments; } std::vector<Pattern> arguments() const { return m_arguments; }
/// @returns the id of the matched expression if this pattern is part of a match group. /// @returns the id of the matched expression if this pattern is part of a match group.
@ -163,7 +167,7 @@ struct ExpressionTemplate
{ {
using Expression = ExpressionClasses::Expression; using Expression = ExpressionClasses::Expression;
using Id = ExpressionClasses::Id; using Id = ExpressionClasses::Id;
explicit ExpressionTemplate(Pattern const& _pattern); explicit ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location);
std::string toString() const; std::string toString() const;
bool hasId = false; bool hasId = false;
/// Id of the matched expression, if available. /// Id of the matched expression, if available.

6
liblll/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE lll)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore) target_link_libraries(${EXECUTABLE} devcore)

6
libnatspec/CMakeLists.txt

@ -22,11 +22,7 @@ file(GLOB HEADERS "*.h")
qt5_add_resources(NATSPECQRC natspec.qrc) qt5_add_resources(NATSPECQRC natspec.qrc)
if (ETH_STATIC) add_library(${EXECUTABLE} ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS} ${NATSPECQRC})
add_library(${EXECUTABLE} STATIC ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS} ${NATSPECQRC})
else()
add_library(${EXECUTABLE} SHARED ${RESOURCE_ADDED} ${SRC_LIST} ${HEADERS} ${NATSPECQRC})
endif()
target_link_libraries(${EXECUTABLE} Qt5::Core) target_link_libraries(${EXECUTABLE} Qt5::Core)
target_link_libraries(${EXECUTABLE} Qt5::Qml) target_link_libraries(${EXECUTABLE} Qt5::Qml)

6
libp2p/CMakeLists.txt

@ -25,11 +25,7 @@ set(EXECUTABLE p2p)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
if (MINIUPNPC_FOUND) if (MINIUPNPC_FOUND)
target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${MINIUPNPC_LIBRARIES})

6
libserpent/CMakeLists.txt

@ -17,11 +17,7 @@ set(EXECUTABLE serpent)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if(ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} lll) target_link_libraries(${EXECUTABLE} lll)
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmcore)

6
libsolidity/AST.cpp

@ -817,7 +817,11 @@ void NewExpression::checkTypeRequirements(TypePointers const*)
BOOST_THROW_EXCEPTION(createTypeError("Trying to create an instance of an abstract contract.")); BOOST_THROW_EXCEPTION(createTypeError("Trying to create an instance of an abstract contract."));
shared_ptr<ContractType const> contractType = make_shared<ContractType>(*m_contract); shared_ptr<ContractType const> contractType = make_shared<ContractType>(*m_contract);
TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes(); TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes();
m_type = make_shared<FunctionType>(parameterTypes, TypePointers{contractType}, m_type = make_shared<FunctionType>(
parameterTypes,
TypePointers{contractType},
strings(),
strings(),
FunctionType::Location::Creation); FunctionType::Location::Creation);
} }

6
libsolidity/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE solidity)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})
target_link_libraries(${EXECUTABLE} evmcore) target_link_libraries(${EXECUTABLE} evmcore)

16
libsolidity/ExpressionCompiler.cpp

@ -521,8 +521,20 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arguments.front()->accept(*this); arguments.front()->accept(*this);
appendTypeConversion(*arguments.front()->getType(), appendTypeConversion(*arguments.front()->getType(),
*function.getParameterTypes().front(), true); *function.getParameterTypes().front(), true);
appendExternalFunctionCall(FunctionType(TypePointers{}, TypePointers{}, appendExternalFunctionCall(
Location::External, false, true, true), {}, true); FunctionType(
TypePointers{},
TypePointers{},
strings(),
strings(),
Location::External,
false,
true,
true
),
{},
true
);
break; break;
case Location::Suicide: case Location::Suicide:
arguments.front()->accept(*this); arguments.front()->accept(*this);

18
libsolidity/InterfaceHandler.cpp

@ -38,8 +38,7 @@ std::unique_ptr<std::string> InterfaceHandler::getDocumentation(ContractDefiniti
std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinition const& _contractDef) std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinition const& _contractDef)
{ {
Json::Value abi(Json::arrayValue); Json::Value abi(Json::arrayValue);
for (auto const& it: _contractDef.getInterfaceFunctions())
{
auto populateParameters = [](vector<string> const& _paramNames, vector<string> const& _paramTypes) auto populateParameters = [](vector<string> const& _paramNames, vector<string> const& _paramTypes)
{ {
Json::Value params(Json::arrayValue); Json::Value params(Json::arrayValue);
@ -54,6 +53,9 @@ std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinitio
return params; return params;
}; };
for (auto it: _contractDef.getInterfaceFunctions())
{
Json::Value method; Json::Value method;
method["type"] = "function"; method["type"] = "function";
method["name"] = it.second->getDeclaration().getName(); method["name"] = it.second->getDeclaration().getName();
@ -64,6 +66,18 @@ std::unique_ptr<std::string> InterfaceHandler::getABIInterface(ContractDefinitio
it.second->getReturnParameterTypeNames()); it.second->getReturnParameterTypeNames());
abi.append(method); abi.append(method);
} }
if (_contractDef.getConstructor())
{
Json::Value method;
method["type"] = "constructor";
auto externalFunction = FunctionType(*_contractDef.getConstructor()).externalFunctionType();
solAssert(!!externalFunction, "");
method["inputs"] = populateParameters(
externalFunction->getParameterNames(),
externalFunction->getParameterTypeNames()
);
abi.append(method);
}
for (auto const& it: _contractDef.getInterfaceEvents()) for (auto const& it: _contractDef.getInterfaceEvents())
{ {

43
libsolidity/Types.cpp

@ -1143,7 +1143,7 @@ FunctionTypePointer FunctionType::externalFunctionType() const
return FunctionTypePointer(); return FunctionTypePointer();
retParamTypes.push_back(type->externalType()); retParamTypes.push_back(type->externalType());
} }
return make_shared<FunctionType>(paramTypes, retParamTypes, m_location, m_arbitraryParameters); return make_shared<FunctionType>(paramTypes, retParamTypes, m_parameterNames, m_returnParameterNames, m_location, m_arbitraryParameters);
} }
MemberList const& FunctionType::getMembers() const MemberList const& FunctionType::getMembers() const
@ -1159,14 +1159,36 @@ MemberList const& FunctionType::getMembers() const
if (!m_members) if (!m_members)
{ {
MemberList::MemberMap members{ MemberList::MemberMap members{
{"value", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}), {
"value",
make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(false, true)}, TypePointers{copyAndSetGasOrValue(false, true)},
Location::SetValue, false, m_gasSet, m_valueSet)}}; strings(),
strings(),
Location::SetValue,
false,
m_gasSet,
m_valueSet
)
}
};
if (m_location != Location::Creation) if (m_location != Location::Creation)
members.push_back(MemberList::Member("gas", make_shared<FunctionType>( members.push_back(
MemberList::Member(
"gas",
make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}), parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(true, false)}, TypePointers{copyAndSetGasOrValue(true, false)},
Location::SetGas, false, m_gasSet, m_valueSet))); strings(),
strings(),
Location::SetGas,
false,
m_gasSet,
m_valueSet
)
)
);
m_members.reset(new MemberList(members)); m_members.reset(new MemberList(members));
} }
return *m_members; return *m_members;
@ -1244,9 +1266,16 @@ TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) const TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) const
{ {
return make_shared<FunctionType>(m_parameterTypes, m_returnParameterTypes, m_location, return make_shared<FunctionType>(
m_parameterTypes,
m_returnParameterTypes,
m_parameterNames,
m_returnParameterNames,
m_location,
m_arbitraryParameters, m_arbitraryParameters,
m_gasSet || _setGas, m_valueSet || _setValue); m_gasSet || _setGas,
m_valueSet || _setValue
);
} }
vector<string> const FunctionType::getParameterTypeNames() const vector<string> const FunctionType::getParameterTypeNames() const

23
libsolidity/Types.h

@ -564,13 +564,26 @@ public:
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);
explicit FunctionType(VariableDeclaration const& _varDecl); explicit FunctionType(VariableDeclaration const& _varDecl);
explicit FunctionType(EventDefinition const& _event); explicit FunctionType(EventDefinition const& _event);
FunctionType(strings const& _parameterTypes, strings const& _returnParameterTypes, FunctionType(
Location _location = Location::Internal, bool _arbitraryParameters = false): strings const& _parameterTypes,
FunctionType(parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes), strings const& _returnParameterTypes,
_location, _arbitraryParameters) {} Location _location = Location::Internal,
bool _arbitraryParameters = false
): FunctionType(
parseElementaryTypeVector(_parameterTypes),
parseElementaryTypeVector(_returnParameterTypes),
strings(),
strings(),
_location,
_arbitraryParameters
)
{
}
FunctionType( FunctionType(
TypePointers const& _parameterTypes, TypePointers const& _parameterTypes,
TypePointers const& _returnParameterTypes, TypePointers const& _returnParameterTypes,
strings _parameterNames = strings(),
strings _returnParameterNames = strings(),
Location _location = Location::Internal, Location _location = Location::Internal,
bool _arbitraryParameters = false, bool _arbitraryParameters = false,
bool _gasSet = false, bool _gasSet = false,
@ -578,6 +591,8 @@ public:
): ):
m_parameterTypes (_parameterTypes), m_parameterTypes (_parameterTypes),
m_returnParameterTypes (_returnParameterTypes), m_returnParameterTypes (_returnParameterTypes),
m_parameterNames (_parameterNames),
m_returnParameterNames (_returnParameterNames),
m_location (_location), m_location (_location),
m_arbitraryParameters (_arbitraryParameters), m_arbitraryParameters (_arbitraryParameters),
m_gasSet (_gasSet), m_gasSet (_gasSet),

6
libtestutils/CMakeLists.txt

@ -23,11 +23,7 @@ if (NOT JSONRPC)
list(REMOVE_ITEM HEADERS "./FixedWebThreeServer.h") list(REMOVE_ITEM HEADERS "./FixedWebThreeServer.h")
endif() endif()
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${Boost_FILESYSTEM_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})

6
libweb3jsonrpc/CMakeLists.txt

@ -20,11 +20,7 @@ set(EXECUTABLE web3jsonrpc)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else ()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif ()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})
target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${JSONCPP_LIBRARIES})

18
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -212,7 +212,16 @@ static dev::eth::LogFilter toLogFilter(Json::Value const& _json) // commented to
} }
if (!_json["topics"].empty()) if (!_json["topics"].empty())
for (unsigned i = 0; i < _json["topics"].size(); i++) for (unsigned i = 0; i < _json["topics"].size(); i++)
{
if (_json["topics"][i].isArray())
{
for (auto t: _json["topics"][i])
if (!t.isNull())
filter.topic(i, jsToFixed<32>(t.asString()));
}
else if (!_json["topics"][i].isNull()) // if it is anything else then string, it should and will fail
filter.topic(i, jsToFixed<32>(_json["topics"][i].asString())); filter.topic(i, jsToFixed<32>(_json["topics"][i].asString()));
}
return filter; return filter;
} }
@ -242,7 +251,16 @@ static shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m,
if (!_json["topics"].empty()) if (!_json["topics"].empty())
for (auto i: _json["topics"]) for (auto i: _json["topics"])
{
if (i.isArray())
{
for (auto j: i)
if (!j.isNull())
bt.shift(jsToBytes(j.asString()));
}
else if (!i.isNull()) // if it is anything else then string, it should and will fail
bt.shift(jsToBytes(i.asString())); bt.shift(jsToBytes(i.asString()));
}
return _m.seal(_from, bt, ttl, workToProve); return _m.seal(_from, bt, ttl, workToProve);
} }

6
libwebthree/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE webthree)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})

6
libwhisper/CMakeLists.txt

@ -19,11 +19,7 @@ set(EXECUTABLE whisper)
file(GLOB HEADERS "*.h") file(GLOB HEADERS "*.h")
if (ETH_STATIC) add_library(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_library(${EXECUTABLE} STATIC ${SRC_LIST} ${HEADERS})
else()
add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
endif()
target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${LEVELDB_LIBRARIES})

1
mix/qml/QBoolTypeView.qml

@ -6,6 +6,7 @@ Item
id: editRoot id: editRoot
property string value property string value
property string defaultValue property string defaultValue
property alias readOnly: !boolCombo.enabled
height: 20 height: 20
width: 150 width: 150

1
mix/qml/QHashTypeView.qml

@ -3,6 +3,7 @@ import QtQuick 2.0
Item Item
{ {
property alias value: textinput.text property alias value: textinput.text
property alias readOnly: textinput.readOnly
id: editRoot id: editRoot
height: 20 height: 20
width: 150 width: 150

11
mix/qml/QIntTypeView.qml

@ -1,12 +1,12 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Layouts 1.1
Item Item
{ {
property alias value: textinput.text property alias value: textinput.text
property alias readOnly: textinput.readOnly
id: editRoot id: editRoot
height: 20 height: 20
width: 150 width: readOnly ? textinput.implicitWidth : 150
SourceSansProBold SourceSansProBold
{ {
@ -22,12 +22,7 @@ Item
anchors.fill: parent anchors.fill: parent
font.family: boldFont.name font.family: boldFont.name
clip: true clip: true
MouseArea { selectByMouse: true
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
} }
} }
} }

10
mix/qml/QStringTypeView.qml

@ -3,9 +3,10 @@ import QtQuick 2.0
Item Item
{ {
property alias value: textinput.text property alias value: textinput.text
property alias readOnly: textinput.readOnly
id: editRoot id: editRoot
height: 20 height: 20
width: 150 width: readOnly ? textinput.implicitWidth : 150
SourceSansProBold SourceSansProBold
{ {
@ -22,12 +23,7 @@ Item
anchors.fill: parent anchors.fill: parent
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
font.family: boldFont.name font.family: boldFont.name
MouseArea { selectByMouse: true
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
} }
} }
} }

13
mix/qml/StructView.qml

@ -12,7 +12,7 @@ Column
property int transactionIndex property int transactionIndex
property string context property string context
Layout.fillWidth: true Layout.fillWidth: true
spacing: 10 spacing: 0
Repeater Repeater
{ {
id: repeater id: repeater
@ -22,7 +22,7 @@ Column
RowLayout RowLayout
{ {
id: row id: row
height: 30 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0) height: 20 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0)
Layout.fillWidth: true Layout.fillWidth: true
DefaultLabel { DefaultLabel {
height: 20 height: 20
@ -32,12 +32,14 @@ Column
} }
DefaultLabel { DefaultLabel {
height: 20
id: nameLabel id: nameLabel
text: modelData.name text: modelData.name
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
DefaultLabel { DefaultLabel {
height: 20
id: equalLabel id: equalLabel
text: "=" text: "="
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -45,6 +47,7 @@ Column
Loader Loader
{ {
id: typeLoader id: typeLoader
height: 20
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
sourceComponent: sourceComponent:
{ {
@ -69,10 +72,10 @@ Column
var ptype = members[index].type; var ptype = members[index].type;
var pname = members[index].name; var pname = members[index].name;
var vals = value; var vals = value;
item.readOnly = context === "variable";
if (ptype.category === QSolidityType.Address) if (ptype.category === QSolidityType.Address)
{ {
item.value = getValue(); item.value = getValue();
item.readOnly = context === "variable";
if (context === "parameter") if (context === "parameter")
{ {
var dec = modelData.type.name.split(" "); var dec = modelData.type.name.split(" ");
@ -119,6 +122,10 @@ Column
vals[pname] = item.value; vals[pname] = item.value;
valueChanged(); valueChanged();
}); });
var newWidth = nameLabel.width + typeLabel.width + item.width + 108;
if (root.width < newWidth)
root.width = newWidth;
} }
function getValue() function getValue()

2
mix/qml/VariablesView.qml

@ -18,12 +18,12 @@ DebugInfoList
property alias members: typeLoader.members; property alias members: typeLoader.members;
property alias value: typeLoader.value; property alias value: typeLoader.value;
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 8
StructView StructView
{ {
id: typeLoader id: typeLoader
members: [] members: []
value: {} value: {}
Layout.preferredWidth: parent.width
context: "variable" context: "variable"
width:parent.width width:parent.width
} }

18
secp256k1/CMakeLists.txt

@ -14,22 +14,14 @@ file(GLOB HEADERS "*.h")
if (APPLE OR UNIX) if (APPLE OR UNIX)
if (ETH_STATIC) add_library(${EXECUTABLE} ${EXECUTABLE}.c field_5x52_asm.asm)
add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm)
else()
add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM")
target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES})
elseif (CMAKE_COMPILER_IS_MINGW) elseif (CMAKE_COMPILER_IS_MINGW)
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
if (ETH_STATIC) add_library(${EXECUTABLE} ${EXECUTABLE}.c field_5x52_asm.asm)
add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c field_5x52_asm.asm)
else()
add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c field_5x52_asm.asm)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -W -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -W -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -DUSE_FIELD_GMP -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM")
target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES}) target_link_libraries(${EXECUTABLE} ${GMP_LIBRARIES})
@ -37,11 +29,7 @@ else()
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
if (ETH_STATIC) add_library(${EXECUTABLE} ${EXECUTABLE}.c)
add_library(${EXECUTABLE} STATIC ${EXECUTABLE}.c)
else()
add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c)
endif()
# /TP - compile project as cpp project # /TP - compile project as cpp project
set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP /wd4244") set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP /wd4244")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN")

6
solc/CMakeLists.txt

@ -19,9 +19,5 @@ target_link_libraries(${EXECUTABLE} solidity)
install( TARGETS ${EXECUTABLE} DESTINATION bin ) install( TARGETS ${EXECUTABLE} DESTINATION bin )
if (ETH_STATIC) add_library(soljson jsonCompiler.cpp ${HEADERS})
add_library(soljson STATIC jsonCompiler.cpp ${HEADERS})
else()
add_library(soljson SHARED jsonCompiler.cpp ${HEADERS})
endif()
target_link_libraries(soljson solidity) target_link_libraries(soljson solidity)

30
test/libsolidity/SolidityABIJSON.cpp

@ -495,6 +495,36 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
checkInterface(sourceCode, interface); checkInterface(sourceCode, interface);
} }
BOOST_AUTO_TEST_CASE(constructor_abi)
{
char const* sourceCode = R"(
contract test {
function test(uint param1, test param2, bool param3) {}
}
)";
char const* interface = R"([
{
"inputs": [
{
"name": "param1",
"type": "uint256"
},
{
"name": "param2",
"type": "address"
},
{
"name": "param3",
"type": "bool"
}
],
"type": "constructor"
}
])";
checkInterface(sourceCode, interface);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }

16
test/libsolidity/SolidityOptimizer.cpp

@ -22,6 +22,7 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <memory>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <test/libsolidity/solidityExecutionFramework.h> #include <test/libsolidity/solidityExecutionFramework.h>
@ -84,9 +85,20 @@ public:
AssemblyItems getCSE(AssemblyItems const& _input) AssemblyItems getCSE(AssemblyItems const& _input)
{ {
// add dummy locations to each item so that we can check that they are not deleted
AssemblyItems input = _input;
for (AssemblyItem& item: input)
item.setLocation(SourceLocation(1, 3, make_shared<string>("")));
eth::CommonSubexpressionEliminator cse; eth::CommonSubexpressionEliminator cse;
BOOST_REQUIRE(cse.feedItems(_input.begin(), _input.end()) == _input.end()); BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end());
return cse.getOptimizedItems(); AssemblyItems output = cse.getOptimizedItems();
for (AssemblyItem const& item: output)
{
BOOST_CHECK(item == Instruction::POP || !item.getLocation().isEmpty());
}
return output;
} }
void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation) void checkCSE(AssemblyItems const& _input, AssemblyItems const& _expectation)

Loading…
Cancel
Save