/ libevmjit / Ext.cpp
Ext.cpp
  1  #include "Ext.h"
  2  
  3  #include "preprocessor/llvm_includes_start.h"
  4  #include <llvm/IR/IntrinsicInst.h>
  5  #include <llvm/IR/Module.h>
  6  #include "preprocessor/llvm_includes_end.h"
  7  
  8  #include "RuntimeManager.h"
  9  #include "Memory.h"
 10  #include "Type.h"
 11  #include "Endianness.h"
 12  
 13  namespace dev
 14  {
 15  namespace eth
 16  {
 17  namespace jit
 18  {
 19  
 20  Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan) :
 21  	RuntimeHelper(_runtimeManager),
 22  	m_memoryMan(_memoryMan)
 23  {
 24  	m_funcs = decltype(m_funcs)();
 25  	m_argAllocas = decltype(m_argAllocas)();
 26  	m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size");
 27  }
 28  
 29  namespace
 30  {
 31  
 32  using FuncDesc = std::tuple<char const*, llvm::FunctionType*>;
 33  
 34  llvm::FunctionType* getFunctionType(llvm::Type* _returnType, std::initializer_list<llvm::Type*> const& _argsTypes)
 35  {
 36  	return llvm::FunctionType::get(_returnType, llvm::ArrayRef<llvm::Type*>{_argsTypes.begin(), _argsTypes.size()}, false);
 37  }
 38  
 39  std::array<FuncDesc, sizeOf<EnvFunc>::value> const& getEnvFuncDescs()
 40  {
 41  	static std::array<FuncDesc, sizeOf<EnvFunc>::value> descs{{
 42  		FuncDesc{"env_sload",   getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
 43  		FuncDesc{"env_sstore",  getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
 44  		FuncDesc{"env_sha3", getFunctionType(Type::Void, {Type::BytePtr, Type::Size, Type::WordPtr})},
 45  		FuncDesc{"env_balance", getFunctionType(Type::Void, {Type::WordPtr, Type::EnvPtr, Type::WordPtr})},
 46  		FuncDesc{"env_create", getFunctionType(Type::Void, {Type::EnvPtr, Type::GasPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr})},
 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})},
 48  		FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})},
 49  		FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
 50  		FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})},
 51  	}};
 52  
 53  	return descs;
 54  }
 55  
 56  llvm::Function* createFunc(EnvFunc _id, llvm::Module* _module)
 57  {
 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);
 60  }
 61  
 62  llvm::Function* getAccountExistsFunc(llvm::Module* _module)
 63  {
 64  	static const auto funcName = "evm.exists";
 65  	auto func = _module->getFunction(funcName);
 66  	if (!func)
 67  	{
 68  		// TODO: Mark the function as pure to eliminate multiple calls.
 69  		auto i32 = llvm::IntegerType::getInt32Ty(_module->getContext());
 70  		auto addrTy = llvm::IntegerType::get(_module->getContext(), 160);
 71  		auto fty = llvm::FunctionType::get(
 72  				i32, {Type::EnvPtr, addrTy->getPointerTo()}, false);
 73  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
 74  	}
 75  	return func;
 76  }
 77  
 78  llvm::Function* getGetStorageFunc(llvm::Module* _module)
 79  {
 80  	static const auto funcName = "evm.sload";
 81  	auto func = _module->getFunction(funcName);
 82  	if (!func)
 83  	{
 84  		// TODO: Mark the function as pure to eliminate multiple calls.
 85  		auto addrTy = llvm::IntegerType::get(_module->getContext(), 160);
 86  		auto fty = llvm::FunctionType::get(
 87  			Type::Void, {Type::WordPtr, Type::EnvPtr, addrTy->getPointerTo(), Type::WordPtr}, false);
 88  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
 89  		func->addAttribute(1, llvm::Attribute::NoAlias);
 90  		func->addAttribute(1, llvm::Attribute::NoCapture);
 91  		func->addAttribute(3, llvm::Attribute::ReadOnly);
 92  		func->addAttribute(3, llvm::Attribute::NoAlias);
 93  		func->addAttribute(3, llvm::Attribute::NoCapture);
 94  		func->addAttribute(4, llvm::Attribute::ReadOnly);
 95  		func->addAttribute(4, llvm::Attribute::NoAlias);
 96  		func->addAttribute(4, llvm::Attribute::NoCapture);
 97  	}
 98  	return func;
 99  }
