@ -201,7 +201,7 @@ set<FunctionDefinition const*> Compiler::getFunctionsCalled(set<ASTNode const*>
void Compiler : : appendFunctionSelector ( ContractDefinition const & _contract )
{
map < FixedHash < 4 > , FunctionDefini tion const * > interfaceFunctions = _contract . getInterfaceFunctions ( ) ;
map < FixedHash < 4 > , FunctionType const * , Declara tion const * > interfaceFunctions = _contract . getInterfaceFunctions ( ) ;
map < FixedHash < 4 > , const eth : : AssemblyItem > callDataUnpackerEntryPoints ;
// retrieve the function signature hash from the calldata
@ -209,7 +209,6 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
CompilerUtils ( m_context ) . loadFromMemory ( 0 , 4 , false , true ) ;
// stack now is: 1 0 <funhash>
// for (auto it = interfaceFunctions.cbegin(); it != interfaceFunctions.cend(); ++it)
for ( auto const & it : interfaceFunctions )
{
callDataUnpackerEntryPoints . insert ( std : : make_pair ( it . first , m_context . newTag ( ) ) ) ;
@ -220,29 +219,28 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
for ( auto const & it : interfaceFunctions )
{
FunctionDefinition const & function = * it . second ;
FunctionType const * functionType = * it . second . first ;
m_context < < callDataUnpackerEntryPoints . at ( it . first ) ;
eth : : AssemblyItem returnTag = m_context . pushNewTag ( ) ;
appendCalldataUnpacker ( function ) ;
m_context . appendJumpTo ( m_context . getFunctionEntryLabel ( function ) ) ;
appendCalldataUnpacker ( functionType - > getParameterTypes ( ) ) ;
m_context . appendJumpTo ( m_context . getFunctionEntryLabel ( it . second . second ) ) ;
m_context < < returnTag ;
appendReturnValuePacker ( function ) ;
appendReturnValuePacker ( functionType - > getReturnParameterTypes ( ) ) ;
}
}
unsigned Compiler : : appendCalldataUnpacker ( FunctionDefinition const & _function , bool _fromMemory )
unsigned Compiler : : appendCalldataUnpacker ( TypePointers const & _typeParameters , bool _fromMemory )
{
// 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
for ( AS TPointer< VariableDeclaration > const & var : _function . getParameters ( ) )
for ( Type Pointer const & type : _typeParameters )
{
unsigned const c_numBytes = var - > getT ype( ) - > getCalldataEncodedSize ( ) ;
unsigned const c_numBytes = t ype- > getCalldataEncodedSize ( ) ;
if ( c_numBytes > 32 )
BOOST_THROW_EXCEPTION ( CompilerError ( )
< < errinfo_sourceLocation ( var - > getLocation ( ) )
< < errinfo_comment ( " Type " + var - > getType ( ) - > toString ( ) + " not yet supported. " ) ) ;
bool const c_leftAligned = var - > getType ( ) - > getCategory ( ) = = Type : : Category : : STRING ;
< < 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 ) ;
@ -250,26 +248,26 @@ unsigned Compiler::appendCalldataUnpacker(FunctionDefinition const& _function, b
return dataOffset ;
}
void Compiler : : appendReturnValuePacker ( FunctionDefinition const & _function )
void Compiler : : appendReturnValuePacker ( TypePointers const & _typeParameters )
{
//@todo this can be also done more efficiently
unsigned dataOffset = 0 ;
vector < ASTPointer < VariableDeclaration > > const & parameters = _function . getReturnParameters ( ) ;
unsigned stackDepth = CompilerUtils ( m_context ) . getSizeOnStack ( parameters ) ;
for ( unsigned i = 0 ; i < parameters . size ( ) ; + + i )
unsigned stackDepth = 0 ;
for ( TypePointer const & type : _typeParameters )
stackDepth + = type - > getSizeOnStack ( ) ;
for ( TypePointer const & type : _typeParameters )
{
Type const & paramType = * parameters [ i ] - > getType ( ) ;
unsigned numBytes = paramType . getCalldataEncodedSize ( ) ;
unsigned numBytes = type - > getCalldataEncodedSize ( ) ;
if ( numBytes > 32 )
BOOST_THROW_EXCEPTION ( CompilerError ( )
< < errinfo_sourceLocation ( parameters [ i ] - > getLocation ( ) )
< < errinfo_comment ( " Type " + paramType . toString ( ) + " not yet supported. " ) ) ;
CompilerUtils ( m_context ) . copyToStackTop ( stackDepth , paramType ) ;
ExpressionCompiler : : appendTypeConversion ( m_context , paramType , paramType , true ) ;
bool const c_leftAligned = paramType . getCategory ( ) = = Type : : Category : : STRING ;
< < errinfo_comment ( " Type " + type - > toString ( ) + " not yet supported. " ) ) ;
CompilerUtils ( m_context ) . copyToStackTop ( stackDepth , * type ) ;
ExpressionCompiler : : appendTypeConversion ( m_context , * type , * type , true ) ;
bool const c_leftAligned = type - > getCategory ( ) = = Type : : Category : : STRING ;
bool const c_padToWords = true ;
dataOffset + = CompilerUtils ( m_context ) . storeInMemory ( dataOffset , numBytes , c_leftAligned , c_padToWords ) ;
stackDepth - = paramType . getSizeOnStack ( ) ;
stackDepth - = type - > getSizeOnStack ( ) ;
}
// note that the stack is not cleaned up here
m_context < < u256 ( dataOffset ) < < u256 ( 0 ) < < eth : : Instruction : : RETURN ;