aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen/ExpressionCompiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen/ExpressionCompiler.cpp')
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp56
1 files changed, 33 insertions, 23 deletions
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 3922da88..b66a3e12 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -250,7 +250,12 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
}
if (lvalueSize > 0)
{
- solAssert(itemSize + lvalueSize <= 16, "Stack too deep, try removing local variables.");
+ if (itemSize + lvalueSize > 16)
+ BOOST_THROW_EXCEPTION(
+ CompilerError() <<
+ errinfo_sourceLocation(_assignment.location()) <<
+ errinfo_comment("Stack too deep, try removing local variables.")
+ );
// value [lvalue_ref] updated_value
for (unsigned i = 0; i < itemSize; ++i)
m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP;
@@ -551,20 +556,24 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arg->accept(*this);
argumentTypes.push_back(arg->annotation().type);
}
- ContractDefinition const& contract =
- dynamic_cast<ContractType const&>(*function.returnParameterTypes().front()).contractDefinition();
- // copy the contract's code into memory
- eth::Assembly const& assembly = m_context.compiledContract(contract);
- utils().fetchFreeMemoryPointer();
- // TODO we create a copy here, which is actually what we want.
- // This should be revisited at the point where we fix
- // https://github.com/ethereum/solidity/issues/1092
- // pushes size
- auto subroutine = m_context.addSubroutine(make_shared<eth::Assembly>(assembly));
- m_context << Instruction::DUP1 << subroutine;
- m_context << Instruction::DUP4 << Instruction::CODECOPY;
-
- m_context << Instruction::ADD;
+ ContractDefinition const* contract =
+ &dynamic_cast<ContractType const&>(*function.returnParameterTypes().front()).contractDefinition();
+ m_context.callLowLevelFunction(
+ "$copyContractCreationCodeToMemory_" + contract->type()->identifier(),
+ 0,
+ 1,
+ [contract](CompilerContext& _context)
+ {
+ // copy the contract's code into memory
+ eth::Assembly const& assembly = _context.compiledContract(*contract);
+ CompilerUtils(_context).fetchFreeMemoryPointer();
+ // pushes size
+ auto subroutine = _context.addSubroutine(make_shared<eth::Assembly>(assembly));
+ _context << Instruction::DUP1 << subroutine;
+ _context << Instruction::DUP4 << Instruction::CODECOPY;
+ _context << Instruction::ADD;
+ }
+ );
utils().encodeToMemory(argumentTypes, function.parameterTypes());
// now on stack: memory_end_ptr
// need: size, offset, endowment
@@ -576,7 +585,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << Instruction::CREATE;
// Check if zero (out of stack or not enough balance).
m_context << Instruction::DUP1 << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ m_context.appendConditionalInvalid();
if (function.valueSet())
m_context << swapInstruction(1) << Instruction::POP;
break;
@@ -892,7 +901,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
solAssert(funType->location() == FunctionType::Location::DelegateCall, "");
auto contract = dynamic_cast<ContractDefinition const*>(funType->declaration().scope());
solAssert(contract && contract->isLibrary(), "");
- m_context.appendLibraryAddress(contract->name());
+ m_context.appendLibraryAddress(contract->fullyQualifiedName());
m_context << funType->externalIdentifier();
utils().moveIntoStack(funType->selfType()->sizeOnStack(), 2);
}
@@ -1225,7 +1234,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
m_context << u256(fixedBytesType.numBytes());
m_context << Instruction::DUP2 << Instruction::LT << Instruction::ISZERO;
// out-of-bounds access throws exception
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ m_context.appendConditionalInvalid();
m_context << Instruction::BYTE;
m_context << (u256(1) << (256 - 8)) << Instruction::MUL;
@@ -1270,7 +1279,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
{
if (contract->isLibrary())
- m_context.appendLibraryAddress(contract->name());
+ m_context.appendLibraryAddress(contract->fullyQualifiedName());
}
else if (dynamic_cast<EventDefinition const*>(declaration))
{
@@ -1299,6 +1308,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
{
case Type::Category::RationalNumber:
case Type::Category::Bool:
+ case Type::Category::Integer:
m_context << type->literalValue(&_literal);
break;
case Type::Category::StringLiteral:
@@ -1406,7 +1416,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
{
// Test for division by zero
m_context << Instruction::DUP2 << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ m_context.appendConditionalInvalid();
if (_operator == Token::Div)
m_context << (c_isSigned ? Instruction::SDIV : Instruction::DIV);
@@ -1467,7 +1477,7 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type co
if (c_amountSigned)
{
m_context << u256(0) << Instruction::DUP3 << Instruction::SLT;
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ m_context.appendConditionalInvalid();
}
switch (_operator)
@@ -1653,7 +1663,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
if (funKind == FunctionKind::External || funKind == FunctionKind::CallCode || funKind == FunctionKind::DelegateCall)
{
m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ m_context.appendConditionalInvalid();
existenceChecked = true;
}
@@ -1689,7 +1699,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
{
//Propagate error condition (if CALL pushes 0 on stack).
m_context << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(m_context.errorTag());
+ m_context.appendConditionalInvalid();
}
utils().popStackSlots(remainsSize);