mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
bytes parameters for events and sha3.
This commit is contained in:
+80
-11
@@ -532,7 +532,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case Location::SHA3:
|
||||
{
|
||||
m_context << u256(0);
|
||||
appendArgumentsCopyToMemory(arguments, TypePointers(), function.padArguments());
|
||||
appendArgumentsCopyToMemory(arguments, TypePointers(), function.padArguments(), false, true);
|
||||
m_context << u256(0) << eth::Instruction::SHA3;
|
||||
break;
|
||||
}
|
||||
@@ -575,9 +575,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
solAssert(numIndexed <= 4, "Too many indexed arguments.");
|
||||
// Copy all non-indexed arguments to memory (data)
|
||||
m_context << u256(0);
|
||||
vector<ASTPointer<Expression const>> nonIndexedArgs;
|
||||
TypePointers nonIndexedTypes;
|
||||
for (unsigned arg = 0; arg < arguments.size(); ++arg)
|
||||
if (!event.getParameters()[arg]->isIndexed())
|
||||
appendExpressionCopyToMemory(*function.getParameterTypes()[arg], *arguments[arg]);
|
||||
{
|
||||
nonIndexedArgs.push_back(arguments[arg]);
|
||||
nonIndexedTypes.push_back(function.getParameterTypes()[arg]);
|
||||
}
|
||||
appendArgumentsCopyToMemory(nonIndexedArgs, nonIndexedTypes);
|
||||
m_context << u256(0) << eth::logInstruction(numIndexed);
|
||||
break;
|
||||
}
|
||||
@@ -1046,8 +1052,14 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
|
||||
|
||||
// For bare call, activate "4 byte pad exception": If the first argument has exactly 4 bytes,
|
||||
// do not pad it to 32 bytes.
|
||||
appendArgumentsCopyToMemory(_arguments, _functionType.getParameterTypes(),
|
||||
_functionType.padArguments(), bare);
|
||||
// If the function takes arbitrary parameters, copy dynamic length data in place.
|
||||
appendArgumentsCopyToMemory(
|
||||
_arguments,
|
||||
_functionType.getParameterTypes(),
|
||||
_functionType.padArguments(),
|
||||
bare,
|
||||
_functionType.takesArbitraryParameters()
|
||||
);
|
||||
|
||||
// CALL arguments: outSize, outOff, inSize, (already present up to here)
|
||||
// inOff, value, addr, gas (stack top)
|
||||
@@ -1089,20 +1101,72 @@ void ExpressionCompiler::appendArgumentsCopyToMemory(
|
||||
vector<ASTPointer<Expression const>> const& _arguments,
|
||||
TypePointers const& _types,
|
||||
bool _padToWordBoundaries,
|
||||
bool _padExceptionIfFourBytes
|
||||
bool _padExceptionIfFourBytes,
|
||||
bool _copyDynamicDataInPlace
|
||||
)
|
||||
{
|
||||
solAssert(_types.empty() || _types.size() == _arguments.size(), "");
|
||||
TypePointers types = _types;
|
||||
if (_types.empty())
|
||||
for (ASTPointer<Expression const> const& argument: _arguments)
|
||||
types.push_back(argument->getType()->getRealType());
|
||||
|
||||
vector<size_t> dynamicArguments;
|
||||
unsigned stackSizeOfDynamicTypes = 0;
|
||||
for (size_t i = 0; i < _arguments.size(); ++i)
|
||||
{
|
||||
_arguments[i]->accept(*this);
|
||||
TypePointer const& expectedType = _types.empty() ? _arguments[i]->getType()->getRealType() : _types[i];
|
||||
appendTypeConversion(*_arguments[i]->getType(), *expectedType, true);
|
||||
TypePointer argType = types[i]->externalType();
|
||||
solAssert(!!argType, "Externalable type expected.");
|
||||
if (argType->isValueType())
|
||||
appendTypeConversion(*_arguments[i]->getType(), *argType, true);
|
||||
else
|
||||
argType = _arguments[i]->getType()->getRealType()->externalType();
|
||||
solAssert(!!argType, "Externalable type expected.");
|
||||
bool pad = _padToWordBoundaries;
|
||||
// Do not pad if the first argument has exactly four bytes
|
||||
if (i == 0 && pad && _padExceptionIfFourBytes && expectedType->getCalldataEncodedSize(false) == 4)
|
||||
if (i == 0 && pad && _padExceptionIfFourBytes && argType->getCalldataEncodedSize(false) == 4)
|
||||
pad = false;
|
||||
appendTypeMoveToMemory(*expectedType, pad);
|
||||
if (!_copyDynamicDataInPlace && argType->isDynamicallySized())
|
||||
{
|
||||
solAssert(argType->getCategory() == Type::Category::Array, "Unknown dynamic type.");
|
||||
auto const& arrayType = dynamic_cast<ArrayType const&>(*_arguments[i]->getType());
|
||||
// move memory reference to top of stack
|
||||
CompilerUtils(m_context).moveToStackTop(arrayType.getSizeOnStack());
|
||||
if (arrayType.getLocation() == ArrayType::Location::CallData)
|
||||
m_context << eth::Instruction::DUP2; // length is on stack
|
||||
else if (arrayType.getLocation() == ArrayType::Location::Storage)
|
||||
m_context << eth::Instruction::DUP3 << eth::Instruction::SLOAD;
|
||||
else
|
||||
{
|
||||
solAssert(arrayType.getLocation() == ArrayType::Location::Memory, "");
|
||||
m_context << eth::Instruction::DUP2 << eth::Instruction::MLOAD;
|
||||
}
|
||||
appendTypeMoveToMemory(IntegerType(256), true);
|
||||
stackSizeOfDynamicTypes += arrayType.getSizeOnStack();
|
||||
dynamicArguments.push_back(i);
|
||||
}
|
||||
else
|
||||
appendTypeMoveToMemory(*argType, pad);
|
||||
}
|
||||
|
||||
// copy dynamic values to memory
|
||||
unsigned dynStackPointer = stackSizeOfDynamicTypes;
|
||||
// stack layout: <dyn arg 1> ... <dyn arg m> <memory pointer>
|
||||
for (size_t i: dynamicArguments)
|
||||
{
|
||||
auto const& arrayType = dynamic_cast<ArrayType const&>(*_arguments[i]->getType());
|
||||
CompilerUtils(m_context).copyToStackTop(1 + dynStackPointer, arrayType.getSizeOnStack());
|
||||
dynStackPointer -= arrayType.getSizeOnStack();
|
||||
appendTypeMoveToMemory(arrayType, true);
|
||||
}
|
||||
solAssert(dynStackPointer == 0, "");
|
||||
|
||||
// remove dynamic values (and retain memory pointer)
|
||||
if (stackSizeOfDynamicTypes > 0)
|
||||
{
|
||||
m_context << eth::swapInstruction(stackSizeOfDynamicTypes);
|
||||
CompilerUtils(m_context).popStackSlots(stackSizeOfDynamicTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1114,8 +1178,13 @@ void ExpressionCompiler::appendTypeMoveToMemory(Type const& _type, bool _padToWo
|
||||
void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression)
|
||||
{
|
||||
_expression.accept(*this);
|
||||
appendTypeConversion(*_expression.getType(), _expectedType, true);
|
||||
appendTypeMoveToMemory(_expectedType);
|
||||
if (_expectedType.isValueType())
|
||||
{
|
||||
appendTypeConversion(*_expression.getType(), _expectedType, true);
|
||||
appendTypeMoveToMemory(_expectedType);
|
||||
}
|
||||
else
|
||||
appendTypeMoveToMemory(*_expression.getType()->getRealType());
|
||||
}
|
||||
|
||||
void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression)
|
||||
|
||||
Reference in New Issue
Block a user