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 }