aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp58
-rw-r--r--libsolidity/codegen/CompilerUtils.h10
-rw-r--r--libsolidity/codegen/LValue.cpp4
3 files changed, 42 insertions, 30 deletions
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 8a06268c..dedb53e7 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -139,7 +139,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
)
{
solAssert(_padToWordBoundaries, "Non-padded store for function not implemented.");
- combineExternalFunctionType();
+ combineExternalFunctionType(true);
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
}
@@ -315,19 +315,29 @@ void CompilerUtils::memoryCopy()
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)
+ 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 << (u256(1) << 160) << Instruction::SWAP1 << Instruction::DIV;
- m_context << u256(0xffffffffUL) << Instruction::AND;
+ if (!_leftAligned)
+ 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;
- m_context << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::OR;
+ if (_leftAligned)
+ 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)
@@ -856,27 +866,29 @@ void CompilerUtils::storeStringData(bytesConstRef _data)
unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _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)
+ {
m_context << Instruction::POP << u256(0);
- else
+ return numBytes;
+ }
+ solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
+ m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD);
+ if (isExternalFunctionType)
+ splitExternalFunctionType(true);
+ else if (numBytes != 32)
{
- solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
- m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD);
- if (numBytes != 32)
- {
- // add leading or trailing zeros by dividing/multiplying depending on alignment
- u256 shiftFactor = u256(1) << ((32 - numBytes) * 8);
- m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV;
- if (leftAligned)
- m_context << shiftFactor << Instruction::MUL;
- }
+ bool leftAligned = _type.category() == Type::Category::FixedBytes;
+ // add leading or trailing zeros by dividing/multiplying depending on alignment
+ u256 shiftFactor = u256(1) << ((32 - numBytes) * 8);
+ m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV;
+ if (leftAligned)
+ m_context << shiftFactor << Instruction::MUL;
}
- if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
- if (funType->location() == FunctionType::Location::External)
- splitExternalFunctionType();
-
return numBytes;
}
diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h
index 0c9adf29..690452f9 100644
--- a/libsolidity/codegen/CompilerUtils.h
+++ b/libsolidity/codegen/CompilerUtils.h
@@ -114,12 +114,12 @@ public:
/// Stack post:
void memoryCopy();
- /// Converts the combined and right-aligned external function type
- /// <function identifier><address> into two stack slots:
+ /// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true)
+ /// external function type <function identifier><address> into two stack slots:
/// address (right aligned), function identifier (right aligned)
- void splitExternalFunctionType();
- /// Performs the opposite operation of splitExternalFunctionType()
- void combineExternalFunctionType();
+ void splitExternalFunctionType(bool _rightAligned);
+ /// Performs the opposite operation of splitExternalFunctionType(_rightAligned)
+ void combineExternalFunctionType(bool _rightAligned);
/// 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
diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp
index 98ab6d41..cb7cbbe3 100644
--- a/libsolidity/codegen/LValue.cpp
+++ b/libsolidity/codegen/LValue.cpp
@@ -194,7 +194,7 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
m_dataType->category() == Type::Category::Function &&
dynamic_cast<FunctionType const&>(*m_dataType).location() == FunctionType::Location::External
)
- CompilerUtils(m_context).splitExternalFunctionType();
+ CompilerUtils(m_context).splitExternalFunctionType(false);
else
{
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
)
// Combine the two-item function type into a single stack slot.
- utils.combineExternalFunctionType();
+ utils.combineExternalFunctionType(false);
else if (m_dataType->category() == Type::Category::FixedBytes)
m_context
<< (u256(0x1) << (256 - 8 * dynamic_cast<FixedBytesType const&>(*m_dataType).numBytes()))