8 #include <llvm/IR/CFG.h> 9 #include <llvm/IR/Module.h> 10 #include <llvm/IR/IntrinsicInst.h> 31 static const auto c_destIdxLabel =
"destIdx";
36 m_builder(_llvmContext)
49 if (*_curr >= push1 && *_curr <= push32)
50 offset += std::min<size_t>(*_curr - push1 + 1, (_end - _curr) - 1);
51 return _curr + offset;
54 std::vector<BasicBlock> blocks;
57 auto begin = _codeBegin;
58 for (
auto curr = begin, next = begin; curr != _codeEnd; curr = next)
60 next = skipPushDataAndGetNext(curr, _codeEnd);
95 auto beginIdx = begin - _codeBegin;
96 blocks.emplace_back(beginIdx, begin, next,
m_mainFunc);
106 auto jumpTable = llvm::cast<llvm::SwitchInst>(
m_jumpTableBB->getTerminator());
107 auto jumpTableInput = llvm::cast<llvm::PHINode>(
m_jumpTableBB->begin());
110 for (
auto it = std::next(
m_mainFunc->begin()), end = std::prev(
m_mainFunc->end(), 4); it != end; ++it)
112 auto nextBlockIter = it;
114 auto currentBlockPtr = &(*it);
115 auto nextBlockPtr = &(*nextBlockIter);
117 auto term = it->getTerminator();
118 llvm::BranchInst* jump =
nullptr;
121 IRBuilder{currentBlockPtr}.CreateBr(nextBlockPtr);
122 else if ((jump = llvm::dyn_cast<llvm::BranchInst>(term)) && jump->getSuccessor(0) ==
m_jumpTableBB)
124 auto destIdx = llvm::cast<llvm::ValueAsMetadata>(jump->getMetadata(c_destIdxLabel)->getOperand(0))->getValue();
125 if (
auto constant = llvm::dyn_cast<llvm::ConstantInt>(destIdx))
128 auto bb = jumpTable->findCaseValue(constant).getCaseSuccessor();
129 jump->setSuccessor(0, bb);
132 jumpTableInput->addIncoming(destIdx, currentBlockPtr);
134 if (jump->isConditional())
135 jump->setSuccessor(1, &(*nextBlockIter));
139 auto simplifiedInput = jumpTableInput->getNumIncomingValues() == 0 ?
140 llvm::UndefValue::get(jumpTableInput->getType()) :
141 jumpTableInput->hasConstantValue();
144 jumpTableInput->replaceAllUsesWith(simplifiedInput);
145 jumpTableInput->eraseFromParent();
151 auto module = llvm::make_unique<llvm::Module>(_id,
m_builder.getContext());
155 m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, _id, module.get());
156 m_mainFunc->getArgumentList().front().setName(
"rt");
178 Memory memory(runtimeManager, gasMeter);
179 Ext ext(runtimeManager, memory);
183 auto frameaddress = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::frameaddress);
186 auto stacksave = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::stacksave);
187 auto sp =
m_builder.CreateCall(stacksave, {},
"sp");
188 auto jmpBufSp =
m_builder.CreateConstInBoundsGEP1_64(jmpBufWords, 2,
"jmpBuf.sp");
190 auto setjmp = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp);
192 auto r =
m_builder.CreateCall(setjmp, jmpBuf);
197 for (
auto& block: blocks)
219 for (
auto it = _basicBlock.
begin(); it != _basicBlock.
end(); ++it)
223 _gasMeter.
count(inst);
230 auto lhs = stack.pop();
231 auto rhs = stack.pop();
232 auto result =
m_builder.CreateAdd(lhs, rhs);
239 auto lhs = stack.pop();
240 auto rhs = stack.pop();
241 auto result =
m_builder.CreateSub(lhs, rhs);
248 auto lhs = stack.pop();
249 auto rhs = stack.pop();
250 auto res =
m_builder.CreateMul(lhs, rhs);
257 auto d = stack.pop();
258 auto n = stack.pop();
269 auto d = stack.pop();
270 auto n = stack.pop();
277 r =
m_builder.CreateSelect(divByMinusOne, dNeg, r);
284 auto d = stack.pop();
285 auto n = stack.pop();
296 auto d = stack.pop();
297 auto n = stack.pop();
311 auto a = stack.pop();
312 auto b = stack.pop();
313 auto m = stack.pop();
329 auto a = stack.pop();
330 auto b = stack.pop();
331 auto m = stack.pop();
346 auto base = stack.pop();
347 auto exponent = stack.pop();
349 auto ret = _arith.
exp(base, exponent);
356 auto value = stack.pop();
364 auto lhs = stack.pop();
365 auto rhs = stack.pop();
366 auto res1 =
m_builder.CreateICmpULT(lhs, rhs);
374 auto lhs = stack.pop();
375 auto rhs = stack.pop();
376 auto res1 =
m_builder.CreateICmpUGT(lhs, rhs);
384 auto lhs = stack.pop();
385 auto rhs = stack.pop();
386 auto res1 =
m_builder.CreateICmpSLT(lhs, rhs);
394 auto lhs = stack.pop();
395 auto rhs = stack.pop();
396 auto res1 =
m_builder.CreateICmpSGT(lhs, rhs);
404 auto lhs = stack.pop();
405 auto rhs = stack.pop();
406 auto res1 =
m_builder.CreateICmpEQ(lhs, rhs);
414 auto top = stack.pop();
423 auto lhs = stack.pop();
424 auto rhs = stack.pop();
425 auto res =
m_builder.CreateAnd(lhs, rhs);
432 auto lhs = stack.pop();
433 auto rhs = stack.pop();
441 auto lhs = stack.pop();
442 auto rhs = stack.pop();
443 auto res =
m_builder.CreateXor(lhs, rhs);
450 const auto idx = stack.pop();
468 auto idx = stack.pop();
469 auto word = stack.pop();
478 auto bitval =
m_builder.CreateLShr(
word, bitposEx,
"bitval");
484 auto negmask =
m_builder.CreateXor(mask, llvm::ConstantInt::getAllOnesValue(
Type::Word),
"negmask");
489 auto result =
m_builder.CreateSelect(kInRange,
490 m_builder.CreateSelect(bittest, val1, val0),
498 auto inOff = stack.pop();
499 auto inSize = stack.pop();
500 _memory.
require(inOff, inSize);
502 auto hash = _ext.
sha3(inOff, inSize);
536 auto addr = stack.pop();
544 auto addr = stack.pop();
545 auto word = stack.pop();
552 auto addr = stack.pop();
553 auto word = stack.pop();
567 auto index = stack.pop();
568 auto value = _ext.
sload(index);
575 auto index = stack.pop();
576 auto value = stack.pop();
578 _ext.
sstore(index, value);
585 auto destIdx = llvm::MDNode::get(
m_builder.getContext(), llvm::ValueAsMetadata::get(stack.pop()));
594 jumpInst->setMetadata(c_destIdxLabel, destIdx);
601 assert(it == _basicBlock.
begin() &&
"JUMPDEST must be the first instruction of a basic block");
602 auto jumpTable = llvm::cast<llvm::SwitchInst>(
m_jumpTableBB->getTerminator());
656 auto beValue = _runtimeManager.getValue();
662 stack.push(_runtimeManager.getCodeSize());
666 stack.push(_runtimeManager.getCallDataSize());
671 auto number = stack.pop();
675 auto isBigNumber =
m_builder.CreateICmpUGT(number, limit);
693 auto addr = stack.pop();
695 stack.push(codesize);
701 auto destMemIdx = stack.pop();
702 auto srcIdx = stack.pop();
703 auto reqBytes = stack.pop();
705 auto srcPtr = _runtimeManager.getCallData();
706 auto srcSize = _runtimeManager.getCallDataSize();
708 _memory.
copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes);
714 auto destMemIdx = stack.pop();
715 auto srcIdx = stack.pop();
716 auto reqBytes = stack.pop();
718 auto srcPtr = _runtimeManager.getCode();
719 auto srcSize = _runtimeManager.getCodeSize();
721 _memory.
copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes);
727 auto addr = stack.pop();
728 auto destMemIdx = stack.pop();
729 auto srcIdx = stack.pop();
730 auto reqBytes = stack.pop();
732 auto codeRef = _ext.
extcode(addr);
734 _memory.
copyBytes(codeRef.ptr, codeRef.size, srcIdx, destMemIdx, reqBytes);
740 auto idx = stack.pop();
748 auto endowment = stack.pop();
749 auto initOff = stack.pop();
750 auto initSize = stack.pop();
751 _memory.
require(initOff, initSize);
754 auto gas = _runtimeManager.getGas();
758 auto createGas =
m_builder.CreateSub(gas, gasKept,
"create.gas",
true,
true);
761 std::tie(r, pAddr) = _ext.
create(createGas, endowment, initOff, initSize);
769 auto gasLeft =
m_builder.CreateSub(r, rmagic,
"create.gasleft");
770 gas =
m_builder.CreateAdd(gasLeft, gasKept);
771 _runtimeManager.setGas(gas);
786 it = _basicBlock.
end() - 1;
797 auto callGas = stack.pop();
801 auto inOff = stack.pop();
802 auto inSize = stack.pop();
803 auto outOff = stack.pop();
804 auto outSize = stack.pop();
809 _memory.
require(outOff, outSize);
811 _memory.
require(inOff, inSize);
814 auto transferCost =
m_builder.CreateSelect(
816 m_builder.getInt64(JITSchedule::valueTransferGas::value));
817 _gasMeter.
count(transferCost, _runtimeManager.getJmpBuf(),
818 _runtimeManager.getGasPtr());
823 auto noPenaltyCond = accountExists;
825 noPenaltyCond =
m_builder.CreateOr(accountExists, noTransfer);
826 auto penalty =
m_builder.CreateSelect(noPenaltyCond,
828 m_builder.getInt64(JITSchedule::callNewAccount::value));
829 _gasMeter.
count(penalty, _runtimeManager.getJmpBuf(),
830 _runtimeManager.getGasPtr());
835 auto gas = _runtimeManager.getGas();
836 auto gas64th =
m_builder.CreateLShr(gas, 6);
837 auto gasMaxAllowed =
m_builder.CreateZExt(
838 m_builder.CreateSub(gas, gas64th,
"gas.maxallowed",
840 auto cmp =
m_builder.CreateICmpUGT(callGas, gasMaxAllowed);
841 callGas =
m_builder.CreateSelect(cmp, gasMaxAllowed, callGas);
844 _gasMeter.
count(callGas, _runtimeManager.getJmpBuf(),
845 _runtimeManager.getGasPtr());
848 m_builder.getInt64(JITSchedule::callStipend::value));
850 gas =
m_builder.CreateAdd(gas, stipend,
"call.gas",
true,
true);
851 auto r = _ext.
call(kind, gas,
address, value, inOff, inSize, outOff,
859 auto finalGas =
m_builder.CreateSub(r, rmagic,
"call.finalgas");
867 auto index = stack.pop();
868 auto size = stack.pop();
871 _runtimeManager.registerReturnData(index,
size);
873 _runtimeManager.exit(ReturnCode::Return);
879 auto dest = stack.pop();
882 auto destExists = _ext.
exists(dest);
883 auto noPenaltyCond = destExists;
890 noPenaltyCond =
m_builder.CreateOr(destExists, noTransfer);
894 m_builder.getInt64(JITSchedule::callNewAccount::value));
895 _gasMeter.
count(penalty, _runtimeManager.getJmpBuf(),
896 _runtimeManager.getGasPtr());
911 auto beginIdx = stack.pop();
912 auto numBytes = stack.pop();
913 _memory.
require(beginIdx, numBytes);
918 llvm::SmallVector<llvm::Value*, 4> topics;
919 auto numTopics =
static_cast<size_t>(inst) - static_cast<size_t>(
Instruction::LOG0);
920 for (
size_t i = 0; i < numTopics; ++i)
921 topics.emplace_back(stack.pop());
923 _ext.
log(beginIdx, numBytes, topics);
929 it = _basicBlock.
end() - 1;
signed greater-than comparision
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
unsigned modular addition
get external code size (from another contract)
void commitCostBlock()
Finalize cost-block by checking gas needed for the block before the block.
Compiler(Options const &_options, evm_mode _mode, llvm::LLVMContext &_llvmContext)
unsigned modular multiplication
get the block's timestamp
place 1 byte item on stack
void countSha3Data(llvm::Value *_dataLength)
Count gas cost of SHA3 data.
MemoryRef extcode(llvm::Value *_addr)
conditionally alter the program counter
void log(llvm::Value *_memIdx, llvm::Value *_numBytes, llvm::ArrayRef< llvm::Value * > _topics)
llvm::Value * sload(llvm::Value *_index)
copy input data in current environment to memory
llvm::Value * query(evm_query_key _key)
retrieve single byte from word
llvm::Value * sha3(llvm::Value *_inOff, llvm::Value *_inSize)
get execution origination address
Makes a log entry; 4 topics.
get the block's number
Current block difficulty for DIFFICULTY.
static llvm::PointerType * RuntimePtr
integer division operation
Current block number for NUMBER.
assert(len-trim+(2 *lenIndices)<=WIDTH)
get the block's coinbase address
set a potential jump destination
get input data of current environment
llvm::Value * loadWord(llvm::Value *_addr)
llvm::BasicBlock * m_jumpTableBB
Block with a jump table.
Transaction gas price for GASPRICE.
void require(llvm::Value *_offset, llvm::Value *_size)
Requires the amount of memory to for data defined by offset and size. And counts gas fee for that mem...
instr_idx firstInstrIdx() const
halt execution and register account for later deletion
signed integer division operation
byte const * code_iterator
signed less-than comparision
halt execution returning output data
llvm::Value * balance(llvm::Value *_address)
Address of the contract for ADDRESS.
get address of currently executing account
get hash of most recent complete block
Message sender address for CALLER.
Ran out of gas executing code of the transaction.
void copyBytes(llvm::Value *_srcPtr, llvm::Value *_srcSize, llvm::Value *_srcIndex, llvm::Value *_destMemIdx, llvm::Value *_byteCount)
static llvm::PointerType * BytePtr
get size of code running in current environment
static llvm::Value * toBE(IRBuilder &_builder, llvm::Value *_word)
Current block timestamp for TIMESTAMP.
llvm::Value * exists(llvm::Value *_address)
copies the highest item in the stack to the top of the stack
Makes a log entry; no topics.
get the size of active memory
std::vector< BasicBlock > createBasicBlocks(code_iterator _begin, code_iterator _end)
get the block's gas limit
llvm::Value * exp(llvm::Value *_arg1, llvm::Value *_arg2)
get balance of the given account
message-call with another account's code only
static llvm::IntegerType * Word
Transaction origin address for ORIGIN.
void storeWord(llvm::Value *_addr, llvm::Value *_word)
std::vector< byte > bytes
void sstore(llvm::Value *_index, llvm::Value *_value)
get size of input data in current environment
void countExp(llvm::Value *_exponent)
Calculate & count additional gas cost for EXP instruction.
Current block miner address for COINBASE.
extend length of signed integer
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)
static llvm::Value * toNative(IRBuilder &_builder, llvm::Value *_word)
static llvm::IntegerType * MainReturn
Main function return type.
copy code running in current environment to memory
void exit(ReturnCode _returnCode)
evm_mode
EVM compatibility mode aka chain mode.
signed modulo remainder operation
Request DELEGATECALL. The value param ignored.
llvm::Value * extcodesize(llvm::Value *_addr)
void compileBasicBlock(BasicBlock &_basicBlock, class RuntimeManager &_runtimeManager, class Arith256 &_arith, class Memory &_memory, class Ext &_ext, class GasMeter &_gasMeter)
like CALLCODE but keeps caller's value and sender
llvm::BasicBlock * llvm()
Instruction
Virtual machine bytecode instruction.
code_iterator begin() const
get the amount of available gas
copy external code (from another contract)
void giveBack(llvm::Value *_gas)
Give back an amount of gas not used by a call.
get deposited value by the instruction/transaction responsible for this execution ...
place 32 byte item on stack
get price of gas in current environment
IRBuilder m_builder
Helper class for generating IR.
void countLogData(llvm::Value *_dataLength)
Count gas cost of LOG data.
alter the program counter to a jumpdest
swaps the highest and second highest value on the stack
void setJmpBuf(llvm::Value *_jmpBuf)
Makes a log entry; 1 topic.
uint8_t const size_t const size
std::unique_ptr< llvm::Module > compile(code_iterator _begin, code_iterator _end, std::string const &_id)
evm_mode m_mode
EVM compatibility mode.
code_iterator end() const
message-call into an account
get the block's difficulty
llvm::Function * m_mainFunc
Main program function.
static llvm::IntegerType * Bool
void storeByte(llvm::Value *_addr, llvm::Value *_byte)
std::tuple< llvm::Value *, llvm::Value * > create(llvm::Value *_gas, llvm::Value *_endowment, llvm::Value *_initOff, llvm::Value *_initSize)
void count(Instruction _inst)
Count step cost of instruction.
llvm::APInt readPushData(code_iterator &_curr, code_iterator _end)
Reads PUSH data from pointed fragment of bytecode and constructs number out of it Reading out of byte...
static llvm::IntegerType * Size
static void init(llvm::LLVMContext &_context)
Current block gas limit for GASLIMIT.
struct evm_uint160be address(struct evm_env *env)
llvm::IRBuilder<> IRBuilder
static llvm::MDNode * expectTrue
Makes a log entry; 3 topics.
void countSStore(class Ext &_ext, llvm::Value *_index, llvm::Value *_newValue)
Calculate & count gas cost for SSTORE instruction.
llvm::Value * blockHash(llvm::Value *_number)
static llvm::IntegerType * Gas
llvm::Value * calldataload(llvm::Value *_index)
static llvm::IntegerType * Byte
void selfdestruct(llvm::Value *_beneficiary)
modulo remainder operation
create a new account with associated code
Makes a log entry; 2 topics.