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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user