4 #include <llvm/IR/IntrinsicInst.h> 5 #include <llvm/IR/Module.h> 22 m_memoryMan(_memoryMan)
32 using FuncDesc = std::tuple<char const*, llvm::FunctionType*>;
34 llvm::FunctionType* getFunctionType(llvm::Type* _returnType, std::initializer_list<llvm::Type*>
const& _argsTypes)
36 return llvm::FunctionType::get(_returnType, llvm::ArrayRef<llvm::Type*>{_argsTypes.begin(), _argsTypes.size()},
false);
39 std::array<FuncDesc, sizeOf<EnvFunc>::value>
const& getEnvFuncDescs()
41 static std::array<FuncDesc, sizeOf<EnvFunc>::value> descs{{
47 FuncDesc{
"env_call", getFunctionType(
Type::Bool, {
Type::EnvPtr,
Type::GasPtr,
Type::Gas,
Type::WordPtr,
Type::WordPtr,
Type::WordPtr,
Type::WordPtr,
Type::WordPtr,
Type::BytePtr,
Type::Size,
Type::BytePtr, Type::Size})},
56 llvm::Function* createFunc(
EnvFunc _id, llvm::Module* _module)
58 auto&& desc = getEnvFuncDescs()[
static_cast<size_t>(_id)];
59 return llvm::Function::Create(std::get<1>(desc), llvm::Function::ExternalLinkage, std::get<0>(desc), _module);
62 llvm::Function* getQueryFunc(llvm::Module* _module)
64 static const auto funcName =
"evm.query";
65 auto func = _module->getFunction(funcName);
69 auto i32 = llvm::IntegerType::getInt32Ty(_module->getContext());
71 func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
72 func->addAttribute(1, llvm::Attribute::NoAlias);
73 func->addAttribute(1, llvm::Attribute::NoCapture);
74 func->addAttribute(4, llvm::Attribute::ReadOnly);
75 func->addAttribute(4, llvm::Attribute::NoAlias);
76 func->addAttribute(4, llvm::Attribute::NoCapture);
81 llvm::Function* getUpdateFunc(llvm::Module* _module)
83 static const auto funcName =
"evm.update";
84 auto func = _module->getFunction(funcName);
87 auto i32 = llvm::IntegerType::getInt32Ty(_module->getContext());
89 func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
90 func->addAttribute(3, llvm::Attribute::ReadOnly);
91 func->addAttribute(3, llvm::Attribute::NoAlias);
92 func->addAttribute(3, llvm::Attribute::NoCapture);
93 func->addAttribute(4, llvm::Attribute::ReadOnly);
94 func->addAttribute(4, llvm::Attribute::NoAlias);
95 func->addAttribute(4, llvm::Attribute::NoCapture);
100 llvm::StructType* getMemRefTy(llvm::Module* _module)
102 static const auto name =
"evm.memref";
103 auto ty = _module->getTypeByName(
name);
109 llvm::Function* getCallFunc(llvm::Module* _module)
111 static const auto funcName =
"call";
112 auto func = _module->getFunction(funcName);
115 auto i32 = llvm::IntegerType::getInt32Ty(_module->getContext());
116 auto hash160Ty = llvm::IntegerType::getIntNTy(_module->getContext(), 160);
117 auto fty = llvm::FunctionType::get(
121 func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage,
"evm.call", _module);
122 func->addAttribute(4, llvm::Attribute::ReadOnly);
123 func->addAttribute(4, llvm::Attribute::NoAlias);
124 func->addAttribute(4, llvm::Attribute::NoCapture);
125 func->addAttribute(5, llvm::Attribute::ReadOnly);
126 func->addAttribute(5, llvm::Attribute::NoAlias);
127 func->addAttribute(5, llvm::Attribute::NoCapture);
128 func->addAttribute(6, llvm::Attribute::ReadOnly);
129 func->addAttribute(6, llvm::Attribute::NoCapture);
130 func->addAttribute(8, llvm::Attribute::NoCapture);
131 auto callFunc = func;
134 func = llvm::Function::Create(fty, llvm::Function::PrivateLinkage, funcName, _module);
135 func->addAttribute(4, llvm::Attribute::ReadOnly);
136 func->addAttribute(4, llvm::Attribute::NoAlias);
137 func->addAttribute(4, llvm::Attribute::NoCapture);
138 func->addAttribute(5, llvm::Attribute::ReadOnly);
139 func->addAttribute(5, llvm::Attribute::NoAlias);
140 func->addAttribute(5, llvm::Attribute::NoCapture);
141 func->addAttribute(6, llvm::Attribute::ReadOnly);
142 func->addAttribute(6, llvm::Attribute::NoCapture);
143 func->addAttribute(8, llvm::Attribute::NoCapture);
145 auto iter = func->arg_begin();
147 std::advance(iter, 1);
148 auto& callKind = *iter;
149 std::advance(iter, 1);
151 std::advance(iter, 2);
152 auto& valuePtr = *iter;
154 auto& ctx = _module->getContext();
155 llvm::IRBuilder<> builder(ctx);
156 auto entryBB = llvm::BasicBlock::Create(ctx,
"Entry", func);
157 auto checkTransferBB = llvm::BasicBlock::Create(ctx,
"CheckTransfer", func);
158 auto checkBalanceBB = llvm::BasicBlock::Create(ctx,
"CheckBalance", func);
159 auto callBB = llvm::BasicBlock::Create(ctx,
"Call", func);
160 auto failBB = llvm::BasicBlock::Create(ctx,
"Fail", func);
162 builder.SetInsertPoint(entryBB);
165 auto queryFn = getQueryFunc(_module);
168 auto depthPtr = builder.CreateBitCast(v, builder.getInt64Ty()->getPointerTo());
169 auto depth = builder.CreateLoad(depthPtr);
170 auto depthOk = builder.CreateICmpSLT(depth, builder.getInt64(1024));
171 builder.CreateCondBr(depthOk, checkTransferBB, failBB);
173 builder.SetInsertPoint(checkTransferBB);
174 auto notDelegateCall = builder.CreateICmpNE(&callKind, builder.getInt32(
EVM_DELEGATECALL));
175 llvm::Value* value = builder.CreateLoad(&valuePtr);
176 auto valueNonZero = builder.CreateICmpNE(value,
Constant::get(0));
177 auto transfer = builder.CreateAnd(notDelegateCall, valueNonZero);
178 builder.CreateCondBr(transfer, checkBalanceBB, callBB);
180 builder.SetInsertPoint(checkBalanceBB);
186 auto balanceOk = builder.CreateICmpUGE(balance, value);
187 builder.CreateCondBr(balanceOk, callBB, failBB);
189 builder.SetInsertPoint(callBB);
191 auto outIt = std::begin(args);
192 for (
auto it = func->arg_begin(); it != func->arg_end(); ++it, ++outIt)
194 auto ret = builder.CreateCall(callFunc, args);
195 builder.CreateRet(ret);
197 builder.SetInsertPoint(failBB);
198 auto failRet = builder.CreateOr(&gas, builder.getInt64(EVM_CALL_FAILURE));
199 builder.CreateRet(failRet);
215 auto allocaPtr = &(*allocaIt);
233 auto& func =
m_funcs[
static_cast<size_t>(_funcId)];
238 return m_builder.CreateCall(func, {_args.begin(), _args.size()});
243 auto args = llvm::SmallVector<llvm::Value*, 8>{_args};
244 for (
auto&& farg: _func->args())
246 if (farg.hasByValAttr() || farg.getType()->isPointerTy())
248 auto& arg = args[farg.getArgNo()];
250 if (!arg->getType()->isPointerTy())
254 mem =
m_builder.CreateBitCast(mem, arg->getType()->getPointerTo());
262 return m_builder.CreateCall(_func, args);
297 auto idxValid =
m_builder.CreateICmpULT(_idx, callDataSize);
301 end =
m_builder.CreateSelect(
m_builder.CreateICmpULE(end, callDataSize64), end, callDataSize64);
302 auto copySize =
m_builder.CreateNUWSub(end, idx);
305 m_builder.CreateMemCpy(result, dataBegin, copySize, 1);
332 auto mask160 = llvm::APInt(160, -1,
true).zext(256);
400 auto memRefTy = getMemRefTy(
getModule());
401 auto memRefPtr =
m_builder.CreateBitCast(vPtr, memRefTy->getPointerTo());
402 auto memRef =
m_builder.CreateLoad(memRefTy, memRefPtr,
"memref");
404 auto size =
m_builder.CreateExtractValue(memRef, 1,
"codesize");
406 return {
code, size256};
417 auto sizePtr =
m_builder.CreateBitCast(vPtr, int64ty->getPointerTo());
418 auto size =
m_builder.CreateLoad(int64ty, sizePtr,
"codesize");
428 m_builder.SetInsertPoint(&entryBB, entryBB.begin());
435 for (
size_t i = 0; i < _topics.size(); ++i)
444 auto memRefTy = getMemRefTy(
getModule());
445 auto pMemRef =
m_builder.CreateBitCast(
a, memRefTy->getPointerTo());
446 auto pData =
m_builder.CreateConstGEP2_32(memRefTy, pMemRef, 0, 0,
"log.data");
448 auto pSize =
m_builder.CreateConstGEP2_32(memRefTy, pMemRef, 0, 1,
"log.size");
452 pMemRef =
m_builder.CreateBitCast(
b, memRefTy->getPointerTo());
453 pData =
m_builder.CreateConstGEP2_32(memRefTy, pMemRef, 0, 0,
"topics.data");
455 pSize =
m_builder.CreateConstGEP2_32(memRefTy, pMemRef, 0, 1,
"topics.size");
484 addr, value, inData, inSize, outData, outSize});
503 _gas, llvm::UndefValue::get(addrTy), value, inData, inSize, pAddr,
506 pAddr =
m_builder.CreateBitCast(pAddr, addrTy->getPointerTo());
507 return std::tuple<llvm::Value*, llvm::Value*>{ret, pAddr};
llvm::Value * getBytePtr(llvm::Value *_index)
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
llvm::Module * getModule()
Reference to the IR module being compiled.
MemoryRef extcode(llvm::Value *_addr)
void log(llvm::Value *_memIdx, llvm::Value *_numBytes, llvm::ArrayRef< llvm::Value * > _topics)
llvm::Value * sload(llvm::Value *_index)
llvm::Value * query(evm_query_key _key)
llvm::Value * sha3(llvm::Value *_inOff, llvm::Value *_inSize)
Current block difficulty for DIFFICULTY.
Current block number for NUMBER.
Transaction gas price for GASPRICE.
static llvm::PointerType * WordPtr
llvm::Value * getArgAlloca()
std::array< llvm::Function *, sizeOf< EnvFunc >::value > m_funcs
llvm::Value * balance(llvm::Value *_address)
Address of the contract for ADDRESS.
Request CREATE. Semantic of some params changes.
Message sender address for CALLER.
static llvm::PointerType * BytePtr
llvm::Value * getCallDataSize()
static llvm::Value * toBE(IRBuilder &_builder, llvm::Value *_word)
Current block timestamp for TIMESTAMP.
llvm::Value * exists(llvm::Value *_address)
Balance of a given address for BALANCE.
static llvm::IntegerType * Word
Transaction origin address for ORIGIN.
void sstore(llvm::Value *_index, llvm::Value *_value)
evm_call_kind
The kind of call-like instruction.
Current block miner address for COINBASE.
Block hash of by block number for BLOCKHASH.
static llvm::ConstantInt * get(int64_t _n)
Returns word-size constant.
llvm::Value * call(evm_call_kind _kind, llvm::Value *_gas, llvm::Value *_addr, llvm::Value *_value, llvm::Value *_inOff, llvm::Value *_inSize, llvm::Value *_outOff, llvm::Value *_outSize)
llvm::Value * getEnvPtr()
static llvm::Value * toNative(IRBuilder &_builder, llvm::Value *_word)
Check if an account exists.
llvm::Function * getMainFunction()
Reference to the main module function.
Request DELEGATECALL. The value param ignored.
llvm::Value * m_topics
Memory for array of up to 4 log topics TODO: Merge this memory with args allocas. ...
llvm::Value * extcodesize(llvm::Value *_addr)
Code by an address for EXTCODECOPY.
std::array< llvm::Value *, 8 > m_argAllocas
static llvm::PointerType * GasPtr
Storage value of a given key for SLOAD.
uint8_t const size_t const size
Mark contract as selfdestructed and set beneficiary address.
Code size by an address for EXTCODESIZE.
llvm::Value * byPtr(llvm::Value *_value)
Compiler helper that depends on runtime data.
static llvm::IntegerType * Bool
llvm::CallInst * createCall(EnvFunc _funcId, std::initializer_list< llvm::Value * > const &_args)
std::tuple< llvm::Value *, llvm::Value * > create(llvm::Value *_gas, llvm::Value *_endowment, llvm::Value *_initOff, llvm::Value *_initSize)
static llvm::IntegerType * Size
IRBuilder & m_builder
Reference to parent compiler IR builder.
Current block gas limit for GASLIMIT.
RuntimeManager & getRuntimeManager()
struct evm_uint160be address(struct evm_env *env)
Ext(RuntimeManager &_runtimeManager, Memory &_memoryMan)
evm_query_key
The query callback key.
llvm::Value * blockHash(llvm::Value *_number)
static llvm::IntegerType * Gas
llvm::Value * calldataload(llvm::Value *_index)
static llvm::PointerType * EnvPtr
static llvm::IntegerType * Byte
void selfdestruct(llvm::Value *_beneficiary)
llvm::Value * createCABICall(llvm::Function *_func, std::initializer_list< llvm::Value * > const &_args)