100  
101  llvm::Function* getSetStorageFunc(llvm::Module* _module)
102  {
103  	static const auto funcName = "evm.sstore";
104  	auto func = _module->getFunction(funcName);
105  	if (!func)
106  	{
107  		auto addrPtrTy = llvm::Type::getIntNPtrTy(_module->getContext(), 160);
108  		auto fty = llvm::FunctionType::get(Type::Void, {Type::EnvPtr, addrPtrTy, Type::WordPtr, Type::WordPtr}, false);
109  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
110  		func->addAttribute(2, llvm::Attribute::ReadOnly);
111  		func->addAttribute(2, llvm::Attribute::NoAlias);
112  		func->addAttribute(2, llvm::Attribute::NoCapture);
113  		func->addAttribute(3, llvm::Attribute::ReadOnly);
114  		func->addAttribute(3, llvm::Attribute::NoAlias);
115  		func->addAttribute(3, llvm::Attribute::NoCapture);
116  	}
117  	return func;
118  }
119  
120  llvm::Function* getGetBalanceFunc(llvm::Module* _module)
121  {
122  	static const auto funcName = "evm.balance";
123  	auto func = _module->getFunction(funcName);
124  	if (!func)
125  	{
126  		auto addrTy = llvm::IntegerType::get(_module->getContext(), 160);
127  		auto fty = llvm::FunctionType::get(
128  			Type::Void, {Type::WordPtr, Type::EnvPtr, addrTy->getPointerTo()}, false);
129  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
130  		func->addAttribute(1, llvm::Attribute::NoAlias);
131  		func->addAttribute(1, llvm::Attribute::NoCapture);
132  		func->addAttribute(3, llvm::Attribute::ReadOnly);
133  		func->addAttribute(3, llvm::Attribute::NoAlias);
134  		func->addAttribute(3, llvm::Attribute::NoCapture);
135  	}
136  	return func;
137  }
138  
139  llvm::Function* getGetCodeSizeFunc(llvm::Module* _module)
140  {
141  	static const auto funcName = "evm.codesize";
142  	auto func = _module->getFunction(funcName);
143  	if (!func)
144  	{
145  		auto addrTy = llvm::IntegerType::get(_module->getContext(), 160);
146  		auto fty = llvm::FunctionType::get(
147  			Type::Size, {Type::EnvPtr, addrTy->getPointerTo()}, false);
148  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
149  		func->addAttribute(2, llvm::Attribute::ReadOnly);
150  		func->addAttribute(2, llvm::Attribute::NoAlias);
151  		func->addAttribute(2, llvm::Attribute::NoCapture);
152  	}
153  	return func;
154  }
155  
156  llvm::Function* getGetCodeFunc(llvm::Module* _module)
157  {
158  	static const auto funcName = "evm.code";
159  	auto func = _module->getFunction(funcName);
160  	if (!func)
161  	{
162  		auto addrTy = llvm::IntegerType::get(_module->getContext(), 160);
163  		auto fty = llvm::FunctionType::get(
164  			Type::Size, {Type::BytePtr->getPointerTo(), Type::EnvPtr, addrTy->getPointerTo()}, false);
165  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
166  		func->addAttribute(1, llvm::Attribute::NoAlias);
167  		func->addAttribute(1, llvm::Attribute::NoCapture);
168  		func->addAttribute(3, llvm::Attribute::ReadOnly);
169  		func->addAttribute(3, llvm::Attribute::NoAlias);
170  		func->addAttribute(3, llvm::Attribute::NoCapture);
171  	}
172  	return func;
173  }
174  
175  llvm::Function* getSelfdestructFunc(llvm::Module* _module)
176  {
177  	static const auto funcName = "evm.selfdestruct";
178  	auto func = _module->getFunction(funcName);
179  	if (!func)
180  	{
181  		auto addrPtrTy = llvm::Type::getIntNPtrTy(_module->getContext(), 160);
182  		auto fty = llvm::FunctionType::get(Type::Void, {Type::EnvPtr, addrPtrTy, addrPtrTy}, false);
183  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
184  		func->addAttribute(2, llvm::Attribute::ReadOnly);
185  		func->addAttribute(2, llvm::Attribute::NoAlias);
186  		func->addAttribute(2, llvm::Attribute::NoCapture);
187  		func->addAttribute(3, llvm::Attribute::ReadOnly);
188  		func->addAttribute(3, llvm::Attribute::NoAlias);
189  		func->addAttribute(3, llvm::Attribute::NoCapture);
190  	}
191  	return func;
192  }
193  
194  llvm::Function* getLogFunc(llvm::Module* _module)
195  {
196  	static const auto funcName = "evm.log";
197  	auto func = _module->getFunction(funcName);
198  	if (!func)
199  	{
200  		auto addrPtrTy = llvm::Type::getIntNPtrTy(_module->getContext(), 160);
201  		auto fty = llvm::FunctionType::get(Type::Void, {Type::EnvPtr, addrPtrTy, Type::BytePtr, Type::Size, Type::WordPtr, Type::Size}, false);
202  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
203  		func->addAttribute(3, llvm::Attribute::ReadOnly);
204  		func->addAttribute(3, llvm::Attribute::NoAlias);
205  		func->addAttribute(3, llvm::Attribute::NoCapture);
206  		func->addAttribute(5, llvm::Attribute::ReadOnly);
207  		func->addAttribute(5, llvm::Attribute::NoAlias);
208  		func->addAttribute(5, llvm::Attribute::NoCapture);
209  	}
210  	return func;
211  }
212  
213  llvm::Function* getCallFunc(llvm::Module* _module)
214  {
215  	static const auto funcName = "call";
216  	auto func = _module->getFunction(funcName);
217  	if (!func)
218  	{
219  		auto i32 = llvm::IntegerType::getInt32Ty(_module->getContext());
220  		auto addrTy = llvm::IntegerType::get(_module->getContext(), 160);
221  		auto addrPtrTy = addrTy->getPointerTo();
222  		auto fty = llvm::FunctionType::get(
223  			Type::Gas,
224  			{Type::EnvPtr, i32, Type::Gas, addrPtrTy, Type::WordPtr,
225  			 Type::BytePtr, Type::Size, Type::BytePtr, Type::Size,
226  			 Type::BytePtr->getPointerTo(), Type::Size->getPointerTo()},
227  			false);
228  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, "evm.call", _module);
229  		func->addAttribute(4, llvm::Attribute::ReadOnly);
230  		func->addAttribute(4, llvm::Attribute::NoAlias);
231  		func->addAttribute(4, llvm::Attribute::NoCapture);
232  		func->addAttribute(5, llvm::Attribute::ReadOnly);
233  		func->addAttribute(5, llvm::Attribute::NoAlias);
234  		func->addAttribute(5, llvm::Attribute::NoCapture);
235  		func->addAttribute(6, llvm::Attribute::ReadOnly);
236  		func->addAttribute(6, llvm::Attribute::NoCapture);
237  		func->addAttribute(8, llvm::Attribute::NoCapture);
238  		auto callFunc = func;
239  
240  		// Create a call wrapper to handle additional checks.
241  		fty = llvm::FunctionType::get(
242  			Type::Gas,
243  			{Type::EnvPtr, i32, Type::Gas, addrPtrTy, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size,
244  			 Type::BytePtr->getPointerTo(), Type::Size->getPointerTo(), addrTy, Type::Size},
245  			false
246  		);
247  		func = llvm::Function::Create(fty, llvm::Function::PrivateLinkage, funcName, _module);
248  		func->addAttribute(4, llvm::Attribute::ReadOnly);
249  		func->addAttribute(4, llvm::Attribute::NoAlias);
250  		func->addAttribute(4, llvm::Attribute::NoCapture);
251  		func->addAttribute(5, llvm::Attribute::ReadOnly);
252  		func->addAttribute(5, llvm::Attribute::NoAlias);
253  		func->addAttribute(5, llvm::Attribute::NoCapture);
254  		func->addAttribute(6, llvm::Attribute::ReadOnly);
255  		func->addAttribute(6, llvm::Attribute::NoCapture);
256  		func->addAttribute(8, llvm::Attribute::NoCapture);
257  
258  		auto iter = func->arg_begin();
259  		auto& env = *iter;
260  		std::advance(iter, 1);
261  		auto& callKind = *iter;
262  		std::advance(iter, 1);
263  		auto& gas = *iter;
264  		std::advance(iter, 2);
265  		auto& valuePtr = *iter;
266  		std::advance(iter, 7);
267  		auto& addr = *iter;
268  		std::advance(iter, 1);
269  		auto& depth = *iter;
270  
271  		auto& ctx = _module->getContext();
272  		llvm::IRBuilder<> builder(ctx);
273  		auto entryBB = llvm::BasicBlock::Create(ctx, "Entry", func);
274  		auto checkTransferBB = llvm::BasicBlock::Create(ctx, "CheckTransfer", func);
275  		auto checkBalanceBB = llvm::BasicBlock::Create(ctx, "CheckBalance", func);
276  		auto callBB = llvm::BasicBlock::Create(ctx, "Call", func);
277  		auto failBB = llvm::BasicBlock::Create(ctx, "Fail", func);
278  
279  		builder.SetInsertPoint(entryBB);
280  		auto v = builder.CreateAlloca(Type::Word);
281  		auto addrAlloca = builder.CreateBitCast(builder.CreateAlloca(Type::Word), addrPtrTy);
282  		auto getBalanceFn = getGetBalanceFunc(_module);
283  		auto depthOk = builder.CreateICmpSLT(&depth, builder.getInt64(1024));
284  		builder.CreateCondBr(depthOk, checkTransferBB, failBB);
285  
286  		builder.SetInsertPoint(checkTransferBB);
287  		auto notDelegateCall = builder.CreateICmpNE(&callKind, builder.getInt32(EVMC_DELEGATECALL));
288  		llvm::Value* value = builder.CreateLoad(&valuePtr);
289  		auto valueNonZero = builder.CreateICmpNE(value, Constant::get(0));
290  		auto transfer = builder.CreateAnd(notDelegateCall, valueNonZero);
291  		builder.CreateCondBr(transfer, checkBalanceBB, callBB);
292  
293  		builder.SetInsertPoint(checkBalanceBB);
294  		builder.CreateStore(&addr, addrAlloca);
295  		builder.CreateCall(getBalanceFn, {v, &env, addrAlloca});
296  		llvm::Value* balance = builder.CreateLoad(v);
297  		balance = Endianness::toNative(builder, balance);
298  		value = Endianness::toNative(builder, value);
299  		auto balanceOk = builder.CreateICmpUGE(balance, value);
300  		builder.CreateCondBr(balanceOk, callBB, failBB);
301  
302  		builder.SetInsertPoint(callBB);
303  		// Pass the first 11 args to the external call.
304  		llvm::Value* args[11];
305  		auto it = func->arg_begin();
306  		for (auto outIt = std::begin(args); outIt != std::end(args); ++it, ++outIt)
307  			*outIt = &*it;
308  		auto ret = builder.CreateCall(callFunc, args);
309  		builder.CreateRet(ret);
310  
311  		builder.SetInsertPoint(failBB);
312  		auto failRet = builder.CreateOr(&gas, builder.getInt64(EVM_CALL_FAILURE));
313  		builder.CreateRet(failRet);
314  	}
315  	return func;
316  }
317  
318  llvm::Function* getBlockHashFunc(llvm::Module* _module)
319  {
320  	static const auto funcName = "evm.blockhash";
321  	auto func = _module->getFunction(funcName);
322  	if (!func)
323  	{
324  		// TODO: Mark the function as pure to eliminate multiple calls.
325  		auto i64 = llvm::IntegerType::getInt64Ty(_module->getContext());
326  		auto fty = llvm::FunctionType::get(Type::Void, {Type::WordPtr, Type::EnvPtr, i64}, false);
327  		func = llvm::Function::Create(fty, llvm::Function::ExternalLinkage, funcName, _module);
328  		func->addAttribute(1, llvm::Attribute::NoAlias);
329  		func->addAttribute(1, llvm::Attribute::NoCapture);
330  	}
331  	return func;
332  }
333  
334  }
335  
336  
337  
338  llvm::Value* Ext::getArgAlloca()
339  {
340  	auto& a = m_argAllocas[m_argCounter];
341  	if (!a)
342  	{
343  		InsertPointGuard g{m_builder};
344  		auto allocaIt = getMainFunction()->front().begin();
345  		auto allocaPtr = &(*allocaIt);
346  		std::advance(allocaIt, m_argCounter); // Skip already created allocas
347  		m_builder.SetInsertPoint(allocaPtr);
348  		a = m_builder.CreateAlloca(Type::Word, nullptr, {"a.", std::to_string(m_argCounter)});
349  	}
350  	++m_argCounter;
351  	return a;
352  }
353  
354  llvm::CallInst* Ext::createCall(EnvFunc _funcId, std::initializer_list<llvm::Value*> const& _args)
355  {
356  	auto& func = m_funcs[static_cast<size_t>(_funcId)];
357  	if (!func)
358  		func = createFunc(_funcId, getModule());
359  
360  	m_argCounter = 0;
361  	return m_builder.CreateCall(func, {_args.begin(), _args.size()});
362  }
363  
364  llvm::Value* Ext::createCABICall(llvm::Function* _func, std::initializer_list<llvm::Value*> const& _args)
365  {
366  	auto args = llvm::SmallVector<llvm::Value*, 8>{_args};
367  	for (auto&& farg: _func->args())
368  	{
369  		if (farg.hasByValAttr() || farg.getType()->isPointerTy())
370  		{
371  			auto& arg = args[farg.getArgNo()];
372  			// TODO: Remove defensive check and always use it this way.
373  			if (!arg->getType()->isPointerTy())
374  			{
375  				auto mem = getArgAlloca();
376  				// TODO: The bitcast may be redundant
377  				mem = m_builder.CreateBitCast(mem, arg->getType()->getPointerTo());
378  				m_builder.CreateStore(arg, mem);
379  				arg = mem;
380  			}
381  		}
382  	}
383  
384  	m_argCounter = 0;
385  	return m_builder.CreateCall(_func, args);
386  }
387  
388  llvm::Value* Ext::sload(llvm::Value* _index)
389  {
390  	auto index = Endianness::toBE(m_builder, _index);
391  	auto addrTy = m_builder.getIntNTy(160);
392  	auto myAddr = Endianness::toBE(m_builder, m_builder.CreateTrunc(Endianness::toNative(m_builder, getRuntimeManager().getAddress()), addrTy));
393  	auto pAddr = m_builder.CreateBitCast(getArgAlloca(), addrTy->getPointerTo());
394  	m_builder.CreateStore(myAddr, pAddr);
395  	auto func = getGetStorageFunc(getModule());
396  	auto pValue = getArgAlloca();
397  	createCABICall(func, {pValue, getRuntimeManager().getEnvPtr(), pAddr, index});
398  	return Endianness::toNative(m_builder, m_builder.CreateLoad(pValue));
399  }
400  
401  void Ext::sstore(llvm::Value* _index, llvm::Value* _value)
402  {
403  	auto addrTy = m_builder.getIntNTy(160);
404  	auto index = Endianness::toBE(m_builder, _index);
405  	auto value = Endianness::toBE(m_builder, _value);
406  	auto myAddr = Endianness::toBE(m_builder, m_builder.CreateTrunc(Endianness::toNative(m_builder, getRuntimeManager().getAddress()), addrTy));
407  	auto func = getSetStorageFunc(getModule());
408  	createCABICall(func, {getRuntimeManager().getEnvPtr(), myAddr, index, value});
409  }
410  
411  void Ext::selfdestruct(llvm::Value* _beneficiary)
412  {
413  	auto addrTy = m_builder.getIntNTy(160);
414  	auto func = getSelfdestructFunc(getModule());
415  	auto b = Endianness::toBE(m_builder, m_builder.CreateTrunc(_beneficiary, addrTy));
416  	auto myAddr = Endianness::toBE(m_builder, m_builder.CreateTrunc(Endianness::toNative(m_builder, getRuntimeManager().getAddress()), addrTy));
417  	createCABICall(func, {getRuntimeManager().getEnvPtr(), myAddr, b});
418  }
419  
420  llvm::Value* Ext::calldataload(llvm::Value* _idx)
421  {
422  	auto ret = getArgAlloca();
423  	auto result = m_builder.CreateBitCast(ret, Type::BytePtr);
424  
425  	auto callDataSize = getRuntimeManager().getCallDataSize();
426  	auto callDataSize64 = m_builder.CreateTrunc(callDataSize, Type::Size);
427  	auto idxValid = m_builder.CreateICmpULT(_idx, callDataSize);
428  	auto idx = m_builder.CreateTrunc(m_builder.CreateSelect(idxValid, _idx, callDataSize), Type::Size, "idx");
429  
430  	auto end = m_builder.CreateNUWAdd(idx, m_builder.getInt64(32));
431  	end = m_builder.CreateSelect(m_builder.CreateICmpULE(end, callDataSize64), end, callDataSize64);
432  	auto copySize = m_builder.CreateNUWSub(end, idx);
433  	auto padSize = m_builder.CreateNUWSub(m_builder.getInt64(32), copySize);
434  	auto dataBegin = m_builder.CreateGEP(Type::Byte, getRuntimeManager().getCallData(), idx);
435  	m_builder.CreateMemCpy(result, dataBegin, copySize, 1);
436  	auto pad = m_builder.CreateGEP(Type::Byte, result, copySize);
437  	m_builder.CreateMemSet(pad, m_builder.getInt8(0), padSize, 1);
438  
439  	m_argCounter = 0; // Release args allocas. TODO: This is a bad design
440  	return Endianness::toNative(m_builder, m_builder.CreateLoad(ret));
441  }
442  
443  llvm::Value* Ext::balance(llvm::Value* _address)
444  {
445  	auto func = getGetBalanceFunc(getModule());
446  	auto addrTy = m_builder.getIntNTy(160);
447  	auto address = Endianness::toBE(m_builder, m_builder.CreateTrunc(_address, addrTy));
448  	auto pResult = getArgAlloca();
449  	auto pAddr = m_builder.CreateBitCast(getArgAlloca(), addrTy->getPointerTo());
450  	m_builder.CreateStore(address, pAddr);
451  	createCABICall(func, {pResult, getRuntimeManager().getEnvPtr(), pAddr});
452  	return Endianness::toNative(m_builder, m_builder.CreateLoad(pResult));
453  }
454  
455  llvm::Value* Ext::exists(llvm::Value* _address)
456  {
457  	auto func = getAccountExistsFunc(getModule());
458  	auto addrTy = m_builder.getIntNTy(160);
459  	auto address = Endianness::toBE(m_builder, m_builder.CreateTrunc(_address, addrTy));
460  	auto pAddr = m_builder.CreateBitCast(getArgAlloca(), addrTy->getPointerTo());
461  	m_builder.CreateStore(address, pAddr);
462  	auto r = createCABICall(func, {getRuntimeManager().getEnvPtr(), pAddr});
463  	return m_builder.CreateTrunc(r, m_builder.getInt1Ty());
464  }
465  
466  llvm::Value* Ext::blockHash(llvm::Value* _number)
467  {
468  	auto func = getBlockHashFunc(getModule());
469  	auto number = m_builder.CreateTrunc(_number, m_builder.getInt64Ty());
470  	auto pResult = getArgAlloca();
471  	createCABICall(func, {pResult, getRuntimeManager().getEnvPtr(), number});
472  	return Endianness::toNative(m_builder, m_builder.CreateLoad(pResult));
473  }
474  
475  llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
476  {
477  	auto begin = m_memoryMan.getBytePtr(_inOff);
478  	auto size = m_builder.CreateTrunc(_inSize, Type::Size, "size");
479  	auto ret = getArgAlloca();
480  	createCall(EnvFunc::sha3, {begin, size, ret});
481  	llvm::Value* hash = m_builder.CreateLoad(ret);
482  	return Endianness::toNative(m_builder, hash);
483  }
484  
485  MemoryRef Ext::extcode(llvm::Value* _address)
486  {
487  	auto func = getGetCodeFunc(getModule());
488  	auto addrTy = m_builder.getIntNTy(160);
489  	auto address = Endianness::toBE(m_builder, m_builder.CreateTrunc(_address, addrTy));
490  	auto pAddr = m_builder.CreateBitCast(getArgAlloca(), addrTy->getPointerTo());
491  	m_builder.CreateStore(address, pAddr);
492  	auto a = getArgAlloca();
493  	auto codePtrPtr = m_builder.CreateBitCast(a, Type::BytePtr->getPointerTo());
494  	auto size = createCABICall(func, {codePtrPtr, getRuntimeManager().getEnvPtr(), pAddr});
495  	auto code = m_builder.CreateLoad(codePtrPtr, "code");
496  	auto size256 = m_builder.CreateZExt(size, Type::Word);
497  	return {code, size256};
498  }
499  
500  llvm::Value* Ext::extcodesize(llvm::Value* _address)
501  {
502  	auto func = getGetCodeSizeFunc(getModule());
503  	auto addrTy = m_builder.getIntNTy(160);
504  	auto address = Endianness::toBE(m_builder, m_builder.CreateTrunc(_address, addrTy));
505  	auto pAddr = m_builder.CreateBitCast(getArgAlloca(), addrTy->getPointerTo());
506  	m_builder.CreateStore(address, pAddr);
507  	auto size = createCABICall(func, {getRuntimeManager().getEnvPtr(), pAddr});
508  	return m_builder.CreateZExt(size, Type::Word);
509  }
510  
511  void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, llvm::ArrayRef<llvm::Value*> _topics)
512  {
513  	if (!m_topics)
514  	{
515  		InsertPointGuard g{m_builder};
516  		auto& entryBB = getMainFunction()->front();
517  		m_builder.SetInsertPoint(&entryBB, entryBB.begin());
518  		m_topics = m_builder.CreateAlloca(Type::Word, m_builder.getInt32(4), "topics");
519  	}
520  
521  	auto dataPtr = m_memoryMan.getBytePtr(_memIdx);
522  	auto dataSize = m_builder.CreateTrunc(_numBytes, Type::Size, "data.size");
523  
524  	for (size_t i = 0; i < _topics.size(); ++i)
525  	{
526  		auto t = Endianness::toBE(m_builder, _topics[i]);
527  		auto p = m_builder.CreateConstGEP1_32(m_topics, static_cast<unsigned>(i));
528  		m_builder.CreateStore(t, p);
529  	}
530  	auto numTopics = m_builder.getInt64(_topics.size());
531  
532  	auto addrTy = m_builder.getIntNTy(160);
533  	auto func = getLogFunc(getModule());
534  	
535  	auto myAddr = Endianness::toBE(m_builder, m_builder.CreateTrunc(Endianness::toNative(m_builder, getRuntimeManager().getAddress()), addrTy));
536  	createCABICall(func, {
537  		getRuntimeManager().getEnvPtr(), myAddr, dataPtr, dataSize, m_topics, numTopics
538  	});
539  }
540  
541  llvm::Value* Ext::call(int _kind,
542  					   llvm::Value* _gas,
543  					   llvm::Value* _addr,
544  					   llvm::Value* _value,
545  					   llvm::Value* _inOff,
546  					   llvm::Value* _inSize,
547  					   llvm::Value* _outOff,
548  					   llvm::Value* _outSize)
549  {
550  	auto gas = m_builder.CreateTrunc(_gas, Type::Size);
551  	auto addrTy = m_builder.getIntNTy(160);
552  	auto addr = m_builder.CreateTrunc(_addr, addrTy);
553  	addr = Endianness::toBE(m_builder, addr);
554  	auto inData = m_memoryMan.getBytePtr(_inOff);
555  	auto inSize = m_builder.CreateTrunc(_inSize, Type::Size);
556  	auto outData = m_memoryMan.getBytePtr(_outOff);
557  	auto outSize = m_builder.CreateTrunc(_outSize, Type::Size);
558  
559  	auto value = getArgAlloca();
560  	m_builder.CreateStore(Endianness::toBE(m_builder, _value), value);
561  
562  	auto func = getCallFunc(getModule());
563  	auto myAddr = Endianness::toBE(m_builder, m_builder.CreateTrunc(Endianness::toNative(m_builder, getRuntimeManager().getAddress()), addrTy));
564  	getRuntimeManager().resetReturnBuf();
565  	return createCABICall(
566  		func,
567  		{getRuntimeManager().getEnvPtr(), m_builder.getInt32(_kind), gas,
568  		 addr, value, inData, inSize, outData, outSize,
569  		 getRuntimeManager().getReturnBufDataPtr(), getRuntimeManager().getReturnBufSizePtr(),
570  		 myAddr, getRuntimeManager().getDepth()
571  		});
572  }
573  
574  std::tuple<llvm::Value*, llvm::Value*> Ext::create(llvm::Value* _gas,
575                                                     llvm::Value* _endowment,
576  												   llvm::Value* _initOff,
577  												   llvm::Value* _initSize)
578  {
579  	auto addrTy = m_builder.getIntNTy(160);
580  	auto value = getArgAlloca();
581  	m_builder.CreateStore(Endianness::toBE(m_builder, _endowment), value);
582  	auto inData = m_memoryMan.getBytePtr(_initOff);
583  	auto inSize = m_builder.CreateTrunc(_initSize, Type::Size);
584  	auto pAddr =
585  		m_builder.CreateBitCast(getArgAlloca(), m_builder.getInt8PtrTy());
586  
587  	auto func = getCallFunc(getModule());
588  	auto myAddr = Endianness::toBE(m_builder, m_builder.CreateTrunc(Endianness::toNative(m_builder, getRuntimeManager().getAddress()), addrTy));
589  	getRuntimeManager().resetReturnBuf();
590  	auto ret = createCABICall(
591  		func, {getRuntimeManager().getEnvPtr(), m_builder.getInt32(EVMC_CREATE),
592  			   _gas, llvm::UndefValue::get(addrTy), value, inData, inSize, pAddr,
593  			   m_builder.getInt64(20),
594  			   getRuntimeManager().getReturnBufDataPtr(), getRuntimeManager().getReturnBufSizePtr(),
595  			   myAddr, getRuntimeManager().getDepth()
596  		});
597  
598  	pAddr = m_builder.CreateBitCast(pAddr, addrTy->getPointerTo());
599  	return std::tuple<llvm::Value*, llvm::Value*>{ret, pAddr};
600  }
601  }
602  }
603  }