From d5ad2aba2248aa0486e4bb5b2d35f21539dd51e3 Mon Sep 17 00:00:00 2001 From: hydai Date: Tue, 5 Nov 2019 14:39:43 +0000 Subject: [PATCH] [CodeGen] Fix intrinsic functions for EVM target --- lib/CodeGen/CGExpr.cpp | 59 +++----- lib/CodeGen/CGValue.h | 43 ++---- lib/CodeGen/CodeGenFunction.cpp | 51 +++---- lib/CodeGen/CodeGenModule.cpp | 230 ++++++++++++++++++++++++++------ lib/CodeGen/CodeGenModule.h | 13 ++ 5 files changed, 263 insertions(+), 133 deletions(-) diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index b5b092e0..19ab5390 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -431,9 +431,8 @@ class ExprEmitter { Builder.CreateCondBr(OutOfBound, Revert, Continue); Builder.SetInsertPoint(Revert); - Builder.CreateCall( - CGF.getCodeGenModule().getModule().getFunction("ethereum.revert"), - {MessageValue, Builder.getInt32(Message.size())}); + CGF.getCodeGenModule().emitRevert(MessageValue, + Builder.getInt32(Message.size())); Builder.CreateUnreachable(); Builder.SetInsertPoint(Continue); @@ -451,9 +450,9 @@ class ExprEmitter { // mapping : store i256 hash value in TempValueTable llvm::Value *MapAddress = Builder.CreateLoad(Base.getValue()); llvm::Value *Bytes = emitConcateBytes( - {CGF.getCodeGenModule().emitEndianConvert(Builder.CreateZExtOrTrunc( + {CGF.getCodeGenModule().getEndianlessValue(Builder.CreateZExtOrTrunc( Index.load(Builder, CGF.getCodeGenModule()), CGF.Int256Ty)), - CGF.getCodeGenModule().emitEndianConvert(MapAddress)}); + CGF.getCodeGenModule().getEndianlessValue(MapAddress)}); llvm::Value *Address = Builder.CreateAlloca(CGF.Int256Ty); Builder.CreateStore(Builder.CreateCall(Sha256, {Bytes}), Address); return ExprValue(Ty, ValueKind::VK_SValue, Address); @@ -485,7 +484,7 @@ class ExprEmitter { // load array position llvm::Value *Bytes = emitConcateBytes( - {CGF.getCodeGenModule().emitEndianConvert(ArrayAddress)}); + {CGF.getCodeGenModule().getEndianlessValue(ArrayAddress)}); ArrayAddress = Builder.CreateCall(Sha256, {Bytes}); } else { // Fixed Size Storage Array @@ -521,24 +520,12 @@ class ExprEmitter { if (ME->getName()->isSpecialIdentifier()) { switch (ME->getName()->getSpecialIdentifier()) { case Identifier::SpecialIdentifier::msg_sender: { - llvm::Function *getCaller = - CGF.getCodeGenModule().getModule().getFunction( - "ethereum.getCaller"); - llvm::Value *ValPtr = Builder.CreateAlloca(CGF.AddressTy); - Builder.CreateCall(getCaller, {ValPtr}); - llvm::Value *Val = CGF.getCodeGenModule().emitEndianConvert( - Builder.CreateLoad(ValPtr)); - return ExprValue::getRValue(ME, Val); + return ExprValue::getRValue(ME, CGF.getCodeGenModule().emitGetCaller()); } case Identifier::SpecialIdentifier::msg_value: { - llvm::Function *getCallValue = - CGF.getCodeGenModule().getModule().getFunction( - "ethereum.getCallValue"); - llvm::Value *ValPtr = Builder.CreateAlloca(CGF.Int128Ty); - Builder.CreateCall(getCallValue, {ValPtr}); llvm::Value *Val = - Builder.CreateZExt(CGF.getCodeGenModule().emitEndianConvert( - Builder.CreateLoad(ValPtr)), + Builder.CreateZExt(CGF.getCodeGenModule().getEndianlessValue( + CGF.getCodeGenModule().emitGetCallValue()), CGF.Int256Ty); return ExprValue::getRValue(ME, Val); } @@ -583,7 +570,7 @@ class ExprEmitter { llvm::Value *ValPtr = Builder.CreateAlloca(CGF.Int128Ty); Builder.CreateCall(getTxGasPrice, {ValPtr}); llvm::Value *Val = - Builder.CreateZExt(CGF.getCodeGenModule().emitEndianConvert( + Builder.CreateZExt(CGF.getCodeGenModule().getEndianlessValue( Builder.CreateLoad(ValPtr)), CGF.Int256Ty); return ExprValue::getRValue(ME, Val); @@ -594,7 +581,7 @@ class ExprEmitter { "ethereum.getTxOrigin"); llvm::Value *ValPtr = Builder.CreateAlloca(CGF.AddressTy); Builder.CreateCall(getTxOrigin, {ValPtr}); - llvm::Value *Val = CGF.getCodeGenModule().emitEndianConvert( + llvm::Value *Val = CGF.getCodeGenModule().getEndianlessValue( Builder.CreateLoad(ValPtr)); return ExprValue::getRValue(ME, Val); } @@ -604,7 +591,7 @@ class ExprEmitter { "ethereum.getBlockCoinbase"); llvm::Value *ValPtr = Builder.CreateAlloca(CGF.AddressTy); Builder.CreateCall(getBlockCoinbase, {ValPtr}); - llvm::Value *Val = CGF.getCodeGenModule().emitEndianConvert( + llvm::Value *Val = CGF.getCodeGenModule().getEndianlessValue( Builder.CreateLoad(ValPtr)); return ExprValue::getRValue(ME, Val); } @@ -614,7 +601,8 @@ class ExprEmitter { "ethereum.getBlockDifficulty"); llvm::Value *ValPtr = Builder.CreateAlloca(CGF.Int256Ty); Builder.CreateCall(getBlockDifficulty, {ValPtr}); - llvm::Value *Val = CGF.getCodeGenModule().emitEndianConvert( + + llvm::Value *Val = CGF.getCodeGenModule().getEndianlessValue( Builder.CreateLoad(ValPtr)); return ExprValue::getRValue(ME, Val); } @@ -701,8 +689,7 @@ void CodeGenFunction::emitCallRequire(const CallExpr *CE) { emitBranchOnBoolExpr(Arguments[0], Continue, Revert); Builder.SetInsertPoint(Revert); - Builder.CreateCall(CGM.getModule().getFunction("ethereum.revert"), - {MessageValue, Builder.getInt32(Message.size())}); + CGM.emitRevert(MessageValue, Builder.getInt32(Message.size())); Builder.CreateUnreachable(); Builder.SetInsertPoint(Continue); @@ -723,8 +710,7 @@ void CodeGenFunction::emitCallAssert(const CallExpr *CE) { emitBranchOnBoolExpr(Arguments[0], Continue, Revert); Builder.SetInsertPoint(Revert); - Builder.CreateCall(CGM.getModule().getFunction("ethereum.revert"), - {MessageValue, Builder.getInt32(Message.size())}); + CGM.emitRevert(MessageValue, Builder.getInt32(Message.size())); Builder.CreateUnreachable(); Builder.SetInsertPoint(Continue); @@ -738,8 +724,7 @@ void CodeGenFunction::emitCallRevert(const CallExpr *CE) { llvm::Constant *MessageValue = createGlobalStringPtr( getLLVMContext(), getCodeGenModule().getModule(), Message); - Builder.CreateCall(CGM.getModule().getFunction("ethereum.revert"), - {MessageValue, Builder.getInt32(Message.size())}); + CGM.emitRevert(MessageValue, Builder.getInt32(Message.size())); Builder.CreateUnreachable(); } @@ -856,21 +841,17 @@ ExprValue CodeGenFunction::emitCallExpr(const CallExpr *CE) { // XXX: Multiple args and complex data type encoding not implemented yet. for (size_t i = 0; i < Arguments.size(); i++) { - auto *v_b = Builder.CreateCall( - CGM.getModule().getFunction("solidity.bswapi256"), - {Builder.CreateZExtOrTrunc(Args[i], Int256Ty)}, "v.b"); llvm::Value *ValPtr = Builder.CreateAlloca(Int256Ty, nullptr); - Builder.CreateStore(v_b, ValPtr); + Builder.CreateStore( + CGM.getEndianlessValue(Builder.CreateZExtOrTrunc(Args[i], Int256Ty)), + ValPtr); if (Params[i]->isIndexed()) { Topics[IndexedCnt++] = ValPtr; } else { Data[DataCnt++] = ValPtr; } } - Builder.CreateCall(CGM.getModule().getFunction("ethereum.log"), - {Builder.CreateBitCast(Data[0], Builder.getInt8PtrTy()), - Builder.getInt32(32), Builder.getInt32(IndexedCnt), - Topics[0], Topics[1], Topics[2], Topics[3]}); + CGM.emitLog(Data[0], Builder.getInt32(32), Topics); return ExprValue(); } assert(false && "Unhandle CallExprType CodeGen case."); diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 2e4a658d..f61088a4 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -30,16 +30,10 @@ class ExprValue { case ValueKind::VK_LValue: return Builder.CreateLoad(V, Name); case ValueKind::VK_SValue: - llvm::Function *StorageLoad = - CGM.getModule().getFunction("ethereum.storageLoad"); - llvm::Value *ValPtr = Builder.CreateAlloca(CGM.Int256Ty, nullptr); - llvm::Value *KeyPtr = Builder.CreateAlloca(CGM.Int256Ty, nullptr); - llvm::Value *Key = CGM.emitEndianConvert(Builder.CreateLoad(V)); - Builder.CreateStore(Key, KeyPtr); - Builder.CreateCall(StorageLoad, {KeyPtr, ValPtr}); + llvm::Value *Key = CGM.getEndianlessValue(Builder.CreateLoad(V)); llvm::Type *ValueTy = Builder.getIntNTy(Ty->getBitNum()); llvm::Value *Val = Builder.CreateZExtOrTrunc( - CGM.emitEndianConvert(Builder.CreateLoad(ValPtr)), ValueTy); + CGM.getEndianlessValue(CGM.emitStorageLoad(Key)), ValueTy); switch (Ty->getCategory()) { case Type::Category::Address: case Type::Category::Bool: @@ -80,7 +74,8 @@ class ExprValue { Builder.SetInsertPoint(Loop); llvm::PHINode *PHIRemain = Builder.CreatePHI(CGM.Int256Ty, 2); llvm::PHINode *PHIPtr = Builder.CreatePHI(CGM.Int8PtrTy, 2); - Builder.CreateCall(StorageLoad, {AddressPtr, PHIPtr}); + llvm::Value *PHIV = CGM.emitStorageLoad(Builder.CreateLoad(AddressPtr)); + Builder.CreateStore(PHIV, PHIPtr); llvm::Value *CurrentAddress = Builder.CreateLoad(AddressPtr); llvm::Value *NextRemain = Builder.CreateSub(PHIRemain, Builder.getIntN(256, 32)); @@ -122,35 +117,26 @@ class ExprValue { Builder.CreateStore(Value, V); return; case ValueKind::VK_SValue: - llvm::Function *StorageStore = - CGM.getModule().getFunction("ethereum.storageStore"); switch (Ty->getCategory()) { case Type::Category::Address: case Type::Category::Bool: case Type::Category::FixedBytes: case Type::Category::Integer: case Type::Category::RationalNumber: { - llvm::Value *ValPtr = Builder.CreateAlloca(CGM.Int256Ty, nullptr); - llvm::Value *KeyPtr = Builder.CreateAlloca(CGM.Int256Ty, nullptr); - llvm::Value *Key = CGM.emitEndianConvert(Builder.CreateLoad(V)); - Builder.CreateStore(Key, KeyPtr); + llvm::Value *Key = CGM.getEndianlessValue(Builder.CreateLoad(V)); if (Shift != nullptr) { - llvm::Function *StorageLoad = - CGM.getModule().getFunction("ethereum.storageLoad"); llvm::ConstantInt *Mask = Builder.getInt( llvm::APInt::getHighBitsSet(256, 256 - Ty->getBitNum())); llvm::Value *Mask1 = Builder.CreateShl(Mask, Shift); llvm::Value *Mask2 = Builder.CreateShl(Builder.CreateZExt(Value, CGM.Int256Ty), Shift); - Builder.CreateCall(StorageLoad, {KeyPtr, ValPtr}); - llvm::Value *Val = CGM.emitEndianConvert(Builder.CreateLoad(ValPtr)); + llvm::Value *Val = CGM.getEndianlessValue(CGM.emitStorageLoad(Key)); Value = Builder.CreateOr(Builder.CreateAnd(Val, Mask1), Mask2); } - Builder.CreateStore(CGM.emitEndianConvert( - Builder.CreateZExtOrTrunc(Value, CGM.Int256Ty)), - ValPtr); - Builder.CreateCall(StorageStore, {KeyPtr, ValPtr}); + CGM.emitStorageStore( + Key, CGM.getEndianlessValue( + Builder.CreateZExtOrTrunc(Value, CGM.Int256Ty))); return; } case Type::Category::String: @@ -172,9 +158,8 @@ class ExprValue { llvm::Value *Ptr = Builder.CreateExtractValue(Value, {1}); Ptr = Builder.CreateBitCast(Ptr, Array32Int8Ptr); - llvm::Value *LengthPtr = Builder.CreateAlloca(CGM.Int256Ty, nullptr); - Builder.CreateStore(CGM.emitEndianConvert(Length), LengthPtr); - Builder.CreateCall(StorageStore, {V, LengthPtr}); + CGM.emitStorageStore(Builder.CreateLoad(V), + CGM.getEndianlessValue(Length)); Builder.CreateBr(LoopInit); Builder.SetInsertPoint(LoopInit); @@ -191,9 +176,9 @@ class ExprValue { Builder.SetInsertPoint(Loop); llvm::PHINode *PHIRemain = Builder.CreatePHI(CGM.Int256Ty, 2); llvm::PHINode *PHIPtr = Builder.CreatePHI(Array32Int8Ptr, 2); - Builder.CreateCall( - StorageStore, - {AddressPtr, Builder.CreateBitCast(PHIPtr, CGM.Int256PtrTy)}); + CGM.emitStorageStore( + Builder.CreateLoad(AddressPtr), + Builder.CreateLoad(Builder.CreateBitCast(PHIPtr, CGM.Int256PtrTy))); llvm::Value *CurrentAddress = Builder.CreateLoad(AddressPtr); llvm::Value *NextRemain = Builder.CreateSub(PHIRemain, Builder.getIntN(256, 32)); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 526467ab..cee3ecfe 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -88,22 +88,22 @@ void CodeGenFunction::emitDeclStmt(const DeclStmt *DS) { Builder.CreateStore(emitExpr(DS->getValue()).load(Builder, CGM), Addr); } else { switch (Ty->getCategory()) { - case Type::Category::Bool: - case Type::Category::Integer: - case Type::Category::Address: - Builder.CreateStore(llvm::ConstantInt::get(LLVMTy, 0), Addr); - break; - case Type::Category::String: - case Type::Category::Bytes: - Builder.CreateStore(llvm::ConstantAggregateZero::get(LLVMTy), Addr); - break; - case Type::Category::Array: - assert(false && "zero-init array not implement"); - __builtin_unreachable(); - break; - default: - assert(false && "unknown type"); - __builtin_unreachable(); + case Type::Category::Bool: + case Type::Category::Integer: + case Type::Category::Address: + Builder.CreateStore(llvm::ConstantInt::get(LLVMTy, 0), Addr); + break; + case Type::Category::String: + case Type::Category::Bytes: + Builder.CreateStore(llvm::ConstantAggregateZero::get(LLVMTy), Addr); + break; + case Type::Category::Array: + assert(false && "zero-init array not implement"); + __builtin_unreachable(); + break; + default: + assert(false && "unknown type"); + __builtin_unreachable(); } } } @@ -237,15 +237,19 @@ void CodeGenFunction::emitBranchOnBoolExpr(const Expr *E, void CodeGenFunction::emitCheckPayable(const FunctionDecl *FD) { if (StateMutability::Payable != FD->getStateMutability()) { - llvm::Function *getCallValue = - CGM.getModule().getFunction("ethereum.getCallValue"); - llvm::Value *ValPtr = Builder.CreateAlloca(Int128Ty); - Builder.CreateCall(getCallValue, {ValPtr}); llvm::BasicBlock *Continue = createBasicBlock("continue"); llvm::BasicBlock *Revert = createBasicBlock("revert"); - llvm::Value *Cond = Builder.CreateICmpNE(Builder.CreateLoad(ValPtr), - Builder.getIntN(128, 0)); + int N = 256; + if (CGM.isEVM()) { + N = 256; + } else if (CGM.isEWASM()) { + N = 128; + } else { + __builtin_unreachable(); + } + llvm::Value *Cond = + Builder.CreateICmpNE(CGM.emitGetCallValue(), Builder.getIntN(N, 0)); Builder.CreateCondBr(Cond, Revert, Continue); using namespace std::string_literals; @@ -253,8 +257,7 @@ void CodeGenFunction::emitCheckPayable(const FunctionDecl *FD) { llvm::Value *MessageValue = createGlobalStringPtr(getLLVMContext(), CGM.getModule(), Message); Builder.SetInsertPoint(Revert); - Builder.CreateCall(CGM.getModule().getFunction("ethereum.revert"), - {MessageValue, Builder.getInt32(Message.size())}); + CGM.emitRevert(MessageValue, Builder.getInt32(Message.size())); Builder.CreateUnreachable(); Builder.SetInsertPoint(Continue); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index bf6be062..dd6b7888 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -16,8 +16,13 @@ enum { evm_sload, evm_caller, evm_callvalue, + evm_log0, + evm_log1, + evm_log2, evm_log3, + evm_log4, evm_gas, + evm_sha3, evm_return, evm_revert, evm_returndatacopy, @@ -96,6 +101,10 @@ void CodeGenModule::initEVMOpcodeDeclaration() { FT = llvm::FunctionType::get(EVMIntTy, {}, false); Func_getCallDataSize = getIntrinsic(llvm::Intrinsic::evm_calldatasize, FT); + // evm_sha3 + FT = llvm::FunctionType::get(EVMIntTy, {EVMIntTy, EVMIntTy}, false); + Func_sha3 = getIntrinsic(llvm::Intrinsic::evm_sha3, FT); + // evm_staticcall FT = llvm::FunctionType::get( EVMIntTy, {EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy}, @@ -118,11 +127,30 @@ void CodeGenModule::initEVMOpcodeDeclaration() { FT = llvm::FunctionType::get(EVMIntTy, {}, false); Func_getCallValue = getIntrinsic(llvm::Intrinsic::evm_callvalue, FT); + // evm_log0 + FT = llvm::FunctionType::get(VoidTy, {EVMIntTy, EVMIntTy}, false); + Func_log0 = getIntrinsic(llvm::Intrinsic::evm_log0, FT); + + // evm_log1 + FT = llvm::FunctionType::get(VoidTy, {EVMIntTy, EVMIntTy, EVMIntTy}, false); + Func_log1 = getIntrinsic(llvm::Intrinsic::evm_log1, FT); + + // evm_log2 + FT = llvm::FunctionType::get(VoidTy, {EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy}, + false); + Func_log2 = getIntrinsic(llvm::Intrinsic::evm_log2, FT); + // evm_log3 FT = llvm::FunctionType::get( VoidTy, {EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy}, false); Func_log3 = getIntrinsic(llvm::Intrinsic::evm_log3, FT); + // evm_log4 + FT = llvm::FunctionType::get( + VoidTy, {EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy, EVMIntTy}, + false); + Func_log4 = getIntrinsic(llvm::Intrinsic::evm_log4, FT); + // evm_gas FT = llvm::FunctionType::get(EVMIntTy, {}, false); Func_getGasLeft = getIntrinsic(llvm::Intrinsic::evm_gas, FT); @@ -251,10 +279,10 @@ void CodeGenModule::initEEIDeclaration() { Func_getGasLeft->addFnAttr(llvm::Attribute::NoUnwind); // log - FT = - llvm::FunctionType::get(VoidTy, {Int8PtrTy, Int32Ty, Int32Ty, Int256PtrTy, - Int256PtrTy, Int256PtrTy, Int256PtrTy}, - false); + FT = llvm::FunctionType::get(VoidTy, + {Int8PtrTy, Int32Ty, Int32Ty, Int256PtrTy, + Int256PtrTy, Int256PtrTy, Int256PtrTy}, + false); Func_log = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, "ethereum.log", TheModule); Func_log->addFnAttr(Ethereum); @@ -512,17 +540,9 @@ void CodeGenModule::initKeccak256() { llvm::Value *Ptr = Builder.CreateExtractValue(Memory, {1}, "ptr"); if (isEVM()) { - llvm::Value *ResultPtr = - Builder.CreateAlloca(Int256Ty, nullptr, "result.ptr"); - llvm::Value *Fee = emitGetGasLeft(); - Builder.CreateCall(Func_callStatic, - {Fee, Builder.getIntN(256, 9), - Builder.CreatePtrToInt(Ptr, EVMIntTy), - Builder.CreateZExtOrTrunc(Length, EVMIntTy), - Builder.CreatePtrToInt(ResultPtr, EVMIntTy), - Builder.getIntN(256, 32)}); - llvm::Value *Result = Builder.CreateLoad(ResultPtr); - + llvm::Value *Result = Builder.CreateCall( + Func_sha3, {Builder.CreatePtrToInt(Ptr, EVMIntTy), + Builder.CreateZExtOrTrunc(Length, EVMIntTy)}); Builder.CreateRet(Result); } else if (isEWASM()) { llvm::Value *AddressPtr = @@ -559,17 +579,9 @@ void CodeGenModule::initSha256() { llvm::Value *Ptr = Builder.CreateExtractValue(Memory, {1}, "ptr"); if (isEVM()) { - llvm::Value *ResultPtr = - Builder.CreateAlloca(Int256Ty, nullptr, "result.ptr"); - llvm::Value *Fee = emitGetGasLeft(); - Builder.CreateCall(Func_callStatic, - {Fee, Builder.getIntN(256, 2), - Builder.CreatePtrToInt(Ptr, EVMIntTy), - Builder.CreateZExtOrTrunc(Length, EVMIntTy), - Builder.CreatePtrToInt(ResultPtr, EVMIntTy), - Builder.getIntN(256, 32)}); - llvm::Value *Result = Builder.CreateLoad(ResultPtr); - + llvm::Value *Result = Builder.CreateCall( + Func_sha3, {Builder.CreatePtrToInt(Ptr, EVMIntTy), + Builder.CreateZExtOrTrunc(Length, EVMIntTy)}); Builder.CreateRet(Result); } else if (isEWASM()) { llvm::Value *AddressPtr = @@ -674,8 +686,7 @@ void CodeGenModule::emitContractDispatcherDecl(const ContractDecl *CD) { emitFinish(llvm::ConstantPointerNull::get(Int8PtrTy), Builder.getInt32(0)); Builder.CreateRetVoid(); } else { - Builder.CreateCall(Func_revert, {llvm::ConstantPointerNull::get(Int8PtrTy), - Builder.getInt32(0)}); + emitRevert(llvm::ConstantPointerNull::get(Int8PtrTy), Builder.getInt32(0)); Builder.CreateUnreachable(); } @@ -698,8 +709,15 @@ void CodeGenModule::emitContractDispatcherDecl(const ContractDecl *CD) { Builder.SetInsertPoint(Entry); llvm::Value *callDataSize = Builder.CreateCall(Func_getCallDataSize, {}, "size"); - llvm::Value *cmp = - Builder.CreateICmpUGE(callDataSize, Builder.getInt32(4), "cmp"); + llvm::Value *CmpV = nullptr; + if (isEVM()) { + CmpV = Builder.getIntN(256, 4); + } else if (isEWASM()) { + CmpV = Builder.getInt32(4); + } else { + __builtin_unreachable(); + } + llvm::Value *cmp = Builder.CreateICmpUGE(callDataSize, CmpV, "cmp"); Builder.CreateCondBr(cmp, Switch, Error); Builder.SetInsertPoint(Switch); @@ -747,7 +765,7 @@ llvm::Value *CodeGenModule::emitABILoadParamStatic(const Type *Ty, Buffer, {Builder.getInt32(Offset)}, Name + ".cptr"); llvm::Value *Ptr = Builder.CreateBitCast(CPtr, Int256PtrTy, Name + ".ptr"); llvm::Value *ValB = Builder.CreateLoad(Int256Ty, Ptr, Name + ".b"); - llvm::Value *Val = Builder.CreateCall(Func_bswap256, {ValB}, Name + ".e"); + llvm::Value *Val = getEndianlessValue(ValB); return Builder.CreateZExtOrTrunc(Val, getLLVMType(Ty), Name); } @@ -801,9 +819,8 @@ void CodeGenModule::emitABIStore(const Type *Ty, llvm::StringRef Name, case Type::Category::FixedBytes: case Type::Category::Integer: { // XXX: check signed - llvm::Value *RetB = Builder.CreateCall( - Func_bswap256, {Builder.CreateZExtOrTrunc(Result, Int256Ty)}, - Name + ".ret.b"); + llvm::Value *RetB = + getEndianlessValue(Builder.CreateZExtOrTrunc(Result, Int256Ty)); // put return value to returndata llvm::Value *RetPtr = @@ -811,7 +828,7 @@ void CodeGenModule::emitABIStore(const Type *Ty, llvm::StringRef Name, Builder.CreateStore(RetB, RetPtr); llvm::Value *RetVPtr = Builder.CreateBitCast(RetPtr, Int8PtrTy, Name + ".ret.vptr"); - Builder.CreateCall(Func_finish, {RetVPtr, Builder.getInt32(32)}); + emitFinish(RetVPtr, Builder.getInt32(32)); break; } case Type::Category::Bytes: @@ -820,8 +837,7 @@ void CodeGenModule::emitABIStore(const Type *Ty, llvm::StringRef Name, Builder.CreateExtractValue(Result, {0}, Name + ".ret.len"); llvm::Value *RetLenTrunc = Builder.CreateTrunc(RetLen, Int32Ty, Name + ".ret.len.trunc"); - llvm::Value *RetLenB = - Builder.CreateCall(Func_bswap256, {RetLen}, Name + ".ret.len.b"); + llvm::Value *RetLenB = getEndianlessValue(RetLen); llvm::Value *RetData = Builder.CreateExtractValue(Result, {1}, Name + ".ret.data"); @@ -844,8 +860,7 @@ void CodeGenModule::emitABIStore(const Type *Ty, llvm::StringRef Name, llvm::Value *RetVPtr = Builder.CreateBitCast(RetPtr, Int8PtrTy, Name + ".ret.vptr"); - Builder.CreateCall(Func_finish, - {RetVPtr, Builder.CreateTrunc(RetSize, Int32Ty)}); + emitFinish(RetVPtr, Builder.CreateTrunc(RetSize, Int32Ty)); break; } default: @@ -928,8 +943,7 @@ void CodeGenModule::emitABILoad(const FunctionDecl *FD, const auto &Returns = FD->getReturnParams()->getParams(); if (Returns.empty()) { Builder.CreateCall(F, ArgsVal); - Builder.CreateCall(Func_finish, {llvm::ConstantPointerNull::get(Int8PtrTy), - Builder.getInt32(0)}); + emitFinish(llvm::ConstantPointerNull::get(Int8PtrTy), Builder.getInt32(0)); } else if (Returns.size() == 1) { llvm::Value *Result = Builder.CreateCall(F, ArgsVal, MangledName + ".ret"); emitABIStore(Returns.front()->GetType().get(), MangledName, Result); @@ -1080,6 +1094,16 @@ llvm::Function *CodeGenModule::createLLVMFunction(const CallableVarDecl *CVD) { return F; } +llvm::Value *CodeGenModule::getEndianlessValue(llvm::Value *Val) { + if (isEVM()) { + return Val; + } else if (isEWASM()) { + return emitEndianConvert(Val); + } else { + __builtin_unreachable(); + } +} + llvm::Value *CodeGenModule::emitEndianConvert(llvm::Value *Val) { // XXX: Assume type of Val is integer llvm::Type *Ty = Val->getType(); @@ -1096,6 +1120,130 @@ llvm::Value *CodeGenModule::emitGetGasLeft() { return Builder.CreateCall(Func_getGasLeft, {}); } +llvm::Value *CodeGenModule::emitGetCallValue() { + if (isEVM()) { + return Builder.CreateCall(Func_getCallValue, {}); + } else if (isEWASM()) { + llvm::Value *ValPtr = Builder.CreateAlloca(Int128Ty); + Builder.CreateCall(Func_getCallValue, {ValPtr}); + return Builder.CreateLoad(ValPtr); + } else { + __builtin_unreachable(); + } +} + +llvm::Value *CodeGenModule::emitGetCaller() { + if (isEVM()) { + return Builder.CreateCall(Func_getCaller, {}); + } else if (isEWASM()) { + llvm::Value *ValPtr = Builder.CreateAlloca(AddressTy); + Builder.CreateCall(Func_getCaller, {ValPtr}); + return getEndianlessValue(Builder.CreateLoad(ValPtr)); + } else { + __builtin_unreachable(); + } +} + +void CodeGenModule::emitLog(llvm::Value *DataOffset, llvm::Value *DataLength, + std::vector &Topics) { + if (isEVM()) { + llvm::Value *Length = Builder.CreateZExtOrTrunc(DataLength, EVMIntTy); + switch (Topics.size()) { + case 0: + Builder.CreateCall( + Func_log0, + {Builder.CreatePtrToInt( + Builder.CreateBitCast(DataOffset, Builder.getInt8PtrTy()), + EVMIntTy), + Length}); + break; + case 1: + Builder.CreateCall( + Func_log1, + {Builder.CreatePtrToInt( + Builder.CreateBitCast(DataOffset, Builder.getInt8PtrTy()), + EVMIntTy), + Length, Builder.CreateLoad(Topics[0])}); + break; + case 2: + Builder.CreateCall( + Func_log2, + {Builder.CreatePtrToInt( + Builder.CreateBitCast(DataOffset, Builder.getInt8PtrTy()), + EVMIntTy), + Length, Builder.CreateLoad(Topics[0]), + Builder.CreateLoad(Topics[1])}); + break; + case 3: + Builder.CreateCall( + Func_log3, + {Builder.CreatePtrToInt( + Builder.CreateBitCast(DataOffset, Builder.getInt8PtrTy()), + EVMIntTy), + Length, Builder.CreateLoad(Topics[0]), Builder.CreateLoad(Topics[1]), + Builder.CreateLoad(Topics[2])}); + break; + case 4: + Builder.CreateCall( + Func_log4, + {Builder.CreatePtrToInt( + Builder.CreateBitCast(DataOffset, Builder.getInt8PtrTy()), + EVMIntTy), + Length, Builder.CreateLoad(Topics[0]), Builder.CreateLoad(Topics[1]), + Builder.CreateLoad(Topics[2]), Builder.CreateLoad(Topics[3])}); + break; + default: + __builtin_unreachable(); + } + } else if (isEWASM()) { + Builder.CreateCall( + Func_log, {Builder.CreateBitCast(DataOffset, Builder.getInt8PtrTy()), + DataLength, Builder.getInt32(Topics.size()), Topics[0], + Topics[1], Topics[2], Topics[3]}); + } else { + __builtin_unreachable(); + } +} + +void CodeGenModule::emitStorageStore(llvm::Value *Key, llvm::Value *Value) { + if (isEVM()) { + Builder.CreateCall(Func_storageStore, {Key, Value}); + } else if (isEWASM()) { + llvm::Value *KeyPtr = Builder.CreateAlloca(Int256Ty, nullptr); + llvm::Value *ValPtr = Builder.CreateAlloca(Int256Ty, nullptr); + Builder.CreateStore(Key, KeyPtr); + Builder.CreateStore(Value, ValPtr); + Builder.CreateCall(Func_storageStore, {KeyPtr, ValPtr}); + } else { + __builtin_unreachable(); + } +} + +llvm::Value *CodeGenModule::emitStorageLoad(llvm::Value *Key) { + if (isEVM()) { + return Builder.CreateCall(Func_storageLoad, {Key}); + } else if (isEWASM()) { + llvm::Value *KeyPtr = Builder.CreateAlloca(Int256Ty, nullptr); + llvm::Value *ValPtr = Builder.CreateAlloca(Int256Ty, nullptr); + Builder.CreateStore(Key, KeyPtr); + Builder.CreateCall(Func_storageLoad, {KeyPtr, ValPtr}); + return Builder.CreateLoad(ValPtr); + } else { + __builtin_unreachable(); + } +} +void CodeGenModule::emitRevert(llvm::Value *DataOffset, llvm::Value *Length) { + if (isEVM()) { + Builder.CreateCall(Func_revert, + {Builder.CreatePtrToInt(DataOffset, EVMIntTy), + Builder.CreateZExtOrTrunc(Length, EVMIntTy)}); + } else if (isEWASM()) { + Builder.CreateCall(Func_revert, {DataOffset, Length}); + } else { + __builtin_unreachable(); + } +} + void CodeGenModule::emitFinish(llvm::Value *DataOffset, llvm::Value *Length) { if (isEVM()) { Builder.CreateCall(Func_finish, diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 6f982c90..01128da2 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -34,7 +34,11 @@ class CodeGenModule : public CodeGenTypeCache { llvm::Function *Func_getCaller = nullptr; llvm::Function *Func_getGasLeft = nullptr; llvm::Function *Func_log = nullptr; + llvm::Function *Func_log0 = nullptr; + llvm::Function *Func_log1 = nullptr; + llvm::Function *Func_log2 = nullptr; llvm::Function *Func_log3 = nullptr; + llvm::Function *Func_log4 = nullptr; llvm::Function *Func_returnDataCopy = nullptr; llvm::Function *Func_revert = nullptr; llvm::Function *Func_storageLoad = nullptr; @@ -52,6 +56,7 @@ class CodeGenModule : public CodeGenTypeCache { llvm::Function *Func_keccak256 = nullptr; llvm::Function *Func_sha256 = nullptr; + llvm::Function *Func_sha3 = nullptr; llvm::Function *Func_bswap256 = nullptr; llvm::Function *Func_memcpy = nullptr; @@ -86,11 +91,19 @@ class CodeGenModule : public CodeGenTypeCache { void emitContractDecl(const ContractDecl *CD); llvm::Value *emitEndianConvert(llvm::Value *Val); + llvm::Value *getEndianlessValue(llvm::Value *Val); llvm::Value *emitGetGasLeft(); + llvm::Value *emitGetCallValue(); + llvm::Value *emitGetCaller(); void emitFinish(llvm::Value *DataOffset, llvm::Value *Length); + void emitLog(llvm::Value *DataOffset, llvm::Value *DataLength, + std::vector &Topics); + void emitRevert(llvm::Value *DataOffset, llvm::Value *Length); void emitCallDataCopy(llvm::Value *ResultOffset, llvm::Value *DataOffset, llvm::Value *Length); + llvm::Value *emitStorageLoad(llvm::Value *Key); + void emitStorageStore(llvm::Value *Key, llvm::Value *Value); private: void emitContractConstructorDecl(const ContractDecl *CD);