Skip to content

Commit

Permalink
[CodeGen] Fix intrinsic functions for EVM target
Browse files Browse the repository at this point in the history
  • Loading branch information
hydai committed Nov 5, 2019
1 parent 440328b commit d5ad2ab
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 133 deletions.
59 changes: 20 additions & 39 deletions lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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();
}

Expand Down Expand Up @@ -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.");
Expand Down
43 changes: 14 additions & 29 deletions lib/CodeGen/CGValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand All @@ -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));
Expand Down
51 changes: 27 additions & 24 deletions lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand Down Expand Up @@ -237,24 +237,27 @@ 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;
static const std::string Message = "Function is not payable"s;
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);
Expand Down
Loading

0 comments on commit d5ad2ab

Please sign in to comment.