From 2721f9c6f5d2ab0403ed508c13cb9aa425b6fffb Mon Sep 17 00:00:00 2001 From: charles-liu Date: Sat, 2 Apr 2022 03:26:01 +0800 Subject: [PATCH] fix: fix issue when the receive function calls an internal function. close #17 --- libevmasm/Assembly.cpp | 5 +++-- libevmasm/Assembly.h | 7 ++++--- libsolidity/codegen/CompilerContext.cpp | 4 +++- libsolidity/codegen/CompilerContext.h | 9 +++++---- libsolidity/codegen/ContractCompiler.cpp | 12 +++++++++--- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 8dfc2e4..bf5c5b4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -45,6 +45,7 @@ void Assembly::appendDebugInfo(string const& _debugInfo) auto iter = m_debugInfos.find(pos); auto message = iter == m_debugInfos.end() ? _debugInfo : iter->second + "\n // " + _debugInfo; m_debugInfos[pos] = message; + if (m_verbose) std::clog << " [Assembly] " << _debugInfo << std::endl; } unsigned Assembly::bytesRequired(unsigned subTagSize) const @@ -757,10 +758,10 @@ LinkerObject const& Assembly::assemble() const subId == numeric_limits::max() ? m_tagPositionsInBytecode : m_subs[subId]->m_tagPositionsInBytecode; - assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag: "+ + assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag: tag_"+ toString(tagId)); size_t pos = tagPositions[tagId]; - assertThrow(pos != numeric_limits::max(), AssemblyException, "Reference to tag without position: "+ + assertThrow(pos != numeric_limits::max(), AssemblyException, "Reference to tag without position: tag_"+ toString(tagId)); assertThrow(util::bytesRequired(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space."); bytesRef r(ret.bytecode.data() + i.first, bytesPerTag); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 77b6183..b30c5e7 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -29,8 +29,8 @@ using AssemblyPointer = std::shared_ptr; class Assembly { public: - AssemblyItem newTag(std::string const& _description = "") { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++, langutil::SourceLocation(), _description); } - AssemblyItem newPushTag(std::string const& _description = "") { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++, langutil::SourceLocation(), _description); } + AssemblyItem newTag(std::string const& _description = "") { appendDebugInfo("newTag tag_" + std::to_string(m_usedTags+1) + ", desc: " + _description); assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++, langutil::SourceLocation(), _description); } + AssemblyItem newPushTag(std::string const& _description = "") { appendDebugInfo("newPushTag tag_" + std::to_string(m_usedTags+1) + ", desc: " + _description); assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++, langutil::SourceLocation(), _description); } /// Returns a tag identified by the given name. Creates it if it does not yet exist. AssemblyItem namedTag(std::string const& _name); // Solidity++: keccak256 -> blake2b @@ -60,7 +60,7 @@ class Assembly void appendDebugInfo(std::string const& _debugInfo); AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; } - AssemblyItem appendJumpI(std::string const& _description = "") { auto ret = append(newPushTag(_description)); append(Instruction::JUMPI); return ret; } + AssemblyItem appendJumpI(std::string const& _description = "") { auto ret = append(newPushTag(_description)); append(Instruction::JUMPI); appendDebugInfo("Jump to "+ret.toAssemblyText(*this)); return ret; } AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; } AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; } @@ -188,6 +188,7 @@ class Assembly public: size_t m_currentModifierDepth = 0; + bool m_verbose = false; }; inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 8914af9..8ce0543 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -172,7 +172,9 @@ void CompilerContext::appendMissingLowLevelFunctions() m_lowLevelFunctionGenerationQueue.pop(); setStackOffset(static_cast(inArgs) + 1); - *this << m_lowLevelFunctions.at(name).tag(); + auto tag = m_lowLevelFunctions.at(name).tag(); + *this << tag; + debug("CompilerContext::appendMissingLowLevelFunctions: " + name + "->" + tag.toAssemblyText(*m_asm)); generator(*this); CompilerUtils(*this).moveToStackTop(outArgs); appendJump(evmasm::AssemblyItem::JumpType::OutOfFunction); diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 8fcd7d0..f93e349 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -59,6 +59,7 @@ class CompilerContext { if (m_runtimeContext) m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data()); + m_asm->m_verbose = _verbose; } langutil::EVMVersion const& evmVersion() const { return m_evmVersion; } @@ -175,11 +176,11 @@ class CompilerContext std::pair storageLocationOfVariable(Declaration const& _declaration) const; /// Appends a JUMPI instruction to a new tag and @returns the tag - evmasm::AssemblyItem appendConditionalJump(std::string const& _description = "") { return m_asm->appendJumpI(_description).tag(); } + evmasm::AssemblyItem appendConditionalJump(std::string const& _description = "") { debug("appendConditionalJump "); return m_asm->appendJumpI(_description).tag(); } /// Appends a JUMPI instruction to @a _tag - CompilerContext& appendConditionalJumpTo(evmasm::AssemblyItem const& _tag) { m_asm->appendJumpI(_tag); return *this; } + CompilerContext& appendConditionalJumpTo(evmasm::AssemblyItem const& _tag) { debug("appendConditionalJumpTo "+_tag.toAssemblyText(*m_asm)); m_asm->appendJumpI(_tag); return *this; } /// Appends a JUMP to a new tag and @returns the tag - evmasm::AssemblyItem appendJumpToNew() { return m_asm->appendJump().tag(); } + evmasm::AssemblyItem appendJumpToNew() { debug("appendJumpToNew "); return m_asm->appendJump().tag(); } /// Appends a JUMP to a tag already on the stack CompilerContext& appendJump(evmasm::AssemblyItem::JumpType _jumpType = evmasm::AssemblyItem::JumpType::Ordinary); /// Appends code to revert with a Panic(uint256) error. @@ -200,7 +201,7 @@ class CompilerContext CompilerContext& appendJumpTo( evmasm::AssemblyItem const& _tag, evmasm::AssemblyItem::JumpType _jumpType = evmasm::AssemblyItem::JumpType::Ordinary - ) { *m_asm << _tag.pushTag(); return appendJump(_jumpType); } + ) { debug("appendJumpTo "+_tag.toAssemblyText(*m_asm)); *m_asm << _tag.pushTag(); return appendJump(_jumpType); } /// Appends pushing of a new tag and @returns the new tag. evmasm::AssemblyItem pushNewTag(std::string const& _description = "") { return m_asm->append(m_asm->newPushTag(_description)).tag(); } /// @returns a new tag without pushing any opcodes or data diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 2ac12bf..22270bc 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -192,6 +192,8 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont m_runtimeCompiler->appendMissingFunctions(); m_runtimeCompiler->appendFunctionSelector(_contract); + // Solidity++: Do it again to compile the missing functions which are called in the receive/fallback functions + m_runtimeCompiler->appendMissingFunctions(); // Solidity++: Moved from appendMissingFunctions() m_runtimeCompiler->m_context.appendYulUtilityFunctions(m_optimiserSettings); @@ -235,10 +237,12 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract) solAssert(_contract.isLibrary(), "Tried to deploy contract as library."); appendMissingFunctions(); - m_runtimeCompiler->appendMissingFunctions(); // Solidity++: Moved from compileContract() + m_runtimeCompiler->appendMissingFunctions(); m_runtimeCompiler->appendFunctionSelector(_contract); + // Solidity++: Do it again to compile the missing functions which are called in the receive/fallback functions + m_runtimeCompiler->appendMissingFunctions(); // Solidity++: Moved from appendMissingFunctions() m_runtimeCompiler->m_context.appendYulUtilityFunctions(m_optimiserSettings); @@ -1467,7 +1471,7 @@ void ContractCompiler::appendMissingFunctions() void ContractCompiler::appendModifierOrFunctionCode() { solAssert(m_currentFunction, ""); - auto debugInfo = "ContractCompiler::appendModifierOrFunctionCode() for " + m_currentFunction->name(); + auto debugInfo = "ContractCompiler::appendModifierOrFunctionCode() for " + m_currentFunction->location().text(); debug(debugInfo); m_context.appendDebugInfo(debugInfo); unsigned stackSurplus = 0; @@ -1542,8 +1546,10 @@ void ContractCompiler::appendModifierOrFunctionCode() solAssert(!m_returnTags.empty(), ""); m_context.appendDebugInfo("start processing return data"); - m_context << m_returnTags.back().first; + auto returnTag = m_returnTags.back().first; + m_context << returnTag; m_returnTags.pop_back(); + debug("Return tag: " + returnTag.toAssemblyText(m_context.assembly())); CompilerUtils(m_context).popStackSlots(stackSurplus); for (auto var: addedVariables)