diff --git a/Changelog.md b/Changelog.md index 95095b102..0259cb075 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: Bugfixes: + * Code Generator: Avoid including references to the deployed label of referenced functions if they are called right away. * ContractLevelChecker: Properly distinguish the case of missing base constructor arguments from having an unimplemented base function. * SMTChecker: Fix internal error when using the custom NatSpec annotation to abstract free functions. * TypeChecker: Also allow external library functions in ``using for``. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 2aa2315f9..c034024b4 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -632,29 +632,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) evmasm::AssemblyItem returnLabel = m_context.pushNewTag(); for (unsigned i = 0; i < arguments.size(); ++i) acceptAndConvert(*arguments[i], *function.parameterTypes()[i]); - - { - bool shortcutTaken = false; - if (auto identifier = dynamic_cast(&_functionCall.expression())) - { - solAssert(!function.hasBoundFirstArgument(), ""); - if (auto functionDef = dynamic_cast(identifier->annotation().referencedDeclaration)) - { - // Do not directly visit the identifier, because this way, we can avoid - // the runtime entry label to be created at the creation time context. - CompilerContext::LocationSetter locationSetter2(m_context, *identifier); - solAssert(*identifier->annotation().requiredLookup == VirtualLookup::Virtual, ""); - utils().pushCombinedFunctionEntryLabel( - functionDef->resolveVirtual(m_context.mostDerivedContract()), - false - ); - shortcutTaken = true; - } - } - - if (!shortcutTaken) - _functionCall.expression().accept(*this); - } + _functionCall.expression().accept(*this); unsigned parameterSize = CompilerUtils::sizeOnStack(function.parameterTypes()); if (function.hasBoundFirstArgument()) @@ -1486,7 +1464,11 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) { FunctionDefinition const& funDef = dynamic_cast(funType->declaration()); solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, ""); - utils().pushCombinedFunctionEntryLabel(funDef); + utils().pushCombinedFunctionEntryLabel( + funDef, + // If we call directly, do not include the second label. + !_memberAccess.annotation().calledDirectly + ); utils().moveIntoStack(funType->selfType()->sizeOnStack(), 1); } else if ( @@ -1519,10 +1501,14 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) _memberAccess.expression().accept(*this); solAssert(_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Super, ""); - utils().pushCombinedFunctionEntryLabel(m_context.superFunction( - dynamic_cast(*_memberAccess.annotation().referencedDeclaration), - contractType->contractDefinition() - )); + utils().pushCombinedFunctionEntryLabel( + m_context.superFunction( + dynamic_cast(*_memberAccess.annotation().referencedDeclaration), + contractType->contractDefinition() + ), + // If we call directly, do not include the second label. + !_memberAccess.annotation().calledDirectly + ); } else { @@ -1541,7 +1527,11 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) if (auto const* function = dynamic_cast(_memberAccess.annotation().referencedDeclaration)) { solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, ""); - utils().pushCombinedFunctionEntryLabel(*function); + utils().pushCombinedFunctionEntryLabel( + *function, + // If we call directly, do not include the second label. + !_memberAccess.annotation().calledDirectly + ); } else solAssert(false, "Function not found in member access"); @@ -2025,7 +2015,11 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) solAssert(function && function->isFree(), ""); solAssert(funType->kind() == FunctionType::Kind::Internal, ""); solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, ""); - utils().pushCombinedFunctionEntryLabel(*function); + utils().pushCombinedFunctionEntryLabel( + *function, + // If we call directly, do not include the second label. + !_memberAccess.annotation().calledDirectly + ); } else if (auto const* contract = dynamic_cast(_memberAccess.annotation().referencedDeclaration)) { @@ -2223,12 +2217,14 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) } else if (FunctionDefinition const* functionDef = dynamic_cast(declaration)) { - // If the identifier is called right away, this code is executed in visit(FunctionCall...), because - // we want to avoid having a reference to the runtime function entry point in the - // constructor context, since this would force the compiler to include unreferenced - // internal functions in the runtime context. solAssert(*_identifier.annotation().requiredLookup == VirtualLookup::Virtual, ""); - utils().pushCombinedFunctionEntryLabel(functionDef->resolveVirtual(m_context.mostDerivedContract())); + utils().pushCombinedFunctionEntryLabel( + functionDef->resolveVirtual(m_context.mostDerivedContract()), + // If we call directly, do not include the second (potential runtime) label. + // Including the label might lead to the runtime code being included in the creation + // code even though it is never executed. + !_identifier.annotation().calledDirectly + ); } else if (auto variable = dynamic_cast(declaration)) appendVariable(*variable, static_cast(_identifier)); diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol new file mode 100644 index 000000000..64b80422c --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/bound_function.sol @@ -0,0 +1,40 @@ +function longdata(S memory) pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol new file mode 100644 index 000000000..931109199 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function.sol @@ -0,0 +1,34 @@ +library L { + function longdata() pure internal returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/library_function_deployed.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function_deployed.sol new file mode 100644 index 000000000..30f403af7 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/library_function_deployed.sol @@ -0,0 +1,31 @@ +library L { + function longdata() pure internal returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol new file mode 100644 index 000000000..018d41055 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function.sol @@ -0,0 +1,36 @@ +==== Source: mod.sol ==== +function longdata() pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/module_function_deployed.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function_deployed.sol new file mode 100644 index 000000000..f29355e07 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/module_function_deployed.sol @@ -0,0 +1,32 @@ +==== Source: mod.sol ==== +function longdata() pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol new file mode 100644 index 000000000..0f9b023b0 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function.sol @@ -0,0 +1,35 @@ +abstract contract S { + function longdata() internal pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function_deployed.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function_deployed.sol new file mode 100644 index 000000000..a7c8d6cfe --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/static_base_function_deployed.sol @@ -0,0 +1,31 @@ +abstract contract S { + function longdata() internal pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol new file mode 100644 index 000000000..9accc54a2 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function.sol @@ -0,0 +1,35 @@ +abstract contract S { + function longdata() internal pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/super_function_deployed.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function_deployed.sol new file mode 100644 index 000000000..9588007b3 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/super_function_deployed.sol @@ -0,0 +1,31 @@ +abstract contract S { + function longdata() internal pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol new file mode 100644 index 000000000..866fe9dfc --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function.sol @@ -0,0 +1,39 @@ +abstract contract S { + function longdata() internal virtual pure returns (bytes memory); +} + +abstract contract X is S { + function longdata() internal override pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function_deployed.sol b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function_deployed.sol new file mode 100644 index 000000000..bcc95b9f4 --- /dev/null +++ b/test/libsolidity/semanticTests/deployedCodeExclusion/virtual_function_deployed.sol @@ -0,0 +1,35 @@ +abstract contract S { + function longdata() internal virtual pure returns (bytes memory); +} + +abstract contract X is S { + function longdata() internal override pure returns (bytes memory) { + return + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "xasopca.pngaibngidak.jbtnudak.cAP.BRRSMCPJAGPD KIAJDOMHUKR,SCPID" + "M,SEYBDXCNTKIMNJGO;DUIAQBQUEHAKMPGIDSAJCOUKANJBCUEBKNA.GIAKMV.TI" + "AJMO true diff --git a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol index 167521bff..64724983a 100644 --- a/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol +++ b/test/libsolidity/semanticTests/userDefinedValueType/erc20.sol @@ -114,8 +114,8 @@ contract ERC20 { // constructor() // ~ emit Transfer(address,address,uint256): #0x00, #0x1212121212121212121212121212120000000012, 0x14 // gas irOptimized: 362054 -// gas legacy: 852973 -// gas legacyOptimized: 419237 +// gas legacy: 852825 +// gas legacyOptimized: 418837 // totalSupply() -> 20 // gas irOptimized: 23415 // gas legacy: 23653