libsolidity: Introducing TypeProvider API, for clear type system ownership.

This commit is contained in:
Christian Parpart
2019-04-16 18:26:45 +02:00
committed by chriseth
parent 862d798047
commit bf43eebea9
38 changed files with 1489 additions and 837 deletions
+35 -34
View File
@@ -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