aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/CompilerContext.cpp5
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp76
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp59
-rw-r--r--libsolidity/codegen/ExpressionCompiler.h12
-rw-r--r--libsolidity/codegen/LValue.cpp49
5 files changed, 98 insertions, 103 deletions
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 210b613d..6e14d68a 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -32,6 +32,7 @@
#include <libsolidity/inlineasm/AsmCodeGen.h>
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
+#include <libyul/YulString.h>
#include <boost/algorithm/string/replace.hpp>
@@ -326,7 +327,7 @@ void CompilerContext::appendInlineAssembly(
bool
)
{
- auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
+ auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
return it == _localVariables.end() ? size_t(-1) : 1;
};
identifierAccess.generateCode = [&](
@@ -335,7 +336,7 @@ void CompilerContext::appendInlineAssembly(
yul::AbstractAssembly& _assembly
)
{
- auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
+ auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
solAssert(it != _localVariables.end(), "");
int stackDepth = _localVariables.end() - it;
int stackDiff = _assembly.stackHeight() - startStackHeight + stackDepth;
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 2bdf88e3..90eb74fe 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -142,9 +142,13 @@ void CompilerUtils::storeInMemory(unsigned _offset)
void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries)
{
+ // process special types (Reference, StringLiteral, Function)
if (auto ref = dynamic_cast<ReferenceType const*>(&_type))
{
- solUnimplementedAssert(ref->location() == DataLocation::Memory, "Only in-memory reference type can be stored.");
+ solUnimplementedAssert(
+ ref->location() == DataLocation::Memory,
+ "Only in-memory reference type can be stored."
+ );
storeInMemoryDynamic(IntegerType(256), _padToWordBoundaries);
}
else if (auto str = dynamic_cast<StringLiteralType const*>(&_type))
@@ -166,18 +170,18 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
}
- else
+ else if (_type.isValueType())
{
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries);
- if (numBytes > 0)
- {
- solUnimplementedAssert(
- _type.sizeOnStack() == 1,
- "Memory store of types with stack size != 1 not implemented."
- );
- m_context << Instruction::DUP2 << Instruction::MSTORE;
- m_context << u256(numBytes) << Instruction::ADD;
- }
+ m_context << Instruction::DUP2 << Instruction::MSTORE;
+ m_context << u256(numBytes) << Instruction::ADD;
+ }
+ else // Should never happen
+ {
+ solAssert(
+ false,
+ "Memory store of type " + _type.toString(true) + " not allowed."
+ );
}
}
@@ -1012,8 +1016,22 @@ void CompilerUtils::convertType(
}
else
{
- // All other types should not be convertible to non-equal types.
- solAssert(_typeOnStack == _targetType, "Invalid type conversion requested.");
+ if (stackTypeCategory == Type::Category::Function && targetTypeCategory == Type::Category::Function)
+ {
+ FunctionType const& typeOnStack = dynamic_cast<FunctionType const&>(_typeOnStack);
+ FunctionType const& targetType = dynamic_cast<FunctionType const&>(_targetType);
+ solAssert(
+ typeOnStack.isImplicitlyConvertibleTo(targetType) &&
+ typeOnStack.sizeOnStack() == targetType.sizeOnStack() &&
+ (typeOnStack.kind() == FunctionType::Kind::Internal || typeOnStack.kind() == FunctionType::Kind::External) &&
+ typeOnStack.kind() == targetType.kind(),
+ "Invalid function type conversion requested."
+ );
+ }
+ else
+ // All other types should not be convertible to non-equal types.
+ solAssert(_typeOnStack == _targetType, "Invalid type conversion requested.");
+
if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32)
m_context
<< ((u256(1) << (8 * _targetType.storageBytes())) - 1)
@@ -1266,18 +1284,30 @@ void CompilerUtils::rightShiftNumberOnStack(unsigned _bits)
unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords)
{
+ solAssert(
+ _type.sizeOnStack() == 1,
+ "Memory store of types with stack size != 1 not allowed (Type: " + _type.toString(true) + ")."
+ );
+
unsigned numBytes = _type.calldataEncodedSize(_padToWords);
+
+ solAssert(
+ numBytes > 0,
+ "Memory store of 0 bytes requested (Type: " + _type.toString(true) + ")."
+ );
+
+ solAssert(
+ numBytes <= 32,
+ "Memory store of more than 32 bytes requested (Type: " + _type.toString(true) + ")."
+ );
+
bool leftAligned = _type.category() == Type::Category::FixedBytes;
- if (numBytes == 0)
- m_context << Instruction::POP;
- else
- {
- solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested.");
- convertType(_type, _type, true);
- if (numBytes != 32 && !leftAligned && !_padToWords)
- // shift the value accordingly before storing
- leftShiftNumberOnStack((32 - numBytes) * 8);
- }
+
+ convertType(_type, _type, true);
+ if (numBytes != 32 && !leftAligned && !_padToWords)
+ // shift the value accordingly before storing
+ leftShiftNumberOnStack((32 - numBytes) * 8);
+
return numBytes;
}
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 3383d8ae..bdf91fbf 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -206,8 +206,8 @@ bool ExpressionCompiler::visit(Conditional const& _condition)
bool ExpressionCompiler::visit(Assignment const& _assignment)
{
CompilerContext::LocationSetter locationSetter(m_context, _assignment);
- Token::Value op = _assignment.assignmentOperator();
- Token::Value binOp = op == Token::Assign ? op : Token::AssignmentToBinaryOp(op);
+ Token op = _assignment.assignmentOperator();
+ Token binOp = op == Token::Assign ? op : TokenTraits::AssignmentToBinaryOp(op);
Type const& leftType = *_assignment.leftHandSide().annotation().type;
if (leftType.category() == Type::Category::Tuple)
{
@@ -223,7 +223,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
// Perform some conversion already. This will convert storage types to memory and literals
// to their actual type, but will not convert e.g. memory to storage.
TypePointer rightIntermediateType;
- if (op != Token::Assign && Token::isShiftOp(binOp))
+ if (op != Token::Assign && TokenTraits::isShiftOp(binOp))
rightIntermediateType = _assignment.rightHandSide().annotation().type->mobileType();
else
rightIntermediateType = _assignment.rightHandSide().annotation().type->closestTemporaryType(
@@ -251,7 +251,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
m_currentLValue->retrieveValue(_assignment.location(), true);
utils().convertType(leftType, leftType, cleanupNeeded);
- if (Token::isShiftOp(binOp))
+ if (TokenTraits::isShiftOp(binOp))
appendShiftOperatorCode(binOp, leftType, *rightIntermediateType);
else
{
@@ -384,7 +384,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
m_context << u256(0) << Instruction::SUB;
break;
default:
- solAssert(false, "Invalid unary operator: " + string(Token::toString(_unaryOperation.getOperator())));
+ solAssert(false, "Invalid unary operator: " + string(TokenTraits::toString(_unaryOperation.getOperator())));
}
return false;
}
@@ -396,7 +396,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
Expression const& rightExpression = _binaryOperation.rightExpression();
solAssert(!!_binaryOperation.annotation().commonType, "");
TypePointer const& commonType = _binaryOperation.annotation().commonType;
- Token::Value const c_op = _binaryOperation.getOperator();
+ Token const c_op = _binaryOperation.getOperator();
if (c_op == Token::And || c_op == Token::Or) // special case: short-circuiting
appendAndOrOperatorCode(_binaryOperation);
@@ -407,7 +407,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
bool cleanupNeeded = cleanupNeededForOp(commonType->category(), c_op);
TypePointer leftTargetType = commonType;
- TypePointer rightTargetType = Token::isShiftOp(c_op) ? rightExpression.annotation().type->mobileType() : commonType;
+ TypePointer rightTargetType = TokenTraits::isShiftOp(c_op) ? rightExpression.annotation().type->mobileType() : commonType;
solAssert(rightTargetType, "");
// for commutative operators, push the literal as late as possible to allow improved optimization
@@ -415,7 +415,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
{
return dynamic_cast<Literal const*>(&_e) || _e.annotation().type->category() == Type::Category::RationalNumber;
};
- bool swap = m_optimize && Token::isCommutativeOp(c_op) && isLiteral(rightExpression) && !isLiteral(leftExpression);
+ bool swap = m_optimize && TokenTraits::isCommutativeOp(c_op) && isLiteral(rightExpression) && !isLiteral(leftExpression);
if (swap)
{
leftExpression.accept(*this);
@@ -430,10 +430,10 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
leftExpression.accept(*this);
utils().convertType(*leftExpression.annotation().type, *leftTargetType, cleanupNeeded);
}
- if (Token::isShiftOp(c_op))
+ if (TokenTraits::isShiftOp(c_op))
// shift only cares about the signedness of both sides
appendShiftOperatorCode(c_op, *leftTargetType, *rightTargetType);
- else if (Token::isCompareOp(c_op))
+ else if (TokenTraits::isCompareOp(c_op))
appendCompareOperatorCode(c_op, *commonType);
else
appendOrdinaryBinaryOperatorCode(c_op, *commonType);
@@ -568,12 +568,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::External:
case FunctionType::Kind::DelegateCall:
case FunctionType::Kind::BareCall:
- case FunctionType::Kind::BareCallCode:
case FunctionType::Kind::BareDelegateCall:
case FunctionType::Kind::BareStaticCall:
_functionCall.expression().accept(*this);
appendExternalFunctionCall(function, arguments);
break;
+ case FunctionType::Kind::BareCallCode:
+ solAssert(false, "Callcode has been removed.");
case FunctionType::Kind::Creation:
{
_functionCall.expression().accept(*this);
@@ -1328,8 +1329,6 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
m_context << Instruction::CALLVALUE;
else if (member == "origin")
m_context << Instruction::ORIGIN;
- else if (member == "gas")
- m_context << Instruction::GAS;
else if (member == "gasprice")
m_context << Instruction::GASPRICE;
else if (member == "data")
@@ -1337,9 +1336,10 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
else if (member == "sig")
m_context << u256(0) << Instruction::CALLDATALOAD
<< (u256(0xffffffff) << (256 - 32)) << Instruction::AND;
+ else if (member == "gas")
+ solAssert(false, "Gas has been removed.");
else if (member == "blockhash")
- {
- }
+ solAssert(false, "Blockhash has been removed.");
else
solAssert(false, "Unknown magic member.");
break;
@@ -1602,7 +1602,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation)
{
- Token::Value const c_op = _binaryOperation.getOperator();
+ Token const c_op = _binaryOperation.getOperator();
solAssert(c_op == Token::Or || c_op == Token::And, "");
_binaryOperation.leftExpression().accept(*this);
@@ -1615,7 +1615,7 @@ void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryO
m_context << endLabel;
}
-void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type const& _type)
+void ExpressionCompiler::appendCompareOperatorCode(Token _operator, Type const& _type)
{
solAssert(_type.sizeOnStack() == 1, "Comparison of multi-slot types.");
if (_operator == Token::Equal || _operator == Token::NotEqual)
@@ -1665,17 +1665,17 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type
}
}
-void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type)
+void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token _operator, Type const& _type)
{
- if (Token::isArithmeticOp(_operator))
+ if (TokenTraits::isArithmeticOp(_operator))
appendArithmeticOperatorCode(_operator, _type);
- else if (Token::isBitOp(_operator))
+ else if (TokenTraits::isBitOp(_operator))
appendBitOperatorCode(_operator);
else
solAssert(false, "Unknown binary operator.");
}
-void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Type const& _type)
+void ExpressionCompiler::appendArithmeticOperatorCode(Token _operator, Type const& _type)
{
if (_type.category() == Type::Category::FixedPoint)
solUnimplemented("Not yet implemented - FixedPointType.");
@@ -1715,7 +1715,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
}
}
-void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator)
+void ExpressionCompiler::appendBitOperatorCode(Token _operator)
{
switch (_operator)
{
@@ -1733,7 +1733,7 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator)
}
}
-void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type const& _valueType, Type const& _shiftAmountType)
+void ExpressionCompiler::appendShiftOperatorCode(Token _operator, Type const& _valueType, Type const& _shiftAmountType)
{
// stack: shift_amount value_to_shift
@@ -1844,8 +1844,9 @@ void ExpressionCompiler::appendExternalFunctionCall(
solAssert(funKind != FunctionType::Kind::BareStaticCall || m_context.evmVersion().hasStaticCall(), "");
- bool returnSuccessConditionAndReturndata = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall;
- bool isCallCode = funKind == FunctionType::Kind::BareCallCode;
+ solAssert(funKind != FunctionType::Kind::BareCallCode, "Callcode has been removed.");
+
+ bool returnSuccessConditionAndReturndata = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall;
bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall;
bool useStaticCall = funKind == FunctionType::Kind::BareStaticCall || (_functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall());
@@ -1930,7 +1931,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
parameterTypes,
_functionType.padArguments(),
_functionType.takesArbitraryParameters() || _functionType.isBareCall(),
- isCallCode || isDelegateCall
+ isDelegateCall
);
// Stack now:
@@ -2001,8 +2002,6 @@ void ExpressionCompiler::appendExternalFunctionCall(
// Order is important here, STATICCALL might overlap with DELEGATECALL.
if (isDelegateCall)
m_context << Instruction::DELEGATECALL;
- else if (isCallCode)
- m_context << Instruction::CALLCODE;
else if (useStaticCall)
m_context << Instruction::STATICCALL;
else
@@ -2141,9 +2140,9 @@ void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression)
setLValue<StorageItem>(_expression, *_expression.annotation().type);
}
-bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _op)
+bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token _op)
{
- if (Token::isCompareOp(_op) || Token::isShiftOp(_op))
+ if (TokenTraits::isCompareOp(_op) || TokenTraits::isShiftOp(_op))
return true;
else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod || _op == Token::Exp))
// We need cleanup for EXP because 0**0 == 1, but 0**0x100 == 0
diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h
index cdfa096e..3d8e8682 100644
--- a/libsolidity/codegen/ExpressionCompiler.h
+++ b/libsolidity/codegen/ExpressionCompiler.h
@@ -86,12 +86,12 @@ private:
///@{
///@name Append code for various operator types
void appendAndOrOperatorCode(BinaryOperation const& _binaryOperation);
- void appendCompareOperatorCode(Token::Value _operator, Type const& _type);
- void appendOrdinaryBinaryOperatorCode(Token::Value _operator, Type const& _type);
+ void appendCompareOperatorCode(Token _operator, Type const& _type);
+ void appendOrdinaryBinaryOperatorCode(Token _operator, Type const& _type);
- void appendArithmeticOperatorCode(Token::Value _operator, Type const& _type);
- void appendBitOperatorCode(Token::Value _operator);
- void appendShiftOperatorCode(Token::Value _operator, Type const& _valueType, Type const& _shiftAmountType);
+ void appendArithmeticOperatorCode(Token _operator, Type const& _type);
+ void appendBitOperatorCode(Token _operator);
+ void appendShiftOperatorCode(Token _operator, Type const& _valueType, Type const& _shiftAmountType);
/// @}
/// Appends code to call a function of the given type with the given arguments.
@@ -119,7 +119,7 @@ private:
/// @returns true if the operator applied to the given type requires a cleanup prior to the
/// operation.
- static bool cleanupNeededForOp(Type::Category _type, Token::Value _op);
+ static bool cleanupNeededForOp(Type::Category _type, Token _op);
/// @returns the CompilerUtils object containing the current context.
CompilerUtils utils();
diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp
index 77684683..790ab309 100644
--- a/libsolidity/codegen/LValue.cpp
+++ b/libsolidity/codegen/LValue.cpp
@@ -134,8 +134,7 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool
void MemoryItem::setToZero(SourceLocation const&, bool _removeReference) const
{
CompilerUtils utils(m_context);
- if (!_removeReference)
- m_context << Instruction::DUP1;
+ solAssert(_removeReference, "");
utils.pushZeroValue(*m_dataType);
utils.storeInMemoryDynamic(*m_dataType, m_padded);
m_context << Instruction::POP;
@@ -460,8 +459,7 @@ void StorageByteArrayElement::storeValue(Type const&, SourceLocation const&, boo
void StorageByteArrayElement::setToZero(SourceLocation const&, bool _removeReference) const
{
// stack: ref byte_number
- if (!_removeReference)
- m_context << Instruction::DUP2 << Instruction::DUP2;
+ solAssert(_removeReference, "");
m_context << u256(31) << Instruction::SUB << u256(0x100) << Instruction::EXP;
// stack: ref (1<<(8*(31-byte_number)))
m_context << Instruction::DUP2 << Instruction::SLOAD;
@@ -498,8 +496,7 @@ void StorageArrayLength::storeValue(Type const&, SourceLocation const&, bool _mo
void StorageArrayLength::setToZero(SourceLocation const&, bool _removeReference) const
{
- if (!_removeReference)
- m_context << Instruction::DUP1;
+ solAssert(_removeReference, "");
ArrayUtils(m_context).clearDynamicArray(m_arrayType);
}
@@ -521,24 +518,9 @@ unsigned TupleObject::sizeOnStack() const
return size;
}
-void TupleObject::retrieveValue(SourceLocation const& _location, bool _remove) const
+void TupleObject::retrieveValue(SourceLocation const&, bool) const
{
- unsigned initialDepth = sizeOnStack();
- unsigned initialStack = m_context.stackHeight();
- for (auto const& lv: m_lvalues)
- if (lv)
- {
- solAssert(initialDepth + m_context.stackHeight() >= initialStack, "");
- unsigned depth = initialDepth + m_context.stackHeight() - initialStack;
- if (lv->sizeOnStack() > 0)
- {
- if (_remove && depth > lv->sizeOnStack())
- CompilerUtils(m_context).moveToStackTop(depth, depth - lv->sizeOnStack());
- else if (!_remove && depth > 0)
- CompilerUtils(m_context).copyToStackTop(depth, lv->sizeOnStack());
- }
- lv->retrieveValue(_location, true);
- }
+ solAssert(false, "Tried to retrieve value of tuple.");
}
void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _location, bool) const
@@ -569,24 +551,7 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc
CompilerUtils(m_context).popStackElement(_sourceType);
}
-void TupleObject::setToZero(SourceLocation const& _location, bool _removeReference) const
+void TupleObject::setToZero(SourceLocation const&, bool) const
{
- if (_removeReference)
- {
- for (size_t i = 0; i < m_lvalues.size(); ++i)
- if (m_lvalues[m_lvalues.size() - i])
- m_lvalues[m_lvalues.size() - i]->setToZero(_location, true);
- }
- else
- {
- unsigned depth = sizeOnStack();
- for (auto const& val: m_lvalues)
- if (val)
- {
- if (val->sizeOnStack() > 0)
- CompilerUtils(m_context).copyToStackTop(depth, val->sizeOnStack());
- val->setToZero(_location, false);
- depth -= val->sizeOnStack();
- }
- }
+ solAssert(false, "Tried to delete tuple.");
}