Browse Source

Merge branch 'develop-evmcc' into pr-jit

cl-refactor
Paweł Bylica 10 years ago
parent
commit
363c79a9a0
  1. 5
      evmcc/CMakeLists.txt
  2. 166
      evmcc/evmcc.cpp
  3. 142
      libevmjit/BasicBlock.cpp
  4. 59
      libevmjit/BasicBlock.h
  5. 15
      libevmjit/Compiler.cpp
  6. 2
      libevmjit/Memory.cpp
  7. 1
      libevmjit/Runtime.cpp
  8. 96
      test/jsonrpc.cpp
  9. 2
      windows/LLVM.props
  10. 2
      windows/bootstrap.sh
  11. 3
      windows/evmcc.vcxproj

5
evmcc/CMakeLists.txt

@ -8,6 +8,7 @@ set(EXECUTABLE evmcc)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} boost_program_options)
target_link_libraries(${EXECUTABLE} devcore)
target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} ethereum)
@ -40,8 +41,8 @@ message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
# llvm_map_components_to_libnames(llvm_libs core support mcjit x86asmparser x86codegen)
# target_link_libraries(evmcc ${llvm_libs})
llvm_map_components_to_libnames(llvm_libs bitwriter)
target_link_libraries(evmcc ${llvm_libs})
# end of LLVM specific commands

166
evmcc/evmcc.cpp

