Browse Source

Move code to loadFromMemory.

cl-refactor
Christian 10 years ago
parent
commit
9ba105a763
  1. 36
      libsolidity/Compiler.cpp
  2. 45
      libsolidity/CompilerUtils.cpp
  3. 9
      libsolidity/CompilerUtils.h
  4. 7
      libsolidity/ExpressionCompiler.cpp

36
libsolidity/Compiler.cpp

@ -147,7 +147,7 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
// retrieve the function signature hash from the calldata
if (!interfaceFunctions.empty())
CompilerUtils(m_context).loadFromMemory(0, 4, false, true);
CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true);
// stack now is: 1 0 <funhash>
for (auto const& it: interfaceFunctions)
@ -182,18 +182,10 @@ unsigned Compiler::appendCalldataUnpacker(TypePointers const& _typeParameters, b
{
// We do not check the calldata size, everything is zero-padded.
unsigned dataOffset = CompilerUtils::dataStartOffset; // the 4 bytes of the function hash signature
//@todo this can be done more efficiently, saving some CALLDATALOAD calls
bool const c_padToWords = true;
for (TypePointer const& type: _typeParameters)
{
unsigned const c_numBytes = type->getCalldataEncodedSize();
if (c_numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_comment("Type " + type->toString() + " not yet supported."));
bool const c_leftAligned = type->getCategory() == Type::Category::String;
bool const c_padToWords = true;
dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, c_numBytes, c_leftAligned,
!_fromMemory, c_padToWords);
}
dataOffset += CompilerUtils(m_context).loadFromMemory(dataOffset, *type, !_fromMemory, c_padToWords);
return dataOffset;
}
@ -255,22 +247,12 @@ bool Compiler::visit(FunctionDefinition const& _function)
// stack upon entry: [return address] [arg0] [arg1] ... [argn]
// reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp]
if (_function.getVisibility() != Declaration::Visibility::External)
{
unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters());
m_context.adjustStackOffset(parametersSize);
for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
{
m_context.addVariable(*variable, parametersSize);
parametersSize -= variable->getType()->getSizeOnStack();
}
}
else
unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters());
m_context.adjustStackOffset(parametersSize);
for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
{
unsigned calldataPos = CompilerUtils::dataStartOffset;
// calldatapos is _always_ dynamic.
for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
m_context.addCalldataVariable(*variable, calldataPos);
m_context.addVariable(*variable, parametersSize);
parametersSize -= variable->getType()->getSizeOnStack();
}
for (ASTPointer<VariableDeclaration const> const& variable: _function.getReturnParameters())
m_context.addAndInitializeVariable(*variable);

45
libsolidity/CompilerUtils.cpp

@ -33,33 +33,34 @@ namespace solidity
const unsigned int CompilerUtils::dataStartOffset = 4;
unsigned CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _leftAligned,
bool _fromCalldata, bool _padToWordBoundaries)
unsigned CompilerUtils::loadFromMemory(unsigned _offset, Type const& _type,
bool _fromCalldata, bool _padToWordBoundaries)
{
if (_bytes == 0)
{
solAssert(_type.getCategory() != Type::Category::ByteArray, "Unable to statically load dynamic type.");
unsigned _encodedSize = _type.getCalldataEncodedSize();
unsigned numBytes = _padToWordBoundaries ? getPaddedSize(_encodedSize) : _encodedSize;
bool leftAligned = _type.getCategory() == Type::Category::String;
if (numBytes == 0)
m_context << u256(0);
return 0;
}
eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD;
solAssert(_bytes <= 32, "Memory load of more than 32 bytes requested.");
if (_bytes == 32 || _padToWordBoundaries)
{
m_context << u256(_offset) << load;
return 32;
}
else
{
// load data and add leading or trailing zeros by dividing/multiplying depending on alignment
u256 shiftFactor = u256(1) << ((32 - _bytes) * 8);
m_context << shiftFactor;
if (_leftAligned)
m_context << eth::Instruction::DUP1;
m_context << u256(_offset) << load << eth::Instruction::DIV;
if (_leftAligned)
m_context << eth::Instruction::MUL;
return _bytes;
eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD;
solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
if (numBytes == 32)
m_context << u256(_offset) << load;
else
{
// load data and add leading or trailing zeros by dividing/multiplying depending on alignment
u256 shiftFactor = u256(1) << ((32 - numBytes) * 8);
m_context << shiftFactor;
if (leftAligned)
m_context << eth::Instruction::DUP1;
m_context << u256(_offset) << load << eth::Instruction::DIV;
if (leftAligned)
m_context << eth::Instruction::MUL;
}
}
return numBytes;
}
unsigned CompilerUtils::storeInMemory(unsigned _offset, Type const& _type, bool _padToWordBoundaries)

9
libsolidity/CompilerUtils.h

@ -37,14 +37,13 @@ public:
/// Loads data from memory to the stack.
/// @param _offset offset in memory (or calldata)
/// @param _bytes number of bytes to load
/// @param _leftAligned if true, store left aligned on stack (otherwise right aligned)
/// @param _type data type to load
/// @param _fromCalldata if true, load from calldata, not from memory
/// @param _padToWordBoundaries if true, assume the data is padded to word (32 byte) boundaries
/// @returns the number of bytes consumed in memory (can be different from _bytes if
/// _padToWordBoundaries is true)
unsigned loadFromMemory(unsigned _offset, unsigned _bytes = 32, bool _leftAligned = false,
bool _fromCalldata = false, bool _padToWordBoundaries = false);
/// _padToWordBoundaries is true)
unsigned loadFromMemory(unsigned _offset, Type const& _type = IntegerType(256),
bool _fromCalldata = false, bool _padToWordBoundaries = false);
/// Stores data from stack in memory.
/// @param _offset offset in memory
/// @param _type type of the data on the stack

7
libsolidity/ExpressionCompiler.cpp

@ -885,11 +885,8 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio
m_context << eth::Instruction::POP;
m_context << eth::Instruction::POP; // pop contract address
if (retSize > 0)
{
bool const c_leftAligned = firstType->getCategory() == Type::Category::String;
CompilerUtils(m_context).loadFromMemory(0, retSize, c_leftAligned, false, true);
}
if (firstType)
CompilerUtils(m_context).loadFromMemory(0, *firstType, false, true);
}
void ExpressionCompiler::appendArgumentsCopyToMemory(vector<ASTPointer<Expression const>> const& _arguments,

Loading…
Cancel
Save