Change alignment.

This commit is contained in:
chriseth 2016-10-19 18:43:31 +02:00
parent 679ea2820f
commit ff3553a348
4 changed files with 45 additions and 33 deletions

View File

@ -2078,7 +2078,7 @@ TypePointer FunctionType::encodingType() const
TypePointer FunctionType::interfaceType(bool /*_inLibrary*/) const TypePointer FunctionType::interfaceType(bool /*_inLibrary*/) const
{ {
if (m_location == Location::External) if (m_location == Location::External)
return make_shared<IntegerType>(8 * storageBytes()); return make_shared<FixedBytesType>(storageBytes());
else else
return TypePointer(); return TypePointer();
} }

View File

@ -139,7 +139,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
) )
{ {
solAssert(_padToWordBoundaries, "Non-padded store for function not implemented."); solAssert(_padToWordBoundaries, "Non-padded store for function not implemented.");
combineExternalFunctionType(); combineExternalFunctionType(true);
m_context << Instruction::DUP2 << Instruction::MSTORE; m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD; m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
} }
@ -315,19 +315,29 @@ void CompilerUtils::memoryCopy()
m_context << Instruction::POP; // ignore return value m_context << Instruction::POP; // ignore return value
} }
void CompilerUtils::splitExternalFunctionType() void CompilerUtils::splitExternalFunctionType(bool _leftAligned)
{ {
// We have to split the right-aligned <function identifier><address> into two stack slots: // We have to split the left-aligned <function identifier><address> into two stack slots:
// address (right aligned), function identifier (right aligned) // address (right aligned), function identifier (right aligned)
if (_leftAligned)
m_context << (u256(1) << 64) << Instruction::SWAP1 << Instruction::DIV;
m_context << Instruction::DUP1 << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::SWAP1; m_context << Instruction::DUP1 << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::SWAP1;
m_context << (u256(1) << 160) << Instruction::SWAP1 << Instruction::DIV; m_context << (u256(1) << 160) << Instruction::SWAP1 << Instruction::DIV;
if (!_leftAligned)
m_context << u256(0xffffffffUL) << Instruction::AND; m_context << u256(0xffffffffUL) << Instruction::AND;
} }
void CompilerUtils::combineExternalFunctionType() void CompilerUtils::combineExternalFunctionType(bool _leftAligned)
{ {
m_context << u256(0xffffffffUL) << Instruction::AND << (u256(1) << 160) << Instruction::MUL << Instruction::SWAP1; if (_leftAligned)
m_context << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::OR; m_context << (u256(1) << 224);
else
m_context << u256(0xffffffffUL) << Instruction::AND << (u256(1) << 160);
m_context << Instruction::MUL << Instruction::SWAP1;
m_context << ((u256(1) << 160) - 1) << Instruction::AND;
if (_leftAligned)
m_context << (u256(1) << 64) << Instruction::MUL;
m_context << Instruction::OR;
} }
void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded) void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded)
@ -856,26 +866,28 @@ void CompilerUtils::storeStringData(bytesConstRef _data)
unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries)
{ {
unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries); unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries);
bool leftAligned = _type.category() == Type::Category::FixedBytes; bool isExternalFunctionType = false;
if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
if (funType->location() == FunctionType::Location::External)
isExternalFunctionType = true;
if (numBytes == 0) if (numBytes == 0)
m_context << Instruction::POP << u256(0);
else
{ {
m_context << Instruction::POP << u256(0);
return numBytes;
}
solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested."); solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD); m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD);
if (numBytes != 32) if (isExternalFunctionType)
splitExternalFunctionType(true);
else if (numBytes != 32)
{ {
bool leftAligned = _type.category() == Type::Category::FixedBytes;
// add leading or trailing zeros by dividing/multiplying depending on alignment // add leading or trailing zeros by dividing/multiplying depending on alignment
u256 shiftFactor = u256(1) << ((32 - numBytes) * 8); u256 shiftFactor = u256(1) << ((32 - numBytes) * 8);
m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV; m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV;
if (leftAligned) if (leftAligned)
m_context << shiftFactor << Instruction::MUL; m_context << shiftFactor << Instruction::MUL;
} }
}
if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
if (funType->location() == FunctionType::Location::External)
splitExternalFunctionType();
return numBytes; return numBytes;
} }

View File

@ -114,12 +114,12 @@ public:
/// Stack post: /// Stack post:
void memoryCopy(); void memoryCopy();
/// Converts the combined and right-aligned external function type /// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true)
/// <function identifier><address> into two stack slots: /// external function type <function identifier><address> into two stack slots:
/// address (right aligned), function identifier (right aligned) /// address (right aligned), function identifier (right aligned)
void splitExternalFunctionType(); void splitExternalFunctionType(bool _rightAligned);
/// Performs the opposite operation of splitExternalFunctionType() /// Performs the opposite operation of splitExternalFunctionType(_rightAligned)
void combineExternalFunctionType(); void combineExternalFunctionType(bool _rightAligned);
/// Appends code for an implicit or explicit type conversion. This includes erasing higher /// Appends code for an implicit or explicit type conversion. This includes erasing higher
/// order bits (@see appendHighBitCleanup) when widening integer but also copy to memory /// order bits (@see appendHighBitCleanup) when widening integer but also copy to memory

View File

@ -194,7 +194,7 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
m_dataType->category() == Type::Category::Function && m_dataType->category() == Type::Category::Function &&
dynamic_cast<FunctionType const&>(*m_dataType).location() == FunctionType::Location::External dynamic_cast<FunctionType const&>(*m_dataType).location() == FunctionType::Location::External
) )
CompilerUtils(m_context).splitExternalFunctionType(); CompilerUtils(m_context).splitExternalFunctionType(false);
else else
{ {
solAssert(m_dataType->sizeOnStack() == 1, ""); solAssert(m_dataType->sizeOnStack() == 1, "");
@ -241,7 +241,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
dynamic_cast<FunctionType const&>(*m_dataType).location() == FunctionType::Location::External dynamic_cast<FunctionType const&>(*m_dataType).location() == FunctionType::Location::External
) )
// Combine the two-item function type into a single stack slot. // Combine the two-item function type into a single stack slot.
utils.combineExternalFunctionType(); utils.combineExternalFunctionType(false);
else if (m_dataType->category() == Type::Category::FixedBytes) else if (m_dataType->category() == Type::Category::FixedBytes)
m_context m_context
<< (u256(0x1) << (256 - 8 * dynamic_cast<FixedBytesType const&>(*m_dataType).numBytes())) << (u256(0x1) << (256 - 8 * dynamic_cast<FixedBytesType const&>(*m_dataType).numBytes()))