mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
libsolidity: Introducing TypeProvider API, for clear type system ownership.
This commit is contained in:
committed by
chriseth
parent
862d798047
commit
bf43eebea9
@@ -311,7 +311,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
case DataLocation::CallData:
|
||||
if (
|
||||
fromArray.isByteArray() ||
|
||||
*fromArray.baseType() == IntegerType::uint256() ||
|
||||
*fromArray.baseType() == *TypeProvider::integerType() ||
|
||||
*fromArray.baseType() == FixedBytesType(32)
|
||||
)
|
||||
return abiEncodingFunctionCalldataArrayWithoutCleanup(fromArray, *toArray, _options);
|
||||
@@ -369,7 +369,7 @@ string ABIFunctions::abiEncodingFunction(
|
||||
// possible for library calls where we just forward the storage reference
|
||||
solAssert(_options.encodeAsLibraryTypes, "");
|
||||
solAssert(_options.padded && !_options.dynamicInplace, "Non-padded / inplace encoding for library call requested.");
|
||||
solAssert(to == IntegerType::uint256(), "");
|
||||
solAssert(to == *TypeProvider::integerType(), "");
|
||||
templ("cleanupConvert", "value");
|
||||
}
|
||||
else
|
||||
@@ -445,7 +445,7 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup(
|
||||
solAssert(fromArrayType.location() == DataLocation::CallData, "");
|
||||
solAssert(
|
||||
fromArrayType.isByteArray() ||
|
||||
*fromArrayType.baseType() == IntegerType::uint256() ||
|
||||
*fromArrayType.baseType() == *TypeProvider::integerType() ||
|
||||
*fromArrayType.baseType() == FixedBytesType(32),
|
||||
"");
|
||||
solAssert(fromArrayType.calldataStride() == toArrayType.memoryStride(), "");
|
||||
@@ -1077,7 +1077,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo
|
||||
TypePointer decodingType = _type.decodingType();
|
||||
solAssert(decodingType, "");
|
||||
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(decodingType.get()))
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(decodingType))
|
||||
{
|
||||
if (arrayType->dataStoredIn(DataLocation::CallData))
|
||||
{
|
||||
@@ -1089,7 +1089,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo
|
||||
else
|
||||
return abiDecodingFunctionArray(*arrayType, _fromMemory);
|
||||
}
|
||||
else if (auto const* structType = dynamic_cast<StructType const*>(decodingType.get()))
|
||||
else if (auto const* structType = dynamic_cast<StructType const*>(decodingType))
|
||||
{
|
||||
if (structType->dataStoredIn(DataLocation::CallData))
|
||||
{
|
||||
@@ -1099,7 +1099,7 @@ string ABIFunctions::abiDecodingFunction(Type const& _type, bool _fromMemory, bo
|
||||
else
|
||||
return abiDecodingFunctionStruct(*structType, _fromMemory);
|
||||
}
|
||||
else if (auto const* functionType = dynamic_cast<FunctionType const*>(decodingType.get()))
|
||||
else if (auto const* functionType = dynamic_cast<FunctionType const*>(decodingType))
|
||||
return abiDecodingFunctionFunctionType(*functionType, _fromMemory, _forUseOnStack);
|
||||
else
|
||||
return abiDecodingFunctionValueType(_type, _fromMemory);
|
||||
|
||||
@@ -41,7 +41,7 @@ class Type;
|
||||
class ArrayType;
|
||||
class StructType;
|
||||
class FunctionType;
|
||||
using TypePointer = std::shared_ptr<Type const>;
|
||||
using TypePointer = Type const*;
|
||||
using TypePointers = std::vector<TypePointer>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <libsolidity/codegen/ArrayUtils.h>
|
||||
|
||||
#include <libsolidity/ast/Types.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/codegen/CompilerContext.h>
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/codegen/LValue.h>
|
||||
@@ -44,7 +45,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
// stack layout: [source_ref] [source length] target_ref (top)
|
||||
solAssert(_targetType.location() == DataLocation::Storage, "");
|
||||
|
||||
TypePointer uint256 = make_shared<IntegerType>(256);
|
||||
TypePointer uint256 = TypeProvider::integerType(256);
|
||||
TypePointer targetBaseType = _targetType.isByteArray() ? uint256 : _targetType.baseType();
|
||||
TypePointer sourceBaseType = _sourceType.isByteArray() ? uint256 : _sourceType.baseType();
|
||||
|
||||
@@ -74,8 +75,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
}
|
||||
|
||||
// stack: target_ref source_ref source_length
|
||||
TypePointer targetType = _targetType.shared_from_this();
|
||||
TypePointer sourceType = _sourceType.shared_from_this();
|
||||
TypePointer targetType = &_targetType;
|
||||
TypePointer sourceType = &_sourceType;
|
||||
m_context.callLowLevelFunction(
|
||||
"$copyArrayToStorage_" + sourceType->identifier() + "_to_" + targetType->identifier(),
|
||||
3,
|
||||
@@ -336,7 +337,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
m_context << Instruction::DUP3 << Instruction::DUP5;
|
||||
accessIndex(_sourceType, false);
|
||||
MemoryItem(m_context, *_sourceType.baseType(), true).retrieveValue(SourceLocation(), true);
|
||||
if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType().get()))
|
||||
if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType()))
|
||||
copyArrayToMemory(*baseArray, _padToWordBoundaries);
|
||||
else
|
||||
utils.storeInMemoryDynamic(*_sourceType.baseType());
|
||||
@@ -493,7 +494,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
else
|
||||
m_context << Instruction::DUP2 << u256(0);
|
||||
StorageItem(m_context, *_sourceType.baseType()).retrieveValue(SourceLocation(), true);
|
||||
if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType().get()))
|
||||
if (auto baseArray = dynamic_cast<ArrayType const*>(_sourceType.baseType()))
|
||||
copyArrayToMemory(*baseArray, _padToWordBoundaries);
|
||||
else
|
||||
utils.storeInMemoryDynamic(*_sourceType.baseType());
|
||||
@@ -530,7 +531,7 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
|
||||
|
||||
void ArrayUtils::clearArray(ArrayType const& _typeIn) const
|
||||
{
|
||||
TypePointer type = _typeIn.shared_from_this();
|
||||
TypePointer type = &_typeIn;
|
||||
m_context.callLowLevelFunction(
|
||||
"$clearArray_" + _typeIn.identifier(),
|
||||
2,
|
||||
@@ -584,7 +585,7 @@ void ArrayUtils::clearArray(ArrayType const& _typeIn) const
|
||||
ArrayUtils(_context).convertLengthToSize(_type);
|
||||
_context << Instruction::ADD << Instruction::SWAP1;
|
||||
if (_type.baseType()->storageBytes() < 32)
|
||||
ArrayUtils(_context).clearStorageLoop(make_shared<IntegerType>(256));
|
||||
ArrayUtils(_context).clearStorageLoop(TypeProvider::integerType(256));
|
||||
else
|
||||
ArrayUtils(_context).clearStorageLoop(_type.baseType());
|
||||
_context << Instruction::POP;
|
||||
@@ -625,7 +626,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
|
||||
<< Instruction::SWAP1;
|
||||
// stack: data_pos_end data_pos
|
||||
if (_type.storageStride() < 32)
|
||||
clearStorageLoop(make_shared<IntegerType>(256));
|
||||
clearStorageLoop(TypeProvider::integerType(256));
|
||||
else
|
||||
clearStorageLoop(_type.baseType());
|
||||
// cleanup
|
||||
@@ -635,7 +636,7 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
|
||||
|
||||
void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
|
||||
{
|
||||
TypePointer type = _typeIn.shared_from_this();
|
||||
TypePointer type = &_typeIn;
|
||||
m_context.callLowLevelFunction(
|
||||
"$resizeDynamicArray_" + _typeIn.identifier(),
|
||||
2,
|
||||
@@ -732,7 +733,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
|
||||
ArrayUtils(_context).convertLengthToSize(_type);
|
||||
_context << Instruction::DUP2 << Instruction::ADD << Instruction::SWAP1;
|
||||
// stack: ref new_length current_length first_word data_location_end data_location
|
||||
ArrayUtils(_context).clearStorageLoop(make_shared<IntegerType>(256));
|
||||
ArrayUtils(_context).clearStorageLoop(TypeProvider::integerType(256));
|
||||
_context << Instruction::POP;
|
||||
// stack: ref new_length current_length first_word
|
||||
solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3");
|
||||
@@ -771,7 +772,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
|
||||
_context << Instruction::SWAP2 << Instruction::ADD;
|
||||
// stack: ref new_length delete_end delete_start
|
||||
if (_type.storageStride() < 32)
|
||||
ArrayUtils(_context).clearStorageLoop(make_shared<IntegerType>(256));
|
||||
ArrayUtils(_context).clearStorageLoop(TypeProvider::integerType(256));
|
||||
else
|
||||
ArrayUtils(_context).clearStorageLoop(_type.baseType());
|
||||
|
||||
@@ -911,7 +912,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayUtils::clearStorageLoop(TypePointer const& _type) const
|
||||
void ArrayUtils::clearStorageLoop(TypePointer _type) const
|
||||
{
|
||||
m_context.callLowLevelFunction(
|
||||
"$clearStorageLoop_" + _type->identifier(),
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace solidity
|
||||
class CompilerContext;
|
||||
class Type;
|
||||
class ArrayType;
|
||||
using TypePointer = std::shared_ptr<Type const>;
|
||||
using TypePointer = Type const*;
|
||||
|
||||
/**
|
||||
* Class that provides code generation for handling arrays.
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
/// Appends a loop that clears a sequence of storage slots of the given type (excluding end).
|
||||
/// Stack pre: end_ref start_ref
|
||||
/// Stack post: end_ref
|
||||
void clearStorageLoop(TypePointer const& _type) const;
|
||||
void clearStorageLoop(TypePointer _type) const;
|
||||
/// Converts length to size (number of storage slots or calldata/memory bytes).
|
||||
/// if @a _pad then add padding to multiples of 32 bytes for calldata/memory.
|
||||
/// Stack pre: length
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/codegen/ABIFunctions.h>
|
||||
#include <libsolidity/codegen/ArrayUtils.h>
|
||||
#include <libsolidity/codegen/LValue.h>
|
||||
@@ -83,13 +84,13 @@ void CompilerUtils::toSizeAfterFreeMemoryPointer()
|
||||
|
||||
void CompilerUtils::revertWithStringData(Type const& _argumentType)
|
||||
{
|
||||
solAssert(_argumentType.isImplicitlyConvertibleTo(*Type::fromElementaryTypeName("string memory")), "");
|
||||
solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory")), "");
|
||||
fetchFreeMemoryPointer();
|
||||
m_context << (u256(FixedHash<4>::Arith(FixedHash<4>(dev::keccak256("Error(string)")))) << (256 - 32));
|
||||
m_context << Instruction::DUP2 << Instruction::MSTORE;
|
||||
m_context << u256(4) << Instruction::ADD;
|
||||
// Stack: <string data> <mem pos of encoding start>
|
||||
abiEncode({_argumentType.shared_from_this()}, {make_shared<ArrayType>(DataLocation::Memory, true)});
|
||||
abiEncode({&_argumentType}, {TypeProvider::arrayType(DataLocation::Memory, true)});
|
||||
toSizeAfterFreeMemoryPointer();
|
||||
m_context << Instruction::REVERT;
|
||||
}
|
||||
@@ -185,7 +186,7 @@ void CompilerUtils::loadFromMemoryDynamic(
|
||||
|
||||
void CompilerUtils::storeInMemory(unsigned _offset)
|
||||
{
|
||||
unsigned numBytes = prepareMemoryStore(IntegerType::uint256(), true);
|
||||
unsigned numBytes = prepareMemoryStore(*TypeProvider::integerType(), true);
|
||||
if (numBytes > 0)
|
||||
m_context << u256(_offset) << Instruction::MSTORE;
|
||||
}
|
||||
@@ -199,7 +200,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
|
||||
ref->location() == DataLocation::Memory,
|
||||
"Only in-memory reference type can be stored."
|
||||
);
|
||||
storeInMemoryDynamic(IntegerType::uint256(), _padToWordBoundaries);
|
||||
storeInMemoryDynamic(*TypeProvider::integerType(), _padToWordBoundaries);
|
||||
}
|
||||
else if (auto str = dynamic_cast<StringLiteralType const*>(&_type))
|
||||
{
|
||||
@@ -311,11 +312,11 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
else
|
||||
{
|
||||
// first load from calldata and potentially convert to memory if arrayType is memory
|
||||
TypePointer calldataType = arrayType.copyForLocation(DataLocation::CallData, false);
|
||||
TypePointer calldataType = TypeProvider::withLocation(&arrayType, DataLocation::CallData, false);
|
||||
if (calldataType->isDynamicallySized())
|
||||
{
|
||||
// put on stack: data_pointer length
|
||||
loadFromMemoryDynamic(IntegerType::uint256(), !_fromMemory);
|
||||
loadFromMemoryDynamic(*TypeProvider::integerType(), !_fromMemory);
|
||||
m_context << Instruction::SWAP1;
|
||||
// stack: input_end base_offset next_pointer data_offset
|
||||
m_context.appendInlineAssembly("{ if gt(data_offset, 0x100000000) { revert(0, 0) } }", {"data_offset"});
|
||||
@@ -326,7 +327,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem
|
||||
{"input_end", "base_offset", "next_ptr", "array_head_ptr"}
|
||||
);
|
||||
// retrieve length
|
||||
loadFromMemoryDynamic(IntegerType::uint256(), !_fromMemory, true);
|
||||
loadFromMemoryDynamic(*TypeProvider::integerType(), !_fromMemory, true);
|
||||
// stack: input_end base_offset next_pointer array_length data_pointer
|
||||
m_context << Instruction::SWAP2;
|
||||
// stack: input_end base_offset data_pointer array_length next_pointer
|
||||
@@ -454,7 +455,7 @@ void CompilerUtils::encodeToMemory(
|
||||
type = _givenTypes[i]; // delay conversion
|
||||
else
|
||||
convertType(*_givenTypes[i], *targetType, true);
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(type.get()))
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(type))
|
||||
ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries);
|
||||
else
|
||||
storeInMemoryDynamic(*type, _padToWordBoundaries);
|
||||
@@ -482,7 +483,7 @@ void CompilerUtils::encodeToMemory(
|
||||
{
|
||||
auto const& strType = dynamic_cast<StringLiteralType const&>(*_givenTypes[i]);
|
||||
m_context << u256(strType.value().size());
|
||||
storeInMemoryDynamic(IntegerType::uint256(), true);
|
||||
storeInMemoryDynamic(*TypeProvider::integerType(), true);
|
||||
// stack: ... <end_of_mem'>
|
||||
storeInMemoryDynamic(strType, _padToWordBoundaries);
|
||||
}
|
||||
@@ -497,7 +498,7 @@ void CompilerUtils::encodeToMemory(
|
||||
m_context << dupInstruction(1 + arrayType.sizeOnStack());
|
||||
ArrayUtils(m_context).retrieveLength(arrayType, 1);
|
||||
// stack: ... <end_of_mem> <value...> <end_of_mem'> <length>
|
||||
storeInMemoryDynamic(IntegerType::uint256(), true);
|
||||
storeInMemoryDynamic(*TypeProvider::integerType(), true);
|
||||
// stack: ... <end_of_mem> <value...> <end_of_mem''>
|
||||
// copy the new memory pointer
|
||||
m_context << swapInstruction(arrayType.sizeOnStack() + 1) << Instruction::POP;
|
||||
@@ -868,7 +869,7 @@ void CompilerUtils::convertType(
|
||||
allocateMemory(storageSize);
|
||||
// stack: mempos
|
||||
m_context << Instruction::DUP1 << u256(data.size());
|
||||
storeInMemoryDynamic(IntegerType::uint256());
|
||||
storeInMemoryDynamic(*TypeProvider::integerType());
|
||||
// stack: mempos datapos
|
||||
storeStringData(data);
|
||||
}
|
||||
@@ -917,7 +918,7 @@ void CompilerUtils::convertType(
|
||||
if (targetType.isDynamicallySized())
|
||||
{
|
||||
m_context << Instruction::DUP2;
|
||||
storeInMemoryDynamic(IntegerType::uint256());
|
||||
storeInMemoryDynamic(*TypeProvider::integerType());
|
||||
}
|
||||
// stack: <mem start> <source ref> (variably sized) <length> <mem data pos>
|
||||
if (targetType.baseType()->isValueType())
|
||||
@@ -988,10 +989,9 @@ void CompilerUtils::convertType(
|
||||
{
|
||||
case DataLocation::Storage:
|
||||
{
|
||||
auto conversionImpl = [
|
||||
typeOnStack = dynamic_pointer_cast<StructType const>(_typeOnStack.shared_from_this()),
|
||||
targetType = dynamic_pointer_cast<StructType const>(targetType.shared_from_this())
|
||||
](CompilerContext& _context) {
|
||||
auto conversionImpl =
|
||||
[typeOnStack = &typeOnStack, targetType = &targetType](CompilerContext& _context)
|
||||
{
|
||||
CompilerUtils utils(_context);
|
||||
// stack: <source ref>
|
||||
utils.allocateMemory(typeOnStack->memorySize());
|
||||
@@ -1029,7 +1029,7 @@ void CompilerUtils::convertType(
|
||||
m_context << Instruction::DUP1;
|
||||
m_context << Instruction::CALLDATASIZE;
|
||||
m_context << Instruction::SUB;
|
||||
abiDecode({targetType.shared_from_this()}, false);
|
||||
abiDecode({&targetType}, false);
|
||||
break;
|
||||
}
|
||||
case DataLocation::Memory:
|
||||
@@ -1162,7 +1162,7 @@ void CompilerUtils::pushZeroValue(Type const& _type)
|
||||
return;
|
||||
}
|
||||
|
||||
TypePointer type = _type.shared_from_this();
|
||||
TypePointer type = &_type;
|
||||
m_context.callLowLevelFunction(
|
||||
"$pushZeroValue_" + referenceType->identifier(),
|
||||
0,
|
||||
@@ -1172,13 +1172,13 @@ void CompilerUtils::pushZeroValue(Type const& _type)
|
||||
utils.allocateMemory(max(32u, type->calldataEncodedSize()));
|
||||
_context << Instruction::DUP1;
|
||||
|
||||
if (auto structType = dynamic_cast<StructType const*>(type.get()))
|
||||
if (auto structType = dynamic_cast<StructType const*>(type))
|
||||
for (auto const& member: structType->members(nullptr))
|
||||
{
|
||||
utils.pushZeroValue(*member.type);
|
||||
utils.storeInMemoryDynamic(*member.type);
|
||||
}
|
||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(type.get()))
|
||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(type))
|
||||
{
|
||||
solAssert(!arrayType->isDynamicallySized(), "");
|
||||
if (arrayType->length() > 0)
|
||||
@@ -1275,10 +1275,10 @@ void CompilerUtils::popAndJump(unsigned _toHeight, eth::AssemblyItem const& _jum
|
||||
m_context.adjustStackOffset(amount);
|
||||
}
|
||||
|
||||
unsigned CompilerUtils::sizeOnStack(vector<shared_ptr<Type const>> const& _variableTypes)
|
||||
unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (shared_ptr<Type const> const& type: _variableTypes)
|
||||
for (Type const* const& type: _variableTypes)
|
||||
size += type->sizeOnStack();
|
||||
return size;
|
||||
}
|
||||
@@ -1321,7 +1321,7 @@ void CompilerUtils::storeStringData(bytesConstRef _data)
|
||||
for (unsigned i = 0; i < _data.size(); i += 32)
|
||||
{
|
||||
m_context << h256::Arith(h256(_data.cropped(i), h256::AlignLeft));
|
||||
storeInMemoryDynamic(IntegerType::uint256());
|
||||
storeInMemoryDynamic(*TypeProvider::integerType());
|
||||
}
|
||||
m_context << Instruction::POP;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/ast/ASTForward.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/codegen/CompilerContext.h>
|
||||
#include <libsolidity/codegen/CompilerContext.h>
|
||||
|
||||
namespace dev {
|
||||
@@ -80,7 +82,7 @@ public:
|
||||
/// @returns the number of bytes consumed in memory.
|
||||
unsigned loadFromMemory(
|
||||
unsigned _offset,
|
||||
Type const& _type = IntegerType::uint256(),
|
||||
Type const& _type = *TypeProvider::integerType(),
|
||||
bool _fromCalldata = false,
|
||||
bool _padToWords = false
|
||||
);
|
||||
@@ -264,7 +266,7 @@ public:
|
||||
|
||||
template <class T>
|
||||
static unsigned sizeOnStack(std::vector<T> const& _variables);
|
||||
static unsigned sizeOnStack(std::vector<std::shared_ptr<Type const>> const& _variableTypes);
|
||||
static unsigned sizeOnStack(std::vector<Type const*> const& _variableTypes);
|
||||
|
||||
/// Helper function to shift top value on the stack to the left.
|
||||
/// Stack pre: <value> <shift_by_bits>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/codegen/ContractCompiler.h>
|
||||
#include <libsolidity/codegen/ExpressionCompiler.h>
|
||||
@@ -871,7 +872,7 @@ bool ContractCompiler::visit(Return const& _return)
|
||||
|
||||
TypePointer expectedType;
|
||||
if (expression->annotation().type->category() == Type::Category::Tuple || types.size() != 1)
|
||||
expectedType = make_shared<TupleType>(types);
|
||||
expectedType = TypeProvider::tupleType(move(types));
|
||||
else
|
||||
expectedType = types.front();
|
||||
compileExpression(*expression, expectedType);
|
||||
@@ -915,7 +916,7 @@ bool ContractCompiler::visit(VariableDeclarationStatement const& _variableDeclar
|
||||
CompilerUtils utils(m_context);
|
||||
compileExpression(*expression);
|
||||
TypePointers valueTypes;
|
||||
if (auto tupleType = dynamic_cast<TupleType const*>(expression->annotation().type.get()))
|
||||
if (auto tupleType = dynamic_cast<TupleType const*>(expression->annotation().type))
|
||||
valueTypes = tupleType->components();
|
||||
else
|
||||
valueTypes = TypePointers{expression->annotation().type};
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <libsolidity/codegen/ExpressionCompiler.h>
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libsolidity/codegen/CompilerContext.h>
|
||||
#include <libsolidity/codegen/CompilerUtils.h>
|
||||
#include <libsolidity/codegen/LValue.h>
|
||||
@@ -102,7 +103,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
|
||||
for (size_t i = 0; i < paramTypes.size(); ++i)
|
||||
{
|
||||
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
|
||||
if (auto mappingType = dynamic_cast<MappingType const*>(returnType))
|
||||
{
|
||||
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
|
||||
|
||||
@@ -152,7 +153,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
m_context << u256(0);
|
||||
returnType = mappingType->valueType();
|
||||
}
|
||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType.get()))
|
||||
else if (auto arrayType = dynamic_cast<ArrayType const*>(returnType))
|
||||
{
|
||||
// pop offset
|
||||
m_context << Instruction::POP;
|
||||
@@ -176,7 +177,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
unsigned retSizeOnStack = 0;
|
||||
auto returnTypes = accessorType.returnParameterTypes();
|
||||
solAssert(returnTypes.size() >= 1, "");
|
||||
if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get()))
|
||||
if (StructType const* structType = dynamic_cast<StructType const*>(returnType))
|
||||
{
|
||||
// remove offset
|
||||
m_context << Instruction::POP;
|
||||
@@ -186,7 +187,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
|
||||
{
|
||||
if (returnTypes[i]->category() == Type::Category::Mapping)
|
||||
continue;
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i].get()))
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(returnTypes[i]))
|
||||
if (!arrayType->isByteArray())
|
||||
continue;
|
||||
pair<u256, unsigned> const& offsets = structType->storageOffsetsOfMember(names[i]);
|
||||
@@ -496,7 +497,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
functionType = structType.constructorType();
|
||||
}
|
||||
else
|
||||
functionType = dynamic_pointer_cast<FunctionType const>(_functionCall.expression().annotation().type);
|
||||
functionType = dynamic_cast<FunctionType const*>(_functionCall.expression().annotation().type);
|
||||
|
||||
TypePointers parameterTypes = functionType->parameterTypes();
|
||||
vector<ASTPointer<Expression const>> const& callArguments = _functionCall.arguments();
|
||||
@@ -647,7 +648,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
_functionCall.expression().accept(*this);
|
||||
|
||||
arguments.front()->accept(*this);
|
||||
utils().convertType(*arguments.front()->annotation().type, IntegerType::uint256(), true);
|
||||
utils().convertType(*arguments.front()->annotation().type, *TypeProvider::integerType(), true);
|
||||
// Note that function is not the original function, but the ".gas" function.
|
||||
// Its values of gasSet and valueSet is equal to the original function's though.
|
||||
unsigned stackDepth = (function.gasSet() ? 1 : 0) + (function.valueSet() ? 1 : 0);
|
||||
@@ -731,9 +732,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
arguments.front()->accept(*this);
|
||||
// Optimization: If type is bytes or string, then do not encode,
|
||||
// but directly compute keccak256 on memory.
|
||||
if (*argType == ArrayType::bytesMemory() || *argType == ArrayType::stringMemory())
|
||||
if (*argType == *TypeProvider::bytesMemoryType() || *argType == *TypeProvider::stringMemoryType())
|
||||
{
|
||||
ArrayUtils(m_context).retrieveLength(ArrayType::bytesMemory());
|
||||
ArrayUtils(m_context).retrieveLength(*TypeProvider::bytesMemoryType());
|
||||
m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD;
|
||||
}
|
||||
else
|
||||
@@ -780,7 +781,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
++numIndexed;
|
||||
arguments[arg - 1]->accept(*this);
|
||||
if (auto const& referenceType = dynamic_pointer_cast<ReferenceType const>(paramTypes[arg - 1]))
|
||||
if (auto const& referenceType = dynamic_cast<ReferenceType const*>(paramTypes[arg - 1]))
|
||||
{
|
||||
utils().fetchFreeMemoryPointer();
|
||||
utils().packedEncode(
|
||||
@@ -835,13 +836,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::MulMod:
|
||||
{
|
||||
arguments[2]->accept(*this);
|
||||
utils().convertType(*arguments[2]->annotation().type, IntegerType::uint256());
|
||||
utils().convertType(*arguments[2]->annotation().type, *TypeProvider::integerType());
|
||||
m_context << Instruction::DUP1 << Instruction::ISZERO;
|
||||
m_context.appendConditionalInvalid();
|
||||
for (unsigned i = 1; i < 3; i ++)
|
||||
{
|
||||
arguments[2 - i]->accept(*this);
|
||||
utils().convertType(*arguments[2 - i]->annotation().type, IntegerType::uint256());
|
||||
utils().convertType(*arguments[2 - i]->annotation().type, *TypeProvider::integerType());
|
||||
}
|
||||
if (function.kind() == FunctionType::Kind::AddMod)
|
||||
m_context << Instruction::ADDMOD;
|
||||
@@ -872,10 +873,10 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
solAssert(function.parameterTypes().size() == 1, "");
|
||||
solAssert(!!function.parameterTypes()[0], "");
|
||||
TypePointer paramType = function.parameterTypes()[0];
|
||||
shared_ptr<ArrayType> arrayType =
|
||||
ArrayType const* arrayType =
|
||||
function.kind() == FunctionType::Kind::ArrayPush ?
|
||||
make_shared<ArrayType>(DataLocation::Storage, paramType) :
|
||||
make_shared<ArrayType>(DataLocation::Storage);
|
||||
TypeProvider::arrayType(DataLocation::Storage, paramType) :
|
||||
TypeProvider::arrayType(DataLocation::Storage);
|
||||
|
||||
// stack: ArrayReference
|
||||
arguments[0]->accept(*this);
|
||||
@@ -927,7 +928,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
|
||||
// Fetch requested length.
|
||||
arguments[0]->accept(*this);
|
||||
utils().convertType(*arguments[0]->annotation().type, IntegerType::uint256());
|
||||
utils().convertType(*arguments[0]->annotation().type, *TypeProvider::integerType());
|
||||
|
||||
// Stack: requested_length
|
||||
utils().fetchFreeMemoryPointer();
|
||||
@@ -1057,11 +1058,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
if (function.kind() == FunctionType::Kind::ABIEncodeWithSignature)
|
||||
{
|
||||
// hash the signature
|
||||
if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType.get()))
|
||||
if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType))
|
||||
{
|
||||
FixedHash<4> hash(dev::keccak256(stringType->value()));
|
||||
m_context << (u256(FixedHash<4>::Arith(hash)) << (256 - 32));
|
||||
dataOnStack = make_shared<FixedBytesType>(4);
|
||||
dataOnStack = TypeProvider::fixedBytesType(4);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1072,7 +1073,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
m_context << Instruction::KECCAK256;
|
||||
// stack: <memory pointer> <hash>
|
||||
|
||||
dataOnStack = make_shared<FixedBytesType>(32);
|
||||
dataOnStack = TypeProvider::fixedBytesType(32);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1103,7 +1104,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
arguments.front()->accept(*this);
|
||||
TypePointer firstArgType = arguments.front()->annotation().type;
|
||||
TypePointers targetTypes;
|
||||
if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type.get()))
|
||||
if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type))
|
||||
targetTypes = targetTupleType->components();
|
||||
else
|
||||
targetTypes = TypePointers{_functionCall.annotation().type};
|
||||
@@ -1114,7 +1115,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
utils().abiDecode(targetTypes, false);
|
||||
else
|
||||
{
|
||||
utils().convertType(*firstArgType, ArrayType::bytesMemory());
|
||||
utils().convertType(*firstArgType, *TypeProvider::bytesMemoryType());
|
||||
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
|
||||
m_context << Instruction::SWAP1 << Instruction::MLOAD;
|
||||
// stack now: <mem_pos> <length>
|
||||
@@ -1145,7 +1146,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
CompilerContext::LocationSetter locationSetter(m_context, _memberAccess);
|
||||
// Check whether the member is a bound function.
|
||||
ASTString const& member = _memberAccess.memberName();
|
||||
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get()))
|
||||
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
|
||||
if (funType->bound())
|
||||
{
|
||||
_memberAccess.expression().accept(*this);
|
||||
@@ -1174,14 +1175,14 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
|
||||
// Special processing for TypeType because we do not want to visit the library itself
|
||||
// for internal functions, or enum/struct definitions.
|
||||
if (TypeType const* type = dynamic_cast<TypeType const*>(_memberAccess.expression().annotation().type.get()))
|
||||
if (TypeType const* type = dynamic_cast<TypeType const*>(_memberAccess.expression().annotation().type))
|
||||
{
|
||||
if (dynamic_cast<ContractType const*>(type->actualType().get()))
|
||||
if (dynamic_cast<ContractType const*>(type->actualType()))
|
||||
{
|
||||
solAssert(_memberAccess.annotation().type, "_memberAccess has no type");
|
||||
if (auto variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
appendVariable(*variable, static_cast<Expression const&>(_memberAccess));
|
||||
else if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get()))
|
||||
else if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
|
||||
{
|
||||
switch (funType->kind())
|
||||
{
|
||||
@@ -1223,14 +1224,14 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
solAssert(false, "unsupported member function");
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type.get()))
|
||||
else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type))
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
else
|
||||
_memberAccess.expression().accept(*this);
|
||||
}
|
||||
else if (auto enumType = dynamic_cast<EnumType const*>(type->actualType().get()))
|
||||
else if (auto enumType = dynamic_cast<EnumType const*>(type->actualType()))
|
||||
{
|
||||
_memberAccess.expression().accept(*this);
|
||||
m_context << enumType->memberValue(_memberAccess.memberName());
|
||||
@@ -1288,7 +1289,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
identifier = FunctionType(*function).externalIdentifier();
|
||||
else
|
||||
solAssert(false, "Contract member is neither variable nor function.");
|
||||
utils().convertType(type, type.isPayable() ? AddressType::addressPayable() : AddressType::address(), true);
|
||||
utils().convertType(type, type.isPayable() ? *TypeProvider::payableAddressType() : *TypeProvider::addressType(), true);
|
||||
m_context << identifier;
|
||||
}
|
||||
else
|
||||
@@ -1306,7 +1307,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
utils().convertType(
|
||||
*_memberAccess.expression().annotation().type,
|
||||
AddressType::address(),
|
||||
*TypeProvider::addressType(),
|
||||
true
|
||||
);
|
||||
m_context << Instruction::BALANCE;
|
||||
@@ -1323,7 +1324,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
|
||||
utils().convertType(
|
||||
*_memberAccess.expression().annotation().type,
|
||||
AddressType::address(),
|
||||
*TypeProvider::addressType(),
|
||||
true
|
||||
);
|
||||
else
|
||||
@@ -1542,7 +1543,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
TypePointers{keyType}
|
||||
);
|
||||
m_context << Instruction::SWAP1;
|
||||
utils().storeInMemoryDynamic(IntegerType::uint256());
|
||||
utils().storeInMemoryDynamic(*TypeProvider::integerType());
|
||||
utils().toSizeAfterFreeMemoryPointer();
|
||||
}
|
||||
else
|
||||
@@ -1551,7 +1552,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
appendExpressionCopyToMemory(*keyType, *_indexAccess.indexExpression());
|
||||
m_context << Instruction::SWAP1;
|
||||
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
|
||||
utils().storeInMemoryDynamic(IntegerType::uint256());
|
||||
utils().storeInMemoryDynamic(*TypeProvider::integerType());
|
||||
m_context << u256(0);
|
||||
}
|
||||
m_context << Instruction::KECCAK256;
|
||||
@@ -1564,7 +1565,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
|
||||
|
||||
_indexAccess.indexExpression()->accept(*this);
|
||||
utils().convertType(*_indexAccess.indexExpression()->annotation().type, IntegerType::uint256(), true);
|
||||
utils().convertType(*_indexAccess.indexExpression()->annotation().type, *TypeProvider::integerType(), true);
|
||||
// stack layout: <base_ref> [<length>] <index>
|
||||
switch (arrayType.location())
|
||||
{
|
||||
@@ -1631,7 +1632,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
|
||||
|
||||
_indexAccess.indexExpression()->accept(*this);
|
||||
utils().convertType(*_indexAccess.indexExpression()->annotation().type, IntegerType::uint256(), true);
|
||||
utils().convertType(*_indexAccess.indexExpression()->annotation().type, *TypeProvider::integerType(), true);
|
||||
// stack layout: <value> <index>
|
||||
// check out-of-bounds access
|
||||
m_context << u256(fixedBytesType.numBytes());
|
||||
@@ -2211,7 +2212,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
||||
needToUpdateFreeMemoryPtr = true;
|
||||
else
|
||||
for (auto const& retType: returnTypes)
|
||||
if (dynamic_cast<ReferenceType const*>(retType.get()))
|
||||
if (dynamic_cast<ReferenceType const*>(retType))
|
||||
needToUpdateFreeMemoryPtr = true;
|
||||
|
||||
// Stack: return_data_start
|
||||
|
||||
@@ -35,7 +35,7 @@ using namespace langutil;
|
||||
|
||||
|
||||
StackVariable::StackVariable(CompilerContext& _compilerContext, VariableDeclaration const& _declaration):
|
||||
LValue(_compilerContext, _declaration.annotation().type.get()),
|
||||
LValue(_compilerContext, _declaration.annotation().type),
|
||||
m_baseStackOffset(m_context.baseStackOffsetOfVariable(_declaration)),
|
||||
m_size(m_dataType->sizeOnStack())
|
||||
{
|
||||
@@ -475,7 +475,7 @@ void StorageByteArrayElement::setToZero(SourceLocation const&, bool _removeRefer
|
||||
}
|
||||
|
||||
StorageArrayLength::StorageArrayLength(CompilerContext& _compilerContext, ArrayType const& _arrayType):
|
||||
LValue(_compilerContext, _arrayType.memberType("length").get()),
|
||||
LValue(_compilerContext, _arrayType.memberType("length")),
|
||||
m_arrayType(_arrayType)
|
||||
{
|
||||
solAssert(m_arrayType.isDynamicallySized(), "");
|
||||
|
||||
@@ -145,7 +145,7 @@ string YulUtilFunctions::leftAlignFunction(Type const& _type)
|
||||
templ("body", "aligned := value");
|
||||
break;
|
||||
case Type::Category::Contract:
|
||||
templ("body", "aligned := " + leftAlignFunction(AddressType::address()) + "(value)");
|
||||
templ("body", "aligned := " + leftAlignFunction(*TypeProvider::addressType()) + "(value)");
|
||||
break;
|
||||
case Type::Category::Enum:
|
||||
{
|
||||
|
||||
@@ -82,7 +82,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
|
||||
{
|
||||
solUnimplementedAssert(_binOp.getOperator() == Token::Add, "");
|
||||
solUnimplementedAssert(*_binOp.leftExpression().annotation().type == *_binOp.rightExpression().annotation().type, "");
|
||||
if (IntegerType const* type = dynamic_cast<IntegerType const*>(_binOp.annotation().commonType.get()))
|
||||
if (IntegerType const* type = dynamic_cast<IntegerType const*>(_binOp.annotation().commonType))
|
||||
{
|
||||
solUnimplementedAssert(!type->isSigned(), "");
|
||||
m_code <<
|
||||
@@ -103,7 +103,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binOp)
|
||||
bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
solUnimplementedAssert(_functionCall.annotation().kind == FunctionCallKind::FunctionCall, "");
|
||||
FunctionTypePointer functionType = dynamic_pointer_cast<FunctionType const>(_functionCall.expression().annotation().type);
|
||||
FunctionTypePointer functionType = dynamic_cast<FunctionType const*>(_functionCall.expression().annotation().type);
|
||||
|
||||
TypePointers parameterTypes = functionType->parameterTypes();
|
||||
vector<ASTPointer<Expression const>> const& callArguments = _functionCall.arguments();
|
||||
|
||||
Reference in New Issue
Block a user