@ -7,6 +7,10 @@
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/raw_os_ostream.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
@ -15,67 +19,76 @@
#include <libevmjit/ExecutionEngine.h>
void show_usage()
void parseProgramOptions(int _argc, char** _argv, boost::program_options::variables_map& _varMap)
{
// FIXME: Use arg[0] as program name?
std::cerr << "usage: evmcc (-b|-c|-d)+ <inputfile.bc>\n";
}
namespace opt = boost::program_options;
opt::options_description explicitOpts("Allowed options");
explicitOpts.add_options()
("help,h", "show usage information")
("compile,c", "compile the code to LLVM IR")
("interpret,i", "compile the code to LLVM IR and execute")
("gas,g", opt::value<size_t>(), "set initial gas for execution")
("disassemble,d", "dissassemble the code")
("dump-cfg", "dump control flow graph to graphviz file")
("optimize-stack,os", "optimize stack use between basic blocks")
("output-ll", opt::value<std::string>(), "dump generated LLVM IR to file")
("output-bc", opt::value<std::string>(), "dump generated LLVM bitcode to file")
("verbose,V", "enable verbose output");
opt::options_description implicitOpts("Input files");
implicitOpts.add_options()
("input-file", opt::value<std::string>(), "input file");
opt::options_description allOpts("");
allOpts.add(explicitOpts).add(implicitOpts);
opt::positional_options_description inputOpts;
inputOpts.add("input-file", 1);
const char* errorMsg = nullptr;
try
{
auto parser = opt::command_line_parser(_argc, _argv).options(allOpts).positional(inputOpts);
opt::store(parser.run(), _varMap);
opt::notify(_varMap);
}
catch (boost::program_options::error& err)
{
errorMsg = err.what();
}
if (!errorMsg && _varMap.count("input-file") == 0)
errorMsg = "missing input file name";
int main(int argc, char** argv)
{
std::string input_file;
bool opt_dissassemble = false;
bool opt_show_bytes = false;
bool opt_compile = false;
bool opt_interpret = false;
bool opt_dump_graph = false;
bool opt_unknown = false;
bool opt_verbose = false;
size_t initialGas = 10000;
for (int i = 1; i < argc; i++)
if (_varMap.count("disassemble") == 0
&& _varMap.count("compile") == 0
&& _varMap.count("interpret") == 0)
{
std::string option = argv[i];
if (option == "-b")
opt_show_bytes = true;
else if (option == "-c")
opt_compile = true;
else if (option == "-d")
opt_dissassemble = true;
else if (option == "-i")
opt_interpret = true;
else if (option == "--dump-cfg")
opt_dump_graph = true;
else if (option == "-g" && i + 1 < argc)
{
std::string gasValue = argv[++i];
initialGas = boost::lexical_cast<size_t>(gasValue);
std::cerr << "Initial gas set to " << initialGas << "\n";
}
else if (option == "-v")
opt_verbose = true;
else if (option[0] != '-' && input_file.empty())
input_file = option;
else
{
opt_unknown = true;
break;
}
errorMsg = "at least one of -c, -i, -d is required";
}
if (opt_unknown ||
input_file.empty() ||
(!opt_show_bytes && !opt_compile && !opt_dissassemble && !opt_interpret))
if (errorMsg || _varMap.count("help"))
{
show_usage();
exit(1);
if (errorMsg)
std::cerr << "Error: " << errorMsg << std::endl;
std::cout << "Usage: " << _argv[0] << " <options> input-file " << std::endl
<< explicitOpts << std::endl;
std::exit(errorMsg ? 1 : 0);
}
}
int main(int argc, char** argv)
{
boost::program_options::variables_map options;
parseProgramOptions(argc, argv, options);
std::ifstream ifs(input_file);
auto inputFile = options["input-file"].as<std::string>();
std::ifstream ifs(inputFile);
if (!ifs.is_open())
{
std::cerr << "cannot open file " << input_file << std::endl;
std::cerr << "cannot open input file " << inputFile << std::endl;
exit(1);
}
@ -88,37 +101,70 @@ int main(int argc, char** argv)
bytes bytecode = fromHex(src);
if (opt_show_bytes)
std::cout << memDump(bytecode) << std::endl;
if (opt_dissassemble)
if (options.count("disassemble"))
{
std::string assembly = eth::disassemble(bytecode);
std::cout << assembly << std::endl;
}
if (opt_compile || opt_interpret)
if (options.count("compile") || options.count("interpret"))
{
size_t initialGas = 10000;
if (options.count("gas"))
initialGas = options["gas"].as<size_t>();
auto compilationStartTime = std::chrono::high_resolution_clock::now();
eth::jit::Compiler::Options options;
options.dumpCFG = opt_dump_graph;
eth::jit::Compiler::Options compilerOptions;
compilerOptions.dumpCFG = options.count("dump-cfg") > 0;
compilerOptions.optimizeStack = options.count("optimize-stack") > 0;
auto compiler = eth::jit::Compiler(options);
auto compiler = eth::jit::Compiler(compilerOptions);
auto module = compiler.compile({bytecode.data(), bytecode.size()});
auto compilationEndTime = std::chrono::high_resolution_clock::now();
module->dump();
if (opt_verbose)
if (options.count("output-ll"))
{
auto outputFile = options["output-ll"].as<std::string>();
std::ofstream ofs(outputFile);
if (!ofs.is_open())
{
std::cerr << "cannot open output file " << outputFile << std::endl;
exit(1);
}
llvm::raw_os_ostream ros(ofs);
module->print(ros, nullptr);
ofs.close();
}
if (options.count("output-bc"))
{
auto outputFile = options["output-bc"].as<std::string>();
std::ofstream ofs(outputFile);
if (!ofs.is_open())
{
std::cerr << "cannot open output file " << outputFile << std::endl;
exit(1);
}
llvm::raw_os_ostream ros(ofs);
llvm::WriteBitcodeToFile(module.get(), ros);
ros.flush();
ofs.close();
}
if (options.count("verbose"))
{
std::cerr << "*** Compilation time: "
<< std::chrono::duration_cast<std::chrono::microseconds>(compilationEndTime - compilationStartTime).count()
<< std::endl;
}
if (opt_interpret)
if (options.count("interpret"))
{
auto engine = eth::jit::ExecutionEngine();
u256 gas = initialGas;

142
libevmjit/BasicBlock.cpp

@ -26,38 +26,36 @@ BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx,
m_beginInstIdx(_beginInstIdx),
m_endInstIdx(_endInstIdx),
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)),
m_stack(_builder, m_llvmBB)
m_stack(*this),
m_builder(_builder)
{}
BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) :
m_beginInstIdx(0),
m_endInstIdx(0),
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
m_stack(_builder, m_llvmBB)
m_stack(*this),
m_builder(_builder)
{}
BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) :
m_llvmBB(_llvmBB),
m_builder(_builder),
m_initialStack(),
m_currentStack(),
m_tosOffset(0)
BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) :
m_bblock(_owner)
{}
void BasicBlock::LocalStack::push(llvm::Value* _value)
{
m_currentStack.push_back(_value);
m_tosOffset += 1;
m_bblock.m_currentStack.push_back(_value);
m_bblock.m_tosOffset += 1;
}
llvm::Value* BasicBlock::LocalStack::pop()
{
auto result = get(0);
if (m_currentStack.size() > 0)
m_currentStack.pop_back();
if (m_bblock.m_currentStack.size() > 0)
m_bblock.m_currentStack.pop_back();
m_tosOffset -= 1;
m_bblock.m_tosOffset -= 1;
return result;
}
@ -83,7 +81,56 @@ void BasicBlock::LocalStack::swap(size_t _index)
set(0, val);
}
void BasicBlock::LocalStack::synchronize(Stack& _evmStack)
std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index)
{
auto& currentStack = m_bblock.m_currentStack;
if (_index < currentStack.size())
return currentStack.end() - _index - 1;
// Need to map more elements from the EVM stack
auto nNewItems = 1 + _index - currentStack.size();
currentStack.insert(currentStack.begin(), nNewItems, nullptr);
return currentStack.end() - _index - 1;
}
llvm::Value* BasicBlock::LocalStack::get(size_t _index)
{
auto& initialStack = m_bblock.m_initialStack;
auto itemIter = getItemIterator(_index);
if (*itemIter == nullptr)
{
// Need to fetch a new item from the EVM stack
assert(static_cast<int>(_index) >= m_bblock.m_tosOffset);
size_t initialIdx = _index - m_bblock.m_tosOffset;
if (initialIdx >= initialStack.size())
{
auto nNewItems = 1 + initialIdx - initialStack.size();
initialStack.insert(initialStack.end(), nNewItems, nullptr);
}
assert(initialStack[initialIdx] == nullptr);
// Create a dummy value.
std::string name = "get_" + boost::lexical_cast<std::string>(_index);
initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, name);
*itemIter = initialStack[initialIdx];
}
return *itemIter;
}
void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
{
auto itemIter = getItemIterator(_index);
*itemIter = _word;
}
void BasicBlock::synchronizeLocalStack(Stack& _evmStack)
{
auto blockTerminator = m_llvmBB->getTerminator();
assert(blockTerminator != nullptr);
@ -141,51 +188,6 @@ void BasicBlock::LocalStack::synchronize(Stack& _evmStack)
m_tosOffset = 0;
}
std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index)
{
if (_index < m_currentStack.size())
return m_currentStack.end() - _index - 1;
// Need to map more elements from the EVM stack
auto nNewItems = 1 + _index - m_currentStack.size();
m_currentStack.insert(m_currentStack.begin(), nNewItems, nullptr);
return m_currentStack.end() - _index - 1;
}
llvm::Value* BasicBlock::LocalStack::get(size_t _index)
{
auto itemIter = getItemIterator(_index);
if (*itemIter == nullptr)
{
// Need to fetch a new item from the EVM stack
assert(static_cast<int>(_index) >= m_tosOffset);
size_t initialIdx = _index - m_tosOffset;
if (initialIdx >= m_initialStack.size())
{
auto nNewItems = 1 + initialIdx - m_initialStack.size();
m_initialStack.insert(m_initialStack.end(), nNewItems, nullptr);
}
assert(m_initialStack[initialIdx] == nullptr);
// Create a dummy value.
std::string name = "get_" + boost::lexical_cast<std::string>(_index);
m_initialStack[initialIdx] = m_builder.CreatePHI(Type::Word, 0, name);
*itemIter = m_initialStack[initialIdx];
}
return *itemIter;
}
void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
{
auto itemIter = getItemIterator(_index);
*itemIter = _word;
}
void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
struct BBInfo
@ -202,14 +204,14 @@ void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRB
inputItems(0),
outputItems(0)
{
auto& initialStack = bblock.localStack().m_initialStack;
auto& initialStack = bblock.m_initialStack;
for (auto it = initialStack.begin();
it != initialStack.end() && *it != nullptr;
++it, ++inputItems);
//if (bblock.localStack().m_tosOffset > 0)
// outputItems = bblock.localStack().m_tosOffset;
auto& exitStack = bblock.localStack().m_currentStack;
auto& exitStack = bblock.m_currentStack;
for (auto it = exitStack.rbegin();
it != exitStack.rend() && *it != nullptr;
++it, ++outputItems);
@ -281,7 +283,7 @@ void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRB
auto& bblock = info.bblock;
llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
auto phiIter = bblock.localStack().m_initialStack.begin();
auto phiIter = bblock.m_initialStack.begin();
for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
{
assert(llvm::isa<llvm::PHINode>(*phiIter));
@ -289,7 +291,7 @@ void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRB
for (auto predIt : info.predecessors)
{
auto& predExitStack = predIt->bblock.localStack().m_currentStack;
auto& predExitStack = predIt->bblock.m_currentStack;
auto value = *(predExitStack.end() - 1 - index);
phi->addIncoming(value, predIt->bblock.llvm());
}
@ -305,10 +307,10 @@ void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRB
// The items pulled directly from predecessors block must be removed
// from the list of items that has to be popped from the initial stack.
auto& initialStack = bblock.localStack().m_initialStack;
auto& initialStack = bblock.m_initialStack;
initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
// Initial stack shrinks, so the size difference grows:
bblock.localStack().m_tosOffset += info.inputItems;
bblock.m_tosOffset += info.inputItems;
}
// We must account for the items that were pushed directly to successor
@ -319,9 +321,9 @@ void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRB
auto& info = entry.second;
auto& bblock = info.bblock;
auto& exitStack = bblock.localStack().m_currentStack;
auto& exitStack = bblock.m_currentStack;
exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
bblock.localStack().m_tosOffset -= info.outputItems;
bblock.m_tosOffset -= info.outputItems;
}
}
@ -335,7 +337,7 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
llvm::raw_os_ostream out(_out);
out << (_dotOutput ? "" : "Initial stack:\n");
for (auto val : m_stack.m_initialStack)
for (auto val : m_initialStack)
{
if (val == nullptr)
out << " ?";
@ -352,11 +354,11 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
out << *ins << (_dotOutput ? "\\l" : "\n");
if (! _dotOutput)
out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n";
out << "Current stack (offset = " << m_tosOffset << "):\n";
else
out << "|";
for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val)
for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val)
{
if (*val == nullptr)
out << " ?";

59
libevmjit/BasicBlock.h

@ -21,7 +21,6 @@ public:
class LocalStack
{
public:
/// Pushes value on stack
void push(llvm::Value* _value);
@ -35,12 +34,8 @@ public:
/// @param _index Index of value to be swaped. Must be > 0.
void swap(size_t _index);
/// Synchronize current local stack with the EVM stack.
void synchronize(Stack& _evmStack);
private:
LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB);
LocalStack(BasicBlock& _owner);
LocalStack(LocalStack const&) = delete;
void operator=(LocalStack const&) = delete;
friend BasicBlock;
@ -54,34 +49,7 @@ public:
std::vector<llvm::Value*>::iterator getItemIterator(size_t _index);
private:
llvm::BasicBlock* m_llvmBB;
llvm::IRBuilder<>& m_builder;
/**
* This stack contains LLVM values that correspond to items found at
* the EVM stack when the current basic block starts executing.
* Location 0 corresponds to the top of the EVM stack, location 1 is
* the item below the top and so on. The stack grows as the code
* accesses more items on the EVM stack but once a value is put on
* the stack, it will never be replaced.
*/
std::vector<llvm::Value*> m_initialStack;
/**
* This stack tracks the contents of the EVM stack as the current basic
* block executes. It may grow on both sides, as the code pushes items on
* top of the stack or changes existing items.
*/
std::vector<llvm::Value*> m_currentStack;
/**
* How many items higher is the current stack than the initial one.
* May be negative.
*/
int m_tosOffset;
BasicBlock& m_bblock;
};
/// Basic block name prefix. The rest is beging instruction index.
@ -105,6 +73,9 @@ public:
/// to avoid excessive pushing/popping on the EVM stack.
static void linkLocalStacks(std::vector<BasicBlock*> _basicBlocks, llvm::IRBuilder<>& _builder);
/// Synchronize current local stack with the EVM stack.
void synchronizeLocalStack(Stack& _evmStack);
/// Prints local stack and block instructions to stderr.
/// Useful for calling in a debugger session.
void dump();
@ -113,11 +84,31 @@ public:
private:
ProgramCounter const m_beginInstIdx;
ProgramCounter const m_endInstIdx;
llvm::BasicBlock* const m_llvmBB;
/// Basic black state vector (stack) - current/end values and their positions on stack
/// @internal Must be AFTER m_llvmBB
LocalStack m_stack;
llvm::IRBuilder<>& m_builder;
/// This stack contains LLVM values that correspond to items found at
/// the EVM stack when the current basic block starts executing.
/// Location 0 corresponds to the top of the EVM stack, location 1 is
/// the item below the top and so on. The stack grows as the code
/// accesses more items on the EVM stack but once a value is put on
/// the stack, it will never be replaced.
std::vector<llvm::Value*> m_initialStack = {};
/// This stack tracks the contents of the EVM stack as the basic block
/// executes. It may grow on both sides, as the code pushes items on
/// top of the stack or changes existing items.
std::vector<llvm::Value*> m_currentStack = {};
/// How many items higher is the current stack than the initial one.
/// May be negative.
int m_tosOffset = 0;
};
}

