6 #include <llvm/IR/Module.h> 7 #include <llvm/ADT/StringSwitch.h> 8 #include <llvm/ADT/Triple.h> 9 #include <llvm/ExecutionEngine/MCJIT.h> 10 #include <llvm/ExecutionEngine/SectionMemoryManager.h> 11 #include <llvm/Support/TargetSelect.h> 12 #include <llvm/Support/Host.h> 13 #include <llvm/Support/CommandLine.h> 14 #include <llvm/Support/ManagedStatic.h> 22 #include "BuildInfo.gen.h" 25 static_assert(
sizeof(
evm_uint256be) == 32,
"evm_uint256be is too big");
26 static_assert(
sizeof(
evm_uint160be) == 20,
"evm_uint160be is too big");
27 static_assert(
sizeof(
evm_result) <= 64,
"evm_result does not fit cache line");
31 static_assert(
sizeof(
evm_query_key) ==
sizeof(
int),
"Enum `evm_query_key` is not the size of int");
32 static_assert(
sizeof(
evm_update_key) ==
sizeof(
int),
"Enum `evm_update_key` is not the size of int");
33 static_assert(
sizeof(
evm_call_kind) ==
sizeof(
int),
"Enum `evm_call_kind` is not the size of int");
34 static_assert(
sizeof(
evm_mode) ==
sizeof(
int),
"Enum `evm_mode` is not the size of int");
41 using namespace eth::jit;
45 using ExecFunc =
ReturnCode(*)(ExecutionContext*);
56 LLVM_BUILTIN_UNREACHABLE;
62 static const auto hexChars =
"0123456789abcdef";
64 str.reserve(
sizeof(codeHash) * 2 + 1);
65 for (
auto b: codeHash.
bytes)
67 str.push_back(hexChars[
b & 0xf]);
68 str.push_back(hexChars[
b >> 4]);
70 str.push_back(modeToChar(mode));
76 std::cout <<
"Ethereum EVM JIT Compiler (http://github.com/ethereum/evmjit):\n" 77 <<
" EVMJIT version " << EVMJIT_VERSION <<
"\n" 79 <<
" Optimized build, " 83 << __DATE__ <<
" (" << __TIME__ <<
")\n" 87 namespace cl = llvm::cl;
88 cl::opt<bool> g_optimize{
"O", cl::desc{
"Optimize"}};
89 cl::opt<CacheMode> g_cache{
"cache", cl::desc{
"Cache compiled EVM code on disk"},
93 clEnumValN(
CacheMode::read,
"r",
"Read only. No new objects are added to cache."),
94 clEnumValN(
CacheMode::write,
"w",
"Write only. No objects are loaded from cache."),
95 clEnumValN(
CacheMode::clear,
"c",
"Clear the cache storage. Cache is disabled."),
98 cl::opt<bool> g_stats{
"st", cl::desc{
"Statistics"}};
99 cl::opt<bool> g_dump{
"dump", cl::desc{
"Dump LLVM IR module"}};
103 static llvm::llvm_shutdown_obj shutdownObj{};
104 cl::AddExtraVersionPrinter(printVersion);
105 cl::ParseEnvironmentOptions(
"evmjit",
"EVMJIT",
"Ethereum EVM JIT Compiler");
114 static llvm::LLVMContext& getLLVMContext()
118 static llvm::LLVMContext llvmContext;
123 static JITImpl& instance()
127 static JITImpl s_instance;
133 llvm::ExecutionEngine& engine() {
return *
m_engine; }
135 ExecFunc getExecFunc(std::string
const& _codeIdentifier)
const;
136 void mapExecFunc(std::string
const& _codeIdentifier, ExecFunc _funcAddr);
138 ExecFunc compile(
evm_mode _mode,
byte const* _code, uint64_t _codeSize, std::string
const& _codeIdentifier);
146 class SymbolResolver :
public llvm::SectionMemoryManager
148 llvm::RuntimeDyld::SymbolInfo findSymbol(std::string
const& _name)
override 150 auto& jit = JITImpl::instance();
151 auto addr = llvm::StringSwitch<uint64_t>(_name)
152 .Case(
"env_sha3", reinterpret_cast<uint64_t>(&
keccak))
153 .Case(
"evm.query", reinterpret_cast<uint64_t>(jit.queryFn))
154 .Case(
"evm.update", reinterpret_cast<uint64_t>(jit.updateFn))
155 .Case(
"evm.call", reinterpret_cast<uint64_t>(jit.callFn))
158 return {addr, llvm::JITSymbolFlags::Exported};
164 return llvm::SectionMemoryManager::findSymbol(_name);
167 void reportMemorySize(
size_t _addedSize)
175 static const auto M = 1024 * 1024;
177 std::cerr <<
"EVMJIT total memory size: " << value <<
'\n';
182 uint8_t* allocateCodeSection(uintptr_t _size,
unsigned _a,
unsigned _id,
183 llvm::StringRef _name)
override 185 reportMemorySize(_size);
186 return llvm::SectionMemoryManager::allocateCodeSection(_size, _a, _id, _name);
189 uint8_t* allocateDataSection(uintptr_t _size,
unsigned _a,
unsigned _id,
190 llvm::StringRef _name,
bool _ro)
override 192 reportMemorySize(_size);
193 return llvm::SectionMemoryManager::allocateDataSection(_size, _a, _id, _name, _ro);
203 ExecFunc JITImpl::getExecFunc(std::string
const& _codeIdentifier)
const 205 std::lock_guard<std::mutex> lock{
x_codeMap};
206 auto it =
m_codeMap.find(_codeIdentifier);
212 void JITImpl::mapExecFunc(std::string
const& _codeIdentifier, ExecFunc _funcAddr)
214 std::lock_guard<std::mutex> lock{
x_codeMap};
215 m_codeMap.emplace(_codeIdentifier, _funcAddr);
218 ExecFunc JITImpl::compile(
evm_mode _mode,
byte const* _code, uint64_t _codeSize,
219 std::string
const& _codeIdentifier)
226 assert(_code || !_codeSize);
228 module = Compiler({}, _mode, getLLVMContext()).compile(_code, _code + _codeSize, _codeIdentifier);
241 m_engine->addModule(std::move(module));
243 return (ExecFunc)
m_engine->getFunctionAddress(_codeIdentifier);
252 std::free(m_memData);
257 auto data = m_data->callData;
258 auto size =
static_cast<size_t>(m_data->callDataSize);
260 if (data < m_memData || data >= m_memData + m_memSize ||
size == 0)
263 m_data->callData =
nullptr;
279 auto& jit = JITImpl::instance();
289 assert(instance == static_cast<void*>(&JITImpl::instance()));
292 static void release_result(
evm_result const* result)
300 int64_t gas, uint8_t
const* input,
size_t input_size,
evm_uint256be value)
302 auto& jit = *
reinterpret_cast<JITImpl*
>(instance);
321 result.
release = release_result;
323 auto codeIdentifier = makeCodeId(code_hash, mode);
324 auto execFunc = jit.getExecFunc(codeIdentifier);
327 execFunc = jit.compile(mode, ctx.code(), ctx.codeSize(), codeIdentifier);
330 jit.mapExecFunc(codeIdentifier, execFunc);
333 auto returnCode = execFunc(&ctx);
349 auto out = ctx.getReturnData();
356 ctx.m_memData =
nullptr;
364 (void)instance, (
void)
name, (void)value;
371 auto& jit = *
reinterpret_cast<JITImpl*
>(instance);
372 auto codeIdentifier = makeCodeId(code_hash, mode);
373 if (jit.getExecFunc(codeIdentifier) !=
nullptr)
380 evm_uint256be code_hash,
unsigned char const* code,
size_t code_size)
382 auto& jit = *
reinterpret_cast<JITImpl*
>(instance);
383 auto codeIdentifier = makeCodeId(code_hash, mode);
384 auto execFunc = jit.compile(mode, code, code_size, codeIdentifier);
386 jit.mapExecFunc(codeIdentifier, execFunc);
399 evmjit::get_code_status,
400 evmjit::prepare_code,
409 llvm::InitializeNativeTarget();
410 llvm::InitializeNativeTargetAsmPrinter();
412 auto module = llvm::make_unique<llvm::Module>(
"", getLLVMContext());
415 auto triple = llvm::Triple(llvm::sys::getProcessTriple());
416 if (triple.getOS() == llvm::Triple::OSType::Win32)
417 triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);
418 module->setTargetTriple(triple.str());
420 llvm::EngineBuilder builder(std::move(module));
421 builder.setEngineKind(llvm::EngineKind::JIT);
422 builder.setMCJITMemoryManager(llvm::make_unique<SymbolResolver>());
423 builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);
425 builder.setVerifyModules(
true);
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
~ExecutionContext() noexcept
uint8_t bytes[32]
The 32 bytes of the big-endian integer or hash.
Big-endian 256-bit integer.
char const * error_message
The error message explaining the result code.
bool prepare(llvm::Module &_module)
uint8_t const * output_data
The reference to output data.
void keccak(uint8_t const *_data, uint64_t _size, uint8_t *o_hash)
int64_t gas_left
The amount of gas left after the execution.
assert(len-trim+(2 *lenIndices)<=WIDTH)
evm_release_result_fn release
The pointer to the result release implementation.
Execution finished with success.
The code has been compiled and is available in memory.
evm_code_status
Status of a code in VM. Useful for JIT-like implementations.
std::unordered_map< std::string, ExecFunc > m_codeMap
size_t m_printMemoryLimit
evm_update_key
The update callback key.
static std::unique_ptr< llvm::Module > getObject(std::string const &id, llvm::LLVMContext &_llvmContext)
The EVM instance factory.
enum evm_result_code code
The execution result code.
size_t output_size
The size of the output data.
void * internal_memory
The pointer to EVM-owned memory.
Big-endian 160-bit hash suitable for keeping an Ethereum address.
evm_call_kind
The kind of call-like instruction.
evm_mode
EVM compatibility mode aka chain mode.
The EVM code execution result.
EXPORT evm_factory evmjit_get_factory()
Get EVMJIT instance.
std::tuple< byte const *, size_t > bytes_ref
uint8_t const size_t const size
void(* evm_update_fn)(struct evm_env *env, enum evm_update_key key, const union evm_variant *arg1, const union evm_variant *arg2)
Update callback function.
void * memcpy(void *a, const void *b, size_t c)
static ObjectCache * init(CacheMode _mode, JITListener *_listener)
bool optimize(llvm::Module &_module)
void(* evm_query_fn)(union evm_variant *result, struct evm_env *env, enum evm_query_key key, const union evm_variant *arg)
Query callback function.
The code is uknown to the VM.
evm_query_key
The query callback key.
int64_t(* evm_call_fn)(struct evm_env *env, enum evm_call_kind kind, int64_t gas, const struct evm_uint160be *address, const struct evm_uint256be *value, uint8_t const *input, size_t input_size, uint8_t *output, size_t output_size)
Pointer to the callback function supporting EVM calls.
std::unique_ptr< llvm::ExecutionEngine > m_engine
Generic execution failure.
bytes_ref getReturnData() const