mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc
Conflicts: libevmjit/Compiler.cpp
This commit is contained in:
commit
b6b4f5f639
5 changed files with 35 additions and 36 deletions
|
|
@ -345,7 +345,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod
|
|||
case Instruction::BNOT:
|
||||
{
|
||||
auto value = stack.pop();
|
||||
auto ret = m_builder.CreateXor(value, llvm::APInt(256, -1, true), "bnot");
|
||||
auto ret = m_builder.CreateXor(value, Constant::get(-1), "bnot");
|
||||
stack.push(ret);
|
||||
break;
|
||||
}
|
||||
|
|
@ -760,12 +760,9 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod
|
|||
|
||||
_gasMeter.commitCostBlock(gas);
|
||||
|
||||
// Require _memory for the max of in and out buffers
|
||||
auto inSizeReq = m_builder.CreateAdd(inOff, inSize, "inSizeReq");
|
||||
auto outSizeReq = m_builder.CreateAdd(outOff, outSize, "outSizeReq");
|
||||
auto cmp = m_builder.CreateICmpUGT(inSizeReq, outSizeReq);
|
||||
auto sizeReq = m_builder.CreateSelect(cmp, inSizeReq, outSizeReq, "sizeReq");
|
||||
_memory.require(sizeReq);
|
||||
// Require memory for in and out buffers
|
||||
memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one
|
||||
memory.require(inOff, inSize);
|
||||
|
||||
auto receiveAddress = codeAddress;
|
||||
if (inst == Instruction::CALLCODE)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <llvm/IR/GlobalVariable.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/IntrinsicInst.h>
|
||||
|
||||
#include <libdevcore/Common.h>
|
||||
|
||||
|
|
@ -28,8 +29,7 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
|
|||
RuntimeHelper(_runtimeManager)
|
||||
{
|
||||
auto module = getModule();
|
||||
auto i64Ty = m_builder.getInt64Ty();
|
||||
llvm::Type* argTypes[] = {i64Ty, i64Ty};
|
||||
llvm::Type* argTypes[] = {Type::i256, Type::i256};
|
||||
auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
|
||||
m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_dump", module);
|
||||
|
|
@ -54,28 +54,41 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
|
|||
|
||||
llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager)
|
||||
{
|
||||
auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
|
||||
llvm::Type* argTypes[] = {Type::i256, Type::i256};
|
||||
auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
|
||||
auto offset = func->arg_begin();
|
||||
offset->setName("offset");
|
||||
auto size = offset->getNextNode();
|
||||
size->setName("size");
|
||||
|
||||
auto checkBB = llvm::BasicBlock::Create(func->getContext(), "check", func);
|
||||
auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func);
|
||||
auto returnBB = llvm::BasicBlock::Create(func->getContext(), "return", func);
|
||||
auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
|
||||
auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
|
||||
auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);
|
||||
|
||||
InsertPointGuard guard(m_builder); // Restores insert point at function exit
|
||||
|
||||
// BB "check"
|
||||
m_builder.SetInsertPoint(checkBB);
|
||||
llvm::Value* sizeRequired = func->arg_begin();
|
||||
sizeRequired->setName("sizeRequired");
|
||||
auto size = m_builder.CreateLoad(m_size, "size");
|
||||
auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded");
|
||||
auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::i256);
|
||||
auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res");
|
||||
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 resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded");
|
||||
m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?
|
||||
|
||||
// BB "resize"
|
||||
m_builder.SetInsertPoint(resizeBB);
|
||||
// Check gas first
|
||||
auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired");
|
||||
sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeRequired");
|
||||
auto words = m_builder.CreateUDiv(size, Constant::get(32), "words"); // size is always 32*k
|
||||
uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res");
|
||||
auto wordsRequired = m_builder.CreateExtractValue(uaddRes, 0);
|
||||
auto overflow2 = m_builder.CreateExtractValue(uaddRes, 1, "overflow2");
|
||||
auto overflow = m_builder.CreateOr(overflow1, overflow2, "overflow");
|
||||
wordsRequired = m_builder.CreateSelect(overflow, Constant::get(-1), wordsRequired);
|
||||
wordsRequired = m_builder.CreateUDiv(wordsRequired, Constant::get(32), "wordsReq");
|
||||
sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq");
|
||||
auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words"); // size is always 32*k
|
||||
auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
|
||||
_gasMeter.checkMemory(newWords, m_builder);
|
||||
// Resize
|
||||
|
|
@ -164,15 +177,9 @@ llvm::Value* Memory::getSize()
|
|||
return m_builder.CreateLoad(m_size);
|
||||
}
|
||||
|
||||
void Memory::require(llvm::Value* _size)
|
||||
{
|
||||
m_builder.CreateCall(m_require, _size);
|
||||
}
|
||||
|
||||
void Memory::require(llvm::Value* _offset, llvm::Value* _size)
|
||||
{
|
||||
auto sizeRequired = m_builder.CreateAdd(_offset, _size, "sizeRequired");
|
||||
require(sizeRequired);
|
||||
m_builder.CreateCall2(m_require, _offset, _size);
|
||||
}
|
||||
|
||||
void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
|
||||
|
|
@ -180,8 +187,7 @@ void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value*
|
|||
{
|
||||
auto zero256 = llvm::ConstantInt::get(Type::i256, 0);
|
||||
|
||||
auto reqMemSize = m_builder.CreateAdd(_destMemIdx, _reqBytes, "req_mem_size");
|
||||
require(reqMemSize);
|
||||
require(_destMemIdx, _reqBytes);
|
||||
|
||||
auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx");
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ public:
|
|||
void copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIndex,
|
||||
llvm::Value* _destMemIdx, llvm::Value* _byteCount);
|
||||
|
||||
/// Requires this amount of memory. And counts gas fee for that memory.
|
||||
void require(llvm::Value* _size);
|
||||
|
||||
/// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory.
|
||||
void require(llvm::Value* _offset, llvm::Value* _size);
|
||||
|
||||
|
|
@ -36,7 +33,6 @@ private:
|
|||
llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter);
|
||||
llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
|
||||
|
||||
private:
|
||||
llvm::GlobalVariable* m_data;
|
||||
llvm::GlobalVariable* m_size;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ void Type::init(llvm::LLVMContext& _context)
|
|||
RuntimePtr = RuntimeData::getType()->getPointerTo();
|
||||
}
|
||||
|
||||
llvm::ConstantInt* Constant::get(uint64_t _n)
|
||||
llvm::ConstantInt* Constant::get(int64_t _n)
|
||||
{
|
||||
return llvm::ConstantInt::get(Type::i256, _n);
|
||||
return llvm::ConstantInt::getSigned(Type::i256, _n);
|
||||
}
|
||||
|
||||
llvm::ConstantInt* Constant::get(u256 _n)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ enum class ReturnCode
|
|||
struct Constant
|
||||
{
|
||||
/// Returns word-size constant
|
||||
static llvm::ConstantInt* get(uint64_t _n);
|
||||
static llvm::ConstantInt* get(int64_t _n);
|
||||
static llvm::ConstantInt* get(u256 _n);
|
||||
|
||||
static llvm::ConstantInt* get(ReturnCode _returnCode);
|
||||
|
|
|
|||
Loading…
Reference in a new issue