diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 2b27c6e32..2a13e4a64 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -329,6 +329,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::CALLDATALOAD: + { + auto index = stack.pop(); + auto value = ext.calldataload(index); + stack.push(value); + break; + } + case Instruction::GASPRICE: { auto value = ext.gasprice(); diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 9011ac694..616bde402 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -74,7 +74,7 @@ int ExecutionEngine::run(std::unique_ptr _module) ext->origin = dev::Address(101010101010101010); ext->value = 0xabcd; ext->gasPrice = 1002; - std::string calldata = "Hello World!"; + std::string calldata = "Hello the Beautiful World of Ethereum!"; ext->data = calldata; Ext::init(std::move(ext)); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 309ef21a3..0c38f73d3 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -69,6 +69,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder) m_init = Function::Create(FunctionType::get(m_builder.getVoidTy(), extDataTy->getPointerTo(), false), Linkage::ExternalLinkage, "ext_init", module); m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); + m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); m_builder.CreateCall(m_init, m_data); } @@ -100,6 +101,13 @@ Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } Value* Ext::calldatasize() { return getDataElem(5, "calldatasize"); } Value* Ext::gasprice() { return getDataElem(4, "gasprice"); } +Value* Ext::calldataload(Value* _index) +{ + m_builder.CreateStore(_index, m_args[0]); + m_builder.CreateCall(m_calldataload, m_args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -128,6 +136,16 @@ EXPORT void ext_setStore(i256* _index, i256* _value) g_ext->setStore(index, value); } +EXPORT void ext_calldataload(i256* _index, i256* _value) +{ + auto index = static_cast(llvm2eth(*_index)); + assert(index + 31 > index); // TODO: Handle large index + auto b = reinterpret_cast(_value); + for (size_t i = index, j = 31; i <= index + 31; ++i, --j) + b[j] = i < g_ext->data.size() ? g_ext->data[i] : 0; + // TODO: It all can be done by adding padding to data or by using min() algorithm without branch +} + } } \ No newline at end of file diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 60efe9f6f..a579dca81 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -26,6 +26,8 @@ public: llvm::Value* calldatasize(); llvm::Value* gasprice(); + llvm::Value* calldataload(llvm::Value* _index); + private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -37,6 +39,7 @@ private: llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; + llvm::Function* m_calldataload; }; diff --git a/evmcc/Utils.h b/evmcc/Utils.h index 065698448..8233ac9e3 100644 --- a/evmcc/Utils.h +++ b/evmcc/Utils.h @@ -9,6 +9,7 @@ namespace evmcc { /// Representation of 256-bit value binary compatible with LLVM i256 +// TODO: Replace with h256 struct i256 { uint64_t a; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index afbe4e752..ccca5e56b 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -30333234363a +30333234363a600035602635601335 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 27dceabde..f6680f2a7 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -6,4 +6,10 @@ ORIGIN CALLVALUE CALLDATASIZE GASPRICE +0 +CALLDATALOAD +38 +CALLDATALOAD +19 +CALLDATALOAD ) \ No newline at end of file