mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into breaking
This commit is contained in:
@@ -34,6 +34,8 @@ using namespace std;
|
||||
namespace solidity::frontend
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Magic variables get negative ids for easy differentiation
|
||||
int magicVariableToID(std::string const& _name)
|
||||
{
|
||||
@@ -103,6 +105,8 @@ inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariable
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GlobalContext::GlobalContext(): m_magicVariables{constructMagicVariables()}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2179,7 +2179,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
for (size_t i = 0; i < paramArgMap.size(); ++i)
|
||||
{
|
||||
solAssert(!!paramArgMap[i], "unmapped parameter");
|
||||
if (!type(*paramArgMap[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
|
||||
BoolResult result = type(*paramArgMap[i])->isImplicitlyConvertibleTo(*parameterTypes[i]);
|
||||
if (!result)
|
||||
{
|
||||
auto [errorId, description] = [&]() -> tuple<ErrorId, string> {
|
||||
string msg =
|
||||
@@ -2189,6 +2190,8 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
" to " +
|
||||
parameterTypes[i]->toString() +
|
||||
" requested.";
|
||||
if (!result.message().empty())
|
||||
msg += " " + result.message();
|
||||
if (
|
||||
_functionType->kind() == FunctionType::Kind::BareCall ||
|
||||
_functionType->kind() == FunctionType::Kind::BareCallCode ||
|
||||
|
||||
@@ -2901,6 +2901,13 @@ BoolResult FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
|
||||
FunctionType const& convertTo = dynamic_cast<FunctionType const&>(_convertTo);
|
||||
|
||||
// These two checks are duplicated in equalExcludingStateMutability, but are added here for error reporting.
|
||||
if (convertTo.bound() != bound())
|
||||
return BoolResult::err("Bound functions can not be converted to non-bound functions.");
|
||||
|
||||
if (convertTo.kind() != kind())
|
||||
return BoolResult::err("Special functions can not be converted to function types.");
|
||||
|
||||
if (!equalExcludingStateMutability(convertTo))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -51,28 +51,12 @@ public:
|
||||
);
|
||||
/// @returns Entire assembly.
|
||||
evmasm::Assembly const& assembly() const { return m_context.assembly(); }
|
||||
/// @returns Runtime assembly.
|
||||
evmasm::Assembly const& runtimeAssembly() const { return m_context.assembly().sub(m_runtimeSub); }
|
||||
/// @returns Entire assembly as a shared pointer to non-const.
|
||||
std::shared_ptr<evmasm::Assembly> assemblyPtr() const { return m_context.assemblyPtr(); }
|
||||
/// @returns Runtime assembly.
|
||||
/// @returns Runtime assembly as a shared pointer.
|
||||
std::shared_ptr<evmasm::Assembly> runtimeAssemblyPtr() const;
|
||||
/// @returns The entire assembled object (with constructor).
|
||||
evmasm::LinkerObject assembledObject() const { return m_context.assembledObject(); }
|
||||
/// @returns Only the runtime object (without constructor).
|
||||
evmasm::LinkerObject runtimeObject() const { return m_context.assembledRuntimeObject(m_runtimeSub); }
|
||||
/// @arg _sourceCodes is the map of input files to source code strings
|
||||
std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
|
||||
{
|
||||
return m_context.assemblyString(_sourceCodes);
|
||||
}
|
||||
/// @arg _sourceCodes is the map of input files to source code strings
|
||||
Json::Value assemblyJSON(std::map<std::string, unsigned> const& _indices = std::map<std::string, unsigned>()) const
|
||||
{
|
||||
return m_context.assemblyJSON(_indices);
|
||||
}
|
||||
/// @returns Assembly items of the normal compiler context
|
||||
evmasm::AssemblyItems const& assemblyItems() const { return m_context.assembly().items(); }
|
||||
/// @returns Assembly items of the runtime compiler context
|
||||
evmasm::AssemblyItems const& runtimeAssemblyItems() const { return m_context.assembly().sub(m_runtimeSub).items(); }
|
||||
|
||||
std::string generatedYulUtilityCode() const { return m_context.generatedYulUtilityCode(); }
|
||||
std::string runtimeGeneratedYulUtilityCode() const { return m_runtimeContext.generatedYulUtilityCode(); }
|
||||
|
||||
@@ -557,13 +557,6 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
|
||||
#endif
|
||||
}
|
||||
|
||||
LinkerObject const& CompilerContext::assembledObject() const
|
||||
{
|
||||
LinkerObject const& object = m_asm->assemble();
|
||||
solAssert(object.immutableReferences.empty(), "Leftover immutables.");
|
||||
return object;
|
||||
}
|
||||
|
||||
string CompilerContext::revertReasonIfDebug(string const& _message)
|
||||
{
|
||||
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);
|
||||
|
||||
@@ -291,21 +291,6 @@ public:
|
||||
/// Should be avoided except when adding sub-assemblies.
|
||||
std::shared_ptr<evmasm::Assembly> assemblyPtr() const { return m_asm; }
|
||||
|
||||
/// @arg _sourceCodes is the map of input files to source code strings
|
||||
std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
|
||||
{
|
||||
return m_asm->assemblyString(_sourceCodes);
|
||||
}
|
||||
|
||||
/// @arg _sourceCodes is the map of input files to source code strings
|
||||
Json::Value assemblyJSON(std::map<std::string, unsigned> const& _indicies = std::map<std::string, unsigned>()) const
|
||||
{
|
||||
return m_asm->assemblyJSON(_indicies);
|
||||
}
|
||||
|
||||
evmasm::LinkerObject const& assembledObject() const;
|
||||
evmasm::LinkerObject const& assembledRuntimeObject(size_t _subIndex) const { return m_asm->sub(_subIndex).assemble(); }
|
||||
|
||||
/**
|
||||
* Helper class to pop the visited nodes stack when a scope closes
|
||||
*/
|
||||
|
||||
@@ -1731,8 +1731,9 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy
|
||||
|
||||
let oldLen := <byteArrayLength>(sload(slot))
|
||||
|
||||
let srcOffset := 0
|
||||
<?fromMemory>
|
||||
src := add(src, 0x20)
|
||||
srcOffset := 0x20
|
||||
</fromMemory>
|
||||
|
||||
// This is not needed in all branches.
|
||||
@@ -1750,14 +1751,16 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy
|
||||
switch gt(newLen, 31)
|
||||
case 1 {
|
||||
let loopEnd := and(newLen, not(0x1f))
|
||||
<?fromStorage> src := <srcDataLocation>(src) </fromStorage>
|
||||
let dstPtr := dstDataArea
|
||||
let i := 0
|
||||
for { } lt(i, loopEnd) { i := add(i, 32) } {
|
||||
sstore(dstPtr, <read>(add(src, i)))
|
||||
for { } lt(i, loopEnd) { i := add(i, 0x20) } {
|
||||
sstore(dstPtr, <read>(add(src, srcOffset)))
|
||||
dstPtr := add(dstPtr, 1)
|
||||
srcOffset := add(srcOffset, <srcIncrement>)
|
||||
}
|
||||
if lt(loopEnd, newLen) {
|
||||
let lastValue := <read>(add(src, i))
|
||||
let lastValue := <read>(add(src, srcOffset))
|
||||
sstore(dstPtr, <maskBytes>(lastValue, and(newLen, 0x1f)))
|
||||
}
|
||||
sstore(slot, add(mul(newLen, 2), 1))
|
||||
@@ -1765,7 +1768,7 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy
|
||||
default {
|
||||
let value := 0
|
||||
if newLen {
|
||||
value := <read>(src)
|
||||
value := <read>(add(src, srcOffset))
|
||||
}
|
||||
sstore(slot, <byteArrayCombineShort>(value, newLen))
|
||||
}
|
||||
@@ -1781,7 +1784,10 @@ string YulUtilFunctions::copyByteArrayToStorageFunction(ArrayType const& _fromTy
|
||||
templ("panic", panicFunction(PanicCode::ResourceError));
|
||||
templ("byteArrayLength", extractByteArrayLengthFunction());
|
||||
templ("dstDataLocation", arrayDataAreaFunction(_toType));
|
||||
if (fromStorage)
|
||||
templ("srcDataLocation", arrayDataAreaFunction(_fromType));
|
||||
templ("clearStorageRange", clearStorageRangeFunction(*_toType.baseType()));
|
||||
templ("srcIncrement", to_string(fromStorage ? 1 : 0x20));
|
||||
templ("read", fromStorage ? "sload" : fromCalldata ? "calldataload" : "mload");
|
||||
templ("maskBytes", maskBytesFunctionDynamic());
|
||||
templ("byteArrayCombineShort", shortByteArrayEncodeUsedAreaSetLengthFunction());
|
||||
|
||||
@@ -356,27 +356,12 @@ void BMC::endVisit(UnaryOperation const& _op)
|
||||
)
|
||||
return;
|
||||
|
||||
switch (_op.getOperator())
|
||||
{
|
||||
case Token::Inc: // ++ (pre- or postfix)
|
||||
case Token::Dec: // -- (pre- or postfix)
|
||||
if (_op.getOperator() == Token::Sub && smt::isInteger(*_op.annotation().type))
|
||||
addVerificationTarget(
|
||||
VerificationTarget::Type::UnderOverflow,
|
||||
expr(_op),
|
||||
&_op
|
||||
);
|
||||
break;
|
||||
case Token::Sub: // -
|
||||
if (_op.annotation().type->category() == Type::Category::Integer)
|
||||
addVerificationTarget(
|
||||
VerificationTarget::Type::UnderOverflow,
|
||||
expr(_op),
|
||||
&_op
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BMC::endVisit(FunctionCall const& _funCall)
|
||||
|
||||
@@ -164,11 +164,11 @@ void CHC::endVisit(ContractDefinition const& _contract)
|
||||
if (base != &_contract)
|
||||
{
|
||||
m_callGraph[&_contract].insert(base);
|
||||
vector<ASTPointer<Expression>> const& args = baseArgs.count(base) ? baseArgs.at(base) : decltype(args){};
|
||||
|
||||
auto baseConstructor = base->constructor();
|
||||
if (baseConstructor && !args.empty())
|
||||
if (baseConstructor && baseArgs.count(base))
|
||||
{
|
||||
vector<ASTPointer<Expression>> const& args = baseArgs.at(base);
|
||||
auto const& params = baseConstructor->parameters();
|
||||
solAssert(params.size() == args.size(), "");
|
||||
for (unsigned i = 0; i < params.size(); ++i)
|
||||
|
||||
@@ -512,7 +512,13 @@ void SMTEncoder::endVisit(UnaryOperation const& _op)
|
||||
auto decl = identifierToVariable(*identifier);
|
||||
solAssert(decl, "");
|
||||
auto innerValue = currentValue(*decl);
|
||||
auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1;
|
||||
auto newValue = arithmeticOperation(
|
||||
_op.getOperator() == Token::Inc ? Token::Add : Token::Sub,
|
||||
innerValue,
|
||||
smtutil::Expression(size_t(1)),
|
||||
_op.annotation().type,
|
||||
_op
|
||||
).first;
|
||||
defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
|
||||
assignment(*decl, newValue);
|
||||
}
|
||||
@@ -522,7 +528,13 @@ void SMTEncoder::endVisit(UnaryOperation const& _op)
|
||||
)
|
||||
{
|
||||
auto innerValue = expr(*subExpr);
|
||||
auto newValue = _op.getOperator() == Token::Inc ? innerValue + 1 : innerValue - 1;
|
||||
auto newValue = arithmeticOperation(
|
||||
_op.getOperator() == Token::Inc ? Token::Add : Token::Sub,
|
||||
innerValue,
|
||||
smtutil::Expression(size_t(1)),
|
||||
_op.annotation().type,
|
||||
_op
|
||||
).first;
|
||||
defineExpr(_op, _op.isPrefixOperation() ? newValue : innerValue);
|
||||
indexOrMemberAssignment(*subExpr, newValue);
|
||||
}
|
||||
|
||||
@@ -399,4 +399,4 @@ smtutil::Expression SymbolicStructVariable::assignAllMembers(vector<smtutil::Exp
|
||||
m_context.addAssertion(_memberValues[i] == member(structMembers[i]->name()));
|
||||
|
||||
return currentValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,7 +627,7 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(string const& _contrac
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
|
||||
|
||||
Contract const& currentContract = contract(_contractName);
|
||||
return currentContract.compiler ? &contract(_contractName).compiler->assemblyItems() : nullptr;
|
||||
return currentContract.evmAssembly ? ¤tContract.evmAssembly->items() : nullptr;
|
||||
}
|
||||
|
||||
evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _contractName) const
|
||||
@@ -636,7 +636,7 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
|
||||
|
||||
Contract const& currentContract = contract(_contractName);
|
||||
return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssemblyItems() : nullptr;
|
||||
return currentContract.evmRuntimeAssembly ? ¤tContract.evmRuntimeAssembly->items() : nullptr;
|
||||
}
|
||||
|
||||
Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const
|
||||
@@ -790,8 +790,8 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap _sou
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
|
||||
|
||||
Contract const& currentContract = contract(_contractName);
|
||||
if (currentContract.compiler)
|
||||
return currentContract.compiler->assemblyString(_sourceCodes);
|
||||
if (currentContract.evmAssembly)
|
||||
return currentContract.evmAssembly->assemblyString(_sourceCodes);
|
||||
else
|
||||
return string();
|
||||
}
|
||||
@@ -803,8 +803,8 @@ Json::Value CompilerStack::assemblyJSON(string const& _contractName) const
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
|
||||
|
||||
Contract const& currentContract = contract(_contractName);
|
||||
if (currentContract.compiler)
|
||||
return currentContract.compiler->assemblyJSON(sourceIndices());
|
||||
if (currentContract.evmAssembly)
|
||||
return currentContract.evmAssembly->assemblyJSON(sourceIndices());
|
||||
else
|
||||
return Json::Value();
|
||||
}
|
||||
@@ -977,7 +977,7 @@ size_t CompilerStack::functionEntryPoint(
|
||||
evmasm::AssemblyItem tag = compiler->functionEntryLabel(_function);
|
||||
if (tag.type() == evmasm::UndefinedItem)
|
||||
return 0;
|
||||
evmasm::AssemblyItems const& items = compiler->runtimeAssemblyItems();
|
||||
evmasm::AssemblyItems const& items = compiler->runtimeAssembly().items();
|
||||
for (size_t i = 0; i < items.size(); ++i)
|
||||
if (items.at(i).type() == evmasm::Tag && items.at(i).data() == tag.data())
|
||||
return i;
|
||||
@@ -1200,20 +1200,25 @@ void CompilerStack::compileContract(
|
||||
solAssert(false, "Optimizer exception during compilation");
|
||||
}
|
||||
|
||||
compiledContract.evmAssembly = compiler->assemblyPtr();
|
||||
solAssert(compiledContract.evmAssembly, "");
|
||||
try
|
||||
{
|
||||
// Assemble deployment (incl. runtime) object.
|
||||
compiledContract.object = compiler->assembledObject();
|
||||
compiledContract.object = compiledContract.evmAssembly->assemble();
|
||||
}
|
||||
catch(evmasm::AssemblyException const&)
|
||||
{
|
||||
solAssert(false, "Assembly exception for bytecode");
|
||||
}
|
||||
solAssert(compiledContract.object.immutableReferences.empty(), "Leftover immutables.");
|
||||
|
||||
compiledContract.evmRuntimeAssembly = compiler->runtimeAssemblyPtr();
|
||||
solAssert(compiledContract.evmRuntimeAssembly, "");
|
||||
try
|
||||
{
|
||||
// Assemble runtime object.
|
||||
compiledContract.runtimeObject = compiler->runtimeObject();
|
||||
compiledContract.runtimeObject = compiledContract.evmRuntimeAssembly->assemble();
|
||||
}
|
||||
catch(evmasm::AssemblyException const&)
|
||||
{
|
||||
|
||||
@@ -358,6 +358,8 @@ private:
|
||||
{
|
||||
ContractDefinition const* contract = nullptr;
|
||||
std::shared_ptr<Compiler> compiler;
|
||||
std::shared_ptr<evmasm::Assembly> evmAssembly;
|
||||
std::shared_ptr<evmasm::Assembly> evmRuntimeAssembly;
|
||||
evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object).
|
||||
evmasm::LinkerObject runtimeObject; ///< Runtime object.
|
||||
std::string yulIR; ///< Experimental Yul IR code.
|
||||
|
||||
Reference in New Issue
Block a user