diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index ffced74c5..d964c1f14 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -205,12 +205,12 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) Whiskers templ(R"( function (headStart, dataEnd) { - if slt(sub(dataEnd, headStart), ) { } + if slt(sub(dataEnd, headStart), ) { () } } )"); templ("functionName", functionName); - templ("revertString", revertReasonIfDebug("ABI decoding: tuple data too short")); + templ("revertString", revertReasonIfDebugFunction("ABI decoding: tuple data too short")); templ("minimumSize", to_string(headSize(decodingTypes))); string decodeElements; @@ -235,7 +235,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) { let offset := (add(headStart, )) - if gt(offset, 0xffffffffffffffff) { } + if gt(offset, 0xffffffffffffffff) { () } let offset := @@ -244,7 +244,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) )"); elementTempl("dynamic", decodingTypes[i]->isDynamicallyEncoded()); // TODO add test - elementTempl("revertString", revertReasonIfDebug("ABI decoding: invalid tuple offset")); + elementTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid tuple offset")); elementTempl("load", _fromMemory ? "mload" : "calldataload"); elementTempl("values", boost::algorithm::join(valueNamesLocal, ", ")); elementTempl("pos", to_string(headPos)); @@ -487,12 +487,12 @@ string ABIFunctions::abiEncodingFunctionCalldataArrayWithoutCleanup( else templ("scaleLengthByStride", Whiskers(R"( - if gt(length, ) { } + if gt(length, ) { () } length := mul(length, ) )") ("stride", toCompactHexWithPrefix(fromArrayType.calldataStride())) ("maxLength", toCompactHexWithPrefix(u256(-1) / fromArrayType.calldataStride())) - ("revertString", revertReasonIfDebug("ABI encoding: array data too long")) + ("revertString", revertReasonIfDebugFunction("ABI encoding: array data too long")) .render() // TODO add revert test ); @@ -1148,14 +1148,14 @@ string ABIFunctions::abiDecodingFunctionArray(ArrayType const& _type, bool _from R"( // function (offset, end) -> array { - if iszero(slt(add(offset, 0x1f), end)) { } + if iszero(slt(add(offset, 0x1f), end)) { () } let length := array := (, length, end) } )" ); // TODO add test - templ("revertString", revertReasonIfDebug("ABI decoding: invalid calldata array offset")); + templ("revertString", revertReasonIfDebugFunction("ABI decoding: invalid calldata array offset")); templ("functionName", functionName); templ("readableTypeName", _type.toString(true)); templ("retrieveLength", _type.isDynamicallySized() ? (load + "(offset)") : toCompactHexWithPrefix(_type.length())); @@ -1188,13 +1188,13 @@ string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _t let src := offset if gt(add(src, mul(length, )), end) { - + () } for { let i := 0 } lt(i, length) { i := add(i, 1) } { let innerOffset := (src) - if gt(innerOffset, 0xffffffffffffffff) { } + if gt(innerOffset, 0xffffffffffffffff) { () } let elementPos := add(offset, innerOffset) let elementPos := src @@ -1215,9 +1215,9 @@ string ABIFunctions::abiDecodingFunctionArrayAvailableLength(ArrayType const& _t templ("dynamicBase", _type.baseType()->isDynamicallyEncoded()); templ( "revertInvalidStride", - revertReasonIfDebug("ABI decoding: invalid calldata array stride") + revertReasonIfDebugFunction("ABI decoding: invalid calldata array stride") ); - templ("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset")); + templ("revertStringOffset", revertReasonIfDebugFunction("ABI decoding: invalid calldata array offset")); templ("decodingFun", abiDecodingFunction(*_type.baseType(), _fromMemory, false)); return templ.render(); }); @@ -1241,15 +1241,15 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) w = Whiskers(R"( // function (offset, end) -> arrayPos, length { - if iszero(slt(add(offset, 0x1f), end)) { } + if iszero(slt(add(offset, 0x1f), end)) { () } length := calldataload(offset) - if gt(length, 0xffffffffffffffff) { } + if gt(length, 0xffffffffffffffff) { () } arrayPos := add(offset, 0x20) - if gt(add(arrayPos, mul(length, )), end) { } + if gt(add(arrayPos, mul(length, )), end) { () } } )"); - w("revertStringOffset", revertReasonIfDebug("ABI decoding: invalid calldata array offset")); - w("revertStringLength", revertReasonIfDebug("ABI decoding: invalid calldata array length")); + w("revertStringOffset", revertReasonIfDebugFunction("ABI decoding: invalid calldata array offset")); + w("revertStringLength", revertReasonIfDebugFunction("ABI decoding: invalid calldata array length")); } else { @@ -1257,12 +1257,12 @@ string ABIFunctions::abiDecodingFunctionCalldataArray(ArrayType const& _type) // function (offset, end) -> arrayPos { arrayPos := offset - if gt(add(arrayPos, mul(, )), end) { } + if gt(add(arrayPos, mul(, )), end) { () } } )"); w("length", toCompactHexWithPrefix(_type.length())); } - w("revertStringPos", revertReasonIfDebug("ABI decoding: invalid calldata array stride")); + w("revertStringPos", revertReasonIfDebugFunction("ABI decoding: invalid calldata array stride")); w("functionName", functionName); w("readableTypeName", _type.toString(true)); w("stride", toCompactHexWithPrefix(_type.calldataStride())); @@ -1288,11 +1288,11 @@ string ABIFunctions::abiDecodingFunctionByteArrayAvailableLength(ArrayType const array := ((length)) mstore(array, length) let dst := add(array, 0x20) - if gt(add(src, length), end) { } + if gt(add(src, length), end) { () } (src, dst, length) } )"); - templ("revertStringLength", revertReasonIfDebug("ABI decoding: invalid byte array length")); + templ("revertStringLength", revertReasonIfDebugFunction("ABI decoding: invalid byte array length")); templ("functionName", functionName); templ("allocate", m_utils.allocationFunction()); templ("allocationSize", m_utils.arrayAllocationSizeFunction(_type)); @@ -1312,12 +1312,12 @@ string ABIFunctions::abiDecodingFunctionCalldataStruct(StructType const& _type) Whiskers w{R"( // function (offset, end) -> value { - if slt(sub(end, offset), ) { } + if slt(sub(end, offset), ) { () } value := offset } )"}; // TODO add test - w("revertString", revertReasonIfDebug("ABI decoding: struct calldata too short")); + w("revertString", revertReasonIfDebugFunction("ABI decoding: struct calldata too short")); w("functionName", functionName); w("readableTypeName", _type.toString(true)); w("minimumSize", to_string(_type.isDynamicallyEncoded() ? _type.calldataEncodedTailSize() : _type.calldataEncodedSize(true))); @@ -1337,7 +1337,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr Whiskers templ(R"( // function (headStart, end) -> value { - if slt(sub(end, headStart), ) { } + if slt(sub(end, headStart), ) { () } value := () <#members> { @@ -1348,7 +1348,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr } )"); // TODO add test - templ("revertString", revertReasonIfDebug("ABI decoding: struct data too short")); + templ("revertString", revertReasonIfDebugFunction("ABI decoding: struct data too short")); templ("functionName", functionName); templ("readableTypeName", _type.toString(true)); templ("allocate", m_utils.allocationFunction()); @@ -1365,7 +1365,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr Whiskers memberTempl(R"( let offset := (add(headStart, )) - if gt(offset, 0xffffffffffffffff) { } + if gt(offset, 0xffffffffffffffff) { () } let offset := @@ -1373,7 +1373,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr )"); memberTempl("dynamic", decodingType->isDynamicallyEncoded()); // TODO add test - memberTempl("revertString", revertReasonIfDebug("ABI decoding: invalid struct offset")); + memberTempl("revertString", revertReasonIfDebugFunction("ABI decoding: invalid struct offset")); memberTempl("load", _fromMemory ? "mload" : "calldataload"); memberTempl("pos", to_string(headPos)); memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name))); @@ -1441,7 +1441,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type) Whiskers w(R"( function (base_ref, ptr) -> { let rel_offset_of_tail := calldataload(ptr) - if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(, 1)))) { } + if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(, 1)))) { () } value := add(rel_offset_of_tail, base_ref) } @@ -1453,14 +1453,14 @@ string ABIFunctions::calldataAccessFunction(Type const& _type) w("handleLength", Whiskers(R"( length := calldataload(value) value := add(value, 0x20) - if gt(length, 0xffffffffffffffff) { } - if sgt(base_ref, sub(calldatasize(), mul(length, ))) { } + if gt(length, 0xffffffffffffffff) { () } + if sgt(base_ref, sub(calldatasize(), mul(length, ))) { () } )") ("calldataStride", toCompactHexWithPrefix(arrayType->calldataStride())) // TODO add test - ("revertStringLength", revertReasonIfDebug("Invalid calldata access length")) + ("revertStringLength", revertReasonIfDebugFunction("Invalid calldata access length")) // TODO add test - ("revertStringStride", revertReasonIfDebug("Invalid calldata access stride")) + ("revertStringStride", revertReasonIfDebugFunction("Invalid calldata access stride")) .render()); w("return", "value, length"); } @@ -1471,7 +1471,7 @@ string ABIFunctions::calldataAccessFunction(Type const& _type) } w("neededLength", toCompactHexWithPrefix(tailSize)); w("functionName", functionName); - w("revertStringOffset", revertReasonIfDebug("Invalid calldata access offset")); + w("revertStringOffset", revertReasonIfDebugFunction("Invalid calldata access offset")); return w.render(); } else if (_type.isValueType()) @@ -1555,7 +1555,7 @@ size_t ABIFunctions::numVariablesForType(Type const& _type, EncodingOptions cons return _type.sizeOnStack(); } -std::string ABIFunctions::revertReasonIfDebug(std::string const& _message) +std::string ABIFunctions::revertReasonIfDebugFunction(std::string const& _message) { - return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); + return m_utils.revertReasonIfDebugFunction(_message); } diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index 8cd858ba0..07088aa3b 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -273,9 +273,9 @@ private: /// is true), for which it is two. static size_t numVariablesForType(Type const& _type, EncodingOptions const& _options); - /// @returns code that stores @param _message for revert reason + /// @returns the name of a function that uses @param _message for revert reason /// if m_revertStrings is debug. - std::string revertReasonIfDebug(std::string const& _message = ""); + std::string revertReasonIfDebugFunction(std::string const& _message = ""); langutil::EVMVersion m_evmVersion; RevertStrings const m_revertStrings; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index cddeea472..434d9056e 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -560,7 +560,11 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ string CompilerContext::revertReasonIfDebug(string const& _message) { - return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); + return YulUtilFunctions::revertReasonIfDebugBody( + m_revertStrings, + "mload(" + to_string(CompilerUtils::freeMemoryPointer) + ")", + _message + ); } void CompilerContext::updateSourceLocation() diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 1ec620271..bdf9abc7d 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -268,7 +268,7 @@ public: ); /// If m_revertStrings is debug, @returns inline assembly code that - /// stores @param _message in memory position 0 and reverts. + /// stores @param _message at the free memory pointer and reverts. /// Otherwise returns "revert(0, 0)". std::string revertReasonIfDebug(std::string const& _message = ""); diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 08dd6bc20..32848a091 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2220,16 +2220,16 @@ string YulUtilFunctions::calldataArrayIndexRangeAccess(ArrayType const& _type) return m_functionCollector.createFunction(functionName, [&]() { return Whiskers(R"( function (offset, length, startIndex, endIndex) -> offsetOut, lengthOut { - if gt(startIndex, endIndex) { } - if gt(endIndex, length) { } + if gt(startIndex, endIndex) { () } + if gt(endIndex, length) { () } offsetOut := add(offset, mul(startIndex, )) lengthOut := sub(endIndex, startIndex) } )") ("functionName", functionName) ("stride", to_string(_type.calldataStride())) - ("revertSliceStartAfterEnd", revertReasonIfDebug("Slice starts after end")) - ("revertSliceGreaterThanLength", revertReasonIfDebug("Slice is greater than length")) + ("revertSliceStartAfterEnd", revertReasonIfDebugFunction("Slice starts after end")) + ("revertSliceGreaterThanLength", revertReasonIfDebugFunction("Slice is greater than length")) .render(); }); } @@ -2243,13 +2243,13 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) return Whiskers(R"( function (base_ref, ptr_to_tail) -> addr, length { let rel_offset_of_tail := calldataload(ptr_to_tail) - if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(, 1)))) { } + if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(, 1)))) { () } addr := add(base_ref, rel_offset_of_tail) length := calldataload(addr) - if gt(length, 0xffffffffffffffff) { } + if gt(length, 0xffffffffffffffff) { () } addr := add(addr, 32) - if sgt(addr, sub(calldatasize(), mul(length, ))) { } + if sgt(addr, sub(calldatasize(), mul(length, ))) { () } } )") @@ -2257,9 +2257,9 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) ("dynamicallySized", _type.isDynamicallySized()) ("neededLength", toCompactHexWithPrefix(_type.calldataEncodedTailSize())) ("calldataStride", toCompactHexWithPrefix(_type.isDynamicallySized() ? dynamic_cast(_type).calldataStride() : 0)) - ("invalidCalldataTailOffset", revertReasonIfDebug("Invalid calldata tail offset")) - ("invalidCalldataTailLength", revertReasonIfDebug("Invalid calldata tail length")) - ("shortCalldataTail", revertReasonIfDebug("Calldata tail too short")) + ("invalidCalldataTailOffset", revertReasonIfDebugFunction("Invalid calldata tail offset")) + ("invalidCalldataTailLength", revertReasonIfDebugFunction("Invalid calldata tail length")) + ("shortCalldataTail", revertReasonIfDebugFunction("Calldata tail too short")) .render(); }); } @@ -4212,42 +4212,52 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC }); } -string YulUtilFunctions::revertReasonIfDebug(RevertStrings revertStrings, string const& _message) +string YulUtilFunctions::revertReasonIfDebugFunction(string const& _message) { - if (revertStrings >= RevertStrings::Debug && !_message.empty()) - { - Whiskers templ(R"({ - mstore(0, ) - mstore(4, 0x20) - mstore(add(4, 0x20), ) - let reasonPos := add(4, 0x40) - <#word> - mstore(add(reasonPos, ), ) - - revert(0, add(reasonPos, )) - })"); - templ("sig", util::selectorFromSignature("Error(string)").str()); - templ("length", to_string(_message.length())); - - size_t words = (_message.length() + 31) / 32; - vector> wordParams(words); - for (size_t i = 0; i < words; ++i) - { - wordParams[i]["offset"] = to_string(i * 32); - wordParams[i]["wordValue"] = formatAsStringOrNumber(_message.substr(32 * i, 32)); - } - templ("word", wordParams); - templ("end", to_string(words * 32)); - - return templ.render(); - } - else - return "revert(0, 0)"; + string functionName = "revert_error_" + util::toHex(util::keccak256(_message).asBytes()); + return m_functionCollector.createFunction(functionName, [&](auto&, auto&) -> string { + return revertReasonIfDebugBody(m_revertStrings, allocateUnboundedFunction() + "()", _message); + }); } -string YulUtilFunctions::revertReasonIfDebug(string const& _message) +string YulUtilFunctions::revertReasonIfDebugBody( + RevertStrings _revertStrings, + string const& _allocation, + string const& _message +) { - return revertReasonIfDebug(m_revertStrings, _message); + if (_revertStrings < RevertStrings::Debug || _message.empty()) + return "revert(0, 0)"; + + Whiskers templ(R"( + let start := + let pos := start + mstore(pos, ) + pos := add(pos, 4) + mstore(pos, 0x20) + pos := add(pos, 0x20) + mstore(pos, ) + pos := add(pos, 0x20) + <#word> + mstore(add(pos, ), ) + + revert(start, ) + )"); + templ("allocate", _allocation); + templ("sig", util::selectorFromSignature("Error(string)").str()); + templ("length", to_string(_message.length())); + + size_t words = (_message.length() + 31) / 32; + vector> wordParams(words); + for (size_t i = 0; i < words; ++i) + { + wordParams[i]["offset"] = to_string(i * 32); + wordParams[i]["wordValue"] = formatAsStringOrNumber(_message.substr(32 * i, 32)); + } + templ("word", wordParams); + templ("overallLength", to_string(4 + 0x20 + 0x20 + words * 32)); + + return templ.render(); } string YulUtilFunctions::panicFunction(util::PanicCode _code) diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index f1eaed9fe..be1f25d24 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -453,12 +453,18 @@ public: /// signature: (slot, offset) -> std::string storageSetToZeroFunction(Type const& _type); - /// If revertStrings is debug, @returns inline assembly code that + /// If revertStrings is debug, @returns the name of a function that /// stores @param _message in memory position 0 and reverts. - /// Otherwise returns "revert(0, 0)". - static std::string revertReasonIfDebug(RevertStrings revertStrings, std::string const& _message = ""); + /// Otherwise returns the name of a function that uses "revert(0, 0)". + std::string revertReasonIfDebugFunction(std::string const& _message = ""); - std::string revertReasonIfDebug(std::string const& _message = ""); + /// @returns the function body of ``revertReasonIfDebug``. + /// Should only be used internally and by the old code generator. + static std::string revertReasonIfDebugBody( + RevertStrings _revertStrings, + std::string const& _allocation, + std::string const& _message + ); /// Reverts with ``Panic(uint256)`` and the given code. std::string panicFunction(util::PanicCode _code); diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index 228bef068..8ab6b1b17 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -177,8 +177,3 @@ ABIFunctions IRGenerationContext::abiFunctions() { return ABIFunctions(m_evmVersion, m_revertStrings, m_functions); } - -std::string IRGenerationContext::revertReasonIfDebug(std::string const& _message) -{ - return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); -} diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index 9976367d9..0f1e9ae1c 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -143,10 +143,6 @@ public: ABIFunctions abiFunctions(); - /// @returns code that stores @param _message for revert reason - /// if m_revertStrings is debug. - std::string revertReasonIfDebug(std::string const& _message = ""); - RevertStrings revertStrings() const { return m_revertStrings; } std::set& subObjectsCreated() { return m_subObjects; } diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index a1d1522a6..20a434e13 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -839,7 +839,7 @@ string IRGenerator::deployCode(ContractDefinition const& _contract) string IRGenerator::callValueCheck() { - return "if callvalue() { " + m_context.revertReasonIfDebug("Ether sent to non-payable function") + " }"; + return "if callvalue() { " + m_utils.revertReasonIfDebugFunction("Ether sent to non-payable function") + "() }"; } string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) @@ -885,8 +885,8 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) // we revert. delegatecallCheck = "if iszero(called_via_delegatecall) { " + - m_context.revertReasonIfDebug("Non-view function of library called without DELEGATECALL") + - " }"; + m_utils.revertReasonIfDebugFunction("Non-view function of library called without DELEGATECALL") + + "() }"; } templ["delegatecallCheck"] = delegatecallCheck; templ["callValueCheck"] = (type->isPayable() || _contract.isLibrary()) ? "" : callValueCheck(); @@ -937,12 +937,11 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract) t("fallback", fallbackCode); } else - t( - "fallback", + t("fallback", ( etherReceiver ? - m_context.revertReasonIfDebug("Unknown signature and no fallback defined") : - m_context.revertReasonIfDebug("Contract does not have fallback nor receive functions") - ); + m_utils.revertReasonIfDebugFunction("Unknown signature and no fallback defined") : + m_utils.revertReasonIfDebugFunction("Contract does not have fallback nor receive functions") + ) + "()"); return t.render(); } diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index fc33065ef..1eed9f04d 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2433,7 +2433,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( } Whiskers templ(R"( - if iszero(extcodesize(
)) { } + if iszero(extcodesize(
)) { () } // storage for arguments and returned data let := () @@ -2458,7 +2458,7 @@ void IRGeneratorForStatements::appendExternalFunctionCall( := (, add(, )) } )"); - templ("revertNoCode", m_context.revertReasonIfDebug("Target contract does not contain code")); + templ("revertNoCode", m_utils.revertReasonIfDebugFunction("Target contract does not contain code")); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); if (_functionCall.annotation().tryCall)