15
libevmjit/Compiler.cpp

@ -81,12 +81,9 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode)
case Instruction::JUMPDEST:
{
// A basic block starts at the next instruction.
if (currentPC + 1 < _bytecode.size())
{
splitPoints.insert(currentPC + 1);
indirectJumpTargets.push_back(currentPC + 1);
}
// A basic block starts here.
splitPoints.insert(currentPC);
indirectJumpTargets.push_back(currentPC);
break;
}
@ -98,9 +95,7 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode)
{
// Create a basic block starting at the following instruction.
if (curr + 1 < _bytecode.end())
{
splitPoints.insert(currentPC + 1);
}
break;
}
@ -234,9 +229,9 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef _bytecode)
}
for (auto& entry : basicBlocks)
entry.second.localStack().synchronize(stack);
entry.second.synchronizeLocalStack(stack);
if (m_jumpTableBlock)
m_jumpTableBlock->localStack().synchronize(stack);
m_jumpTableBlock->synchronizeLocalStack(stack);
dumpCFGifRequired("blocks-sync.dot");

2
libevmjit/Memory.cpp

@ -74,7 +74,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _
auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq");
auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1");
auto currSize = m_builder.CreateLoad(m_size, "currSize");
auto tooSmall = m_builder.CreateICmpULE(size, sizeRequired, "tooSmall");
auto tooSmall = m_builder.CreateICmpULE(currSize, sizeRequired, "tooSmall");
auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded");
m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

1
libevmjit/Runtime.cpp

@ -105,7 +105,6 @@ bytesConstRef Runtime::getReturnData() const
RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
{
m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt");
llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()};
m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp);
// Export data

96
test/jsonrpc.cpp

@ -43,44 +43,39 @@ using namespace dev;
using namespace dev::eth;
namespace js = json_spirit;
namespace jsonrpc_tests
{
string name = "Ethereum(++) tests";
string dbPath;
auto s = set<string>{"eth", "shh"};
dev::p2p::NetworkPreferences np(30303, std::string(), false);
dev::WebThreeDirect web3(name, dbPath, true, s, np);
WebThreeDirect *web3;
unique_ptr<WebThreeStubServer> jsonrpcServer;
unique_ptr<WebThreeStubClient> jsonrpcClient;
struct JsonrpcFixture {
JsonrpcFixture()
struct Setup
{
Setup()
{
cnote << "setup jsonrpc";
static bool setup = false;
if (setup)
return;
setup = true;
web3.setIdealPeerCount(5);
web3.ethereum()->setForceMining(true);
jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), web3, {}));
dev::p2p::NetworkPreferences nprefs(30303, std::string(), false);
web3 = new WebThreeDirect("Ethereum(++) tests", "", true, {"eth", "shh"}, nprefs);
web3->setIdealPeerCount(5);
web3->ethereum()->setForceMining(true);
jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), *web3, {}));
jsonrpcServer->setIdentities({});
jsonrpcServer->StartListening();
jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080")));
}
~JsonrpcFixture()
{
cnote << "teardown jsonrpc";
}
};
BOOST_GLOBAL_FIXTURE(JsonrpcFixture)
BOOST_FIXTURE_TEST_SUITE(environment, Setup)
BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock)
{
cnote << "Testing jsonrpc defaultBlock...";
int defaultBlock = jsonrpcClient->defaultBlock();
BOOST_CHECK_EQUAL(defaultBlock, web3.ethereum()->getDefault());
BOOST_CHECK_EQUAL(defaultBlock, web3->ethereum()->getDefault());
}
BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice)
@ -94,26 +89,26 @@ BOOST_AUTO_TEST_CASE(jsonrpc_isListening)
{
cnote << "Testing jsonrpc isListening...";
web3.startNetwork();
web3->startNetwork();
bool listeningOn = jsonrpcClient->listening();
BOOST_CHECK_EQUAL(listeningOn, web3.isNetworkStarted());
BOOST_CHECK_EQUAL(listeningOn, web3->isNetworkStarted());
web3.stopNetwork();
web3->stopNetwork();
bool listeningOff = jsonrpcClient->listening();
BOOST_CHECK_EQUAL(listeningOff, web3.isNetworkStarted());
BOOST_CHECK_EQUAL(listeningOff, web3->isNetworkStarted());
}
BOOST_AUTO_TEST_CASE(jsonrpc_isMining)
{
cnote << "Testing jsonrpc isMining...";
web3.ethereum()->startMining();
web3->ethereum()->startMining();
bool miningOn = jsonrpcClient->mining();
BOOST_CHECK_EQUAL(miningOn, web3.ethereum()->isMining());
BOOST_CHECK_EQUAL(miningOn, web3->ethereum()->isMining());
web3.ethereum()->stopMining();
web3->ethereum()->stopMining();
bool miningOff = jsonrpcClient->mining();
BOOST_CHECK_EQUAL(miningOff, web3.ethereum()->isMining());
BOOST_CHECK_EQUAL(miningOff, web3->ethereum()->isMining());
}
BOOST_AUTO_TEST_CASE(jsonrpc_accounts)
@ -139,18 +134,18 @@ BOOST_AUTO_TEST_CASE(jsonrpc_number)
{
cnote << "Testing jsonrpc number2...";
int number = jsonrpcClient->number();
BOOST_CHECK_EQUAL(number, web3.ethereum()->number() + 1);
dev::eth::mine(*(web3.ethereum()), 1);
BOOST_CHECK_EQUAL(number, web3->ethereum()->number() + 1);
dev::eth::mine(*(web3->ethereum()), 1);
int numberAfter = jsonrpcClient->number();
BOOST_CHECK_EQUAL(number + 1, numberAfter);
BOOST_CHECK_EQUAL(numberAfter, web3.ethereum()->number() + 1);
BOOST_CHECK_EQUAL(numberAfter, web3->ethereum()->number() + 1);
}
BOOST_AUTO_TEST_CASE(jsonrpc_peerCount)
{
cnote << "Testing jsonrpc peerCount...";
int peerCount = jsonrpcClient->peerCount();
BOOST_CHECK_EQUAL(web3.peerCount(), peerCount);
BOOST_CHECK_EQUAL(web3->peerCount(), peerCount);
}
BOOST_AUTO_TEST_CASE(jsonrpc_setListening)
@ -158,10 +153,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_setListening)
cnote << "Testing jsonrpc setListening...";
jsonrpcClient->setListening(true);
BOOST_CHECK_EQUAL(web3.isNetworkStarted(), true);
BOOST_CHECK_EQUAL(web3->isNetworkStarted(), true);
jsonrpcClient->setListening(false);
BOOST_CHECK_EQUAL(web3.isNetworkStarted(), false);
BOOST_CHECK_EQUAL(web3->isNetworkStarted(), false);
}
BOOST_AUTO_TEST_CASE(jsonrpc_setMining)
@ -169,10 +164,10 @@ BOOST_AUTO_TEST_CASE(jsonrpc_setMining)
cnote << "Testing jsonrpc setMining...";
jsonrpcClient->setMining(true);
BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), true);
BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), true);
jsonrpcClient->setMining(false);
BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), false);
BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), false);
}
BOOST_AUTO_TEST_CASE(jsonrpc_stateAt)
@ -181,36 +176,36 @@ BOOST_AUTO_TEST_CASE(jsonrpc_stateAt)
dev::KeyPair key = KeyPair::create();
auto address = key.address();
string stateAt = jsonrpcClient->stateAt(toJS(address), "0");
BOOST_CHECK_EQUAL(toJS(web3.ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt);
BOOST_CHECK_EQUAL(toJS(web3->ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt);
}
BOOST_AUTO_TEST_CASE(jsonrpc_transact)
{
cnote << "Testing jsonrpc transact...";
string coinbase = jsonrpcClient->coinbase();
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address());
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());
dev::KeyPair key = KeyPair::create();
auto address = key.address();
auto receiver = KeyPair::create();
web3.ethereum()->setAddress(address);
web3->ethereum()->setAddress(address);
coinbase = jsonrpcClient->coinbase();
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address());
BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());
BOOST_CHECK_EQUAL(jsToAddress(coinbase), address);
jsonrpcServer->setAccounts({key});
auto balance = web3.ethereum()->balanceAt(address, 0);
auto balance = web3->ethereum()->balanceAt(address, 0);
string balanceString = jsonrpcClient->balanceAt(toJS(address));
double countAt = jsonrpcClient->countAt(toJS(address));
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address));
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
BOOST_CHECK_EQUAL(countAt, 0);
BOOST_CHECK_EQUAL(toJS(balance), balanceString);
BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0");
dev::eth::mine(*(web3.ethereum()), 1);
balance = web3.ethereum()->balanceAt(address, 0);
dev::eth::mine(*(web3->ethereum()), 1);
balance = web3->ethereum()->balanceAt(address, 0);
balanceString = jsonrpcClient->balanceAt(toJS(address));
BOOST_CHECK_EQUAL(toJS(balance), balanceString);
@ -230,21 +225,20 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact)
jsonrpcClient->transact(t);
jsonrpcServer->setAccounts({});
dev::eth::mine(*(web3.ethereum()), 1);
dev::eth::mine(*(web3->ethereum()), 1);
countAt = jsonrpcClient->countAt(toJS(address));
auto balance2 = web3.ethereum()->balanceAt(receiver.address());
auto balance2 = web3->ethereum()->balanceAt(receiver.address());
string balanceString2 = jsonrpcClient->balanceAt(toJS(receiver.address()));
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address));
BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
BOOST_CHECK_EQUAL(countAt, 1);
BOOST_CHECK_EQUAL(toJS(balance2), balanceString2);
BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000");
BOOST_CHECK_EQUAL(txAmount, balance2);
}
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()
#endif

2
windows/LLVM.props

@ -7,7 +7,7 @@
<LLVMBuildDir>../../_build/llvm/$(Platform)</LLVMBuildDir>
<LLVMIncludeDir>$(LLVMSrcDir)\include;$(LLVMBuildDir)\include</LLVMIncludeDir>
<LLVMLibDir>$(LLVMBuildDir)\$(Configuration)\lib</LLVMLibDir>
<LLVMLibs Condition="'$(LLVMEnabled)' == '1'">LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib</LLVMLibs>
<LLVMLibs Condition="'$(LLVMEnabled)' == '1'">LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib</LLVMLibs>
</PropertyGroup>
<PropertyGroup />
<ItemDefinitionGroup>

2
windows/bootstrap.sh

@ -152,7 +152,7 @@ compile_boost()
fi
if [ ! -d "stage/$platform" ]; then
targets="--with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test"
targets="--with-filesystem --with-system --with-thread --with-date_time --with-regex --with-test --with-program_options"
(set -x; ./b2 -j4 --build-type=complete link=static runtime-link=shared variant=debug,release threading=multi $addressModel $targets stage)
(set -x; mv stage/lib stage/$platform)
fi

3
windows/evmcc.vcxproj

@ -119,7 +119,6 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -138,7 +137,6 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -158,7 +156,6 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>LibEthereum.lib;LibEvmJit.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

Loading…
Cancel
Save