aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-09-29 01:22:23 +0800
committerchriseth <c@ethdev.com>2016-11-16 21:37:17 +0800
commitdd173f83e3a6a9046d1aa7e64cb171598a73b272 (patch)
tree7c5b47b6a4b15a151284d6503af27667993a782b /libsolidity/codegen
parentcc8583ec7d6fd86ca7e129475fde32b76d102e79 (diff)
downloaddexon-solidity-dd173f83e3a6a9046d1aa7e64cb171598a73b272.tar.gz
dexon-solidity-dd173f83e3a6a9046d1aa7e64cb171598a73b272.tar.zst
dexon-solidity-dd173f83e3a6a9046d1aa7e64cb171598a73b272.zip
Code generator for function types.
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp34
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp1
2 files changed, 34 insertions, 1 deletions
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 58d1caa9..38a7a23b 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -133,6 +133,17 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
m_context << u256(str->value().size());
m_context << Instruction::ADD;
}
+ else if (
+ _type.category() == Type::Category::Function &&
+ dynamic_cast<FunctionType const&>(_type).location() == FunctionType::Location::External
+ )
+ {
+ solAssert(_padToWordBoundaries, "Non-padded store for function not implemented.");
+ m_context << u256(0xffffffffUL) << Instruction::AND << (u256(1) << 160) << Instruction::MUL << Instruction::SWAP1;
+ m_context << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::OR;
+ m_context << Instruction::DUP2 << Instruction::MSTORE;
+ m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
+ }
else
{
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries);
@@ -206,7 +217,8 @@ void CompilerUtils::encodeToMemory(
else if (
_givenTypes[i]->dataStoredIn(DataLocation::Storage) ||
_givenTypes[i]->dataStoredIn(DataLocation::CallData) ||
- _givenTypes[i]->category() == Type::Category::StringLiteral
+ _givenTypes[i]->category() == Type::Category::StringLiteral ||
+ _givenTypes[i]->category() == Type::Category::Function
)
type = _givenTypes[i]; // delay conversion
else
@@ -678,6 +690,14 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
void CompilerUtils::pushZeroValue(Type const& _type)
{
+ if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
+ {
+ if (funType->location() == FunctionType::Location::Internal)
+ {
+ m_context << m_context.errorTag();
+ return;
+ }
+ }
auto const* referenceType = dynamic_cast<ReferenceType const*>(&_type);
if (!referenceType || referenceType->location() == DataLocation::Storage)
{
@@ -839,6 +859,18 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda
}
}
+ if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
+ {
+ if (funType->location() == FunctionType::Location::External)
+ {
+ // We have to split the right-aligned <function identifier><address> into two stack slots:
+ // address (right aligned), function identifier (right aligned)
+ 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;
+ }
+ }
+
return numBytes;
}
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 2aec3055..9cd893e8 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -293,6 +293,7 @@ void ContractCompiler::appendCalldataUnpacker(TypePointers const& _typeParameter
{
// stack: v1 v2 ... v(k-1) base_offset current_offset
TypePointer type = parameterType->decodingType();
+ solAssert(type, "No decoding type found.");
if (type->category() == Type::Category::Array)
{
auto const& arrayType = dynamic_cast<ArrayType const&>(*type);