diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 36571adc8..a1a42f971 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -511,7 +511,7 @@ LinkerObject const& Assembly::assemble() const LinkerObject& ret = m_assembledObject; - bool const needsEOFContainer = m_eofVersion.has_value(); + bool const eof = m_eofVersion.has_value(); size_t subTagSize = 1; map>> immutableReferencesBySub; @@ -575,10 +575,11 @@ LinkerObject const& Assembly::assemble() const std::optional dataSectionSizeOffset; auto setDataSectionSize = [&](size_t _size) { assertThrow(dataSectionSizeOffset.has_value(), AssemblyException, ""); + assertThrow(_size <= 0xFFFF, AssemblyException, ""); bytesRef length(ret.bytecode.data() + *dataSectionSizeOffset, 2); - toBigEndian(_size, length); + toBigEndian(static_cast(_size), length); }; - if (needsEOFContainer) + if (eof) { bool needsTypeSection = m_codeSections.size() > 1; // TODO: empty data is disallowed @@ -621,14 +622,20 @@ LinkerObject const& Assembly::assemble() const unsigned headerSize = static_cast(ret.bytecode.size()); unsigned bytesRequiredForCode = codeSize(static_cast(subTagSize)); m_tagPositionsInBytecode = vector(m_usedTags, numeric_limits::max()); - map> tagRef; + struct TagRef + { + size_t subId = 0; + size_t tagId = 0; + bool isRelative = 0; + }; + map tagRef; multimap dataRef; multimap subRef; vector sizeRef; ///< Pointers to code locations where the size of the program is inserted unsigned bytesPerTag = numberEncodingSize(headerSize + bytesRequiredForCode + bytesRequiredForDataUpperBound); uint8_t tagPush = static_cast(pushInstruction(bytesPerTag)); - if (!needsEOFContainer) + if (!eof) ++bytesRequiredForCode; ///< Additional INVALID marker. unsigned bytesRequiredIncludingDataAndSubsUpperBound = headerSize + bytesRequiredForCode + bytesRequiredForDataAndSubsUpperBound; @@ -636,10 +643,6 @@ LinkerObject const& Assembly::assemble() const uint8_t dataRefPush = static_cast(pushInstruction(bytesPerDataRef)); ret.bytecode.reserve(bytesRequiredIncludingDataAndSubsUpperBound); - auto const codeStart = ret.bytecode.size(); - - - for (auto&& [codeSectionIndex, codeSection]: m_codeSections | ranges::views::enumerate) { auto const sectionStart = ret.bytecode.size(); @@ -666,8 +669,10 @@ LinkerObject const& Assembly::assemble() const } case PushTag: { + assertThrow(!eof, AssemblyException, "Push tag in EOF code"); ret.bytecode.push_back(tagPush); - tagRef[ret.bytecode.size()] = i.splitForeignPushTag(); + auto [subId, tagId] = i.splitForeignPushTag(); + tagRef[ret.bytecode.size()] = TagRef{subId, tagId, false}; ret.bytecode.resize(ret.bytecode.size() + bytesPerTag); break; } @@ -722,7 +727,7 @@ LinkerObject const& Assembly::assemble() const { // Expect 2 elements on stack (source, dest_base) auto const& offsets = immutableReferencesBySub[i.data()].second; - for (size_t i = 0; i < offsets.size(); ++i) + for (size_t i = 0u; i < offsets.size(); ++i) { if (i != offsets.size() - 1) { @@ -755,12 +760,14 @@ LinkerObject const& Assembly::assemble() const size_t tagId = static_cast(i.data()); assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large."); assertThrow(m_tagPositionsInBytecode[tagId] == numeric_limits::max(), AssemblyException, "Duplicate tag position."); - m_tagPositionsInBytecode[tagId] = ret.bytecode.size() - codeStart; - ret.bytecode.push_back(static_cast(Instruction::JUMPDEST)); + m_tagPositionsInBytecode[tagId] = ret.bytecode.size(); + if (!eof) + ret.bytecode.push_back(static_cast(Instruction::JUMPDEST)); break; } case CallF: { + assertThrow(eof, AssemblyException, "Function call (CALLF) in non-EOF code"); ret.bytecode.push_back(static_cast(Instruction::CALLF)); ret.bytecode.resize(ret.bytecode.size() + 2); bytesRef byr(&ret.bytecode.back() + 1 - 2, 2); @@ -769,9 +776,21 @@ LinkerObject const& Assembly::assemble() const } case RetF: { + assertThrow(eof, AssemblyException, "Function return (RETF) in non-EOF code"); ret.bytecode.push_back(static_cast(Instruction::RETF)); break; } + case RelativeJump: + case ConditionalRelativeJump: + { + assertThrow(eof, AssemblyException, "Relative jump in non-EOF code"); + ret.bytecode.push_back(static_cast(i.type() == RelativeJump ? Instruction::RJUMP : Instruction::RJUMPI)); + auto [subId, tagId] = i.splitForeignPushTag(); + tagRef[ret.bytecode.size()] = TagRef{subId, tagId, true}; + ret.bytecode.push_back(0x00); + ret.bytecode.push_back(0x00); + break; + } default: assertThrow(false, InvalidOpcode, "Unexpected opcode while assembling."); } @@ -779,7 +798,7 @@ LinkerObject const& Assembly::assemble() const auto sectionEnd = ret.bytecode.size(); - if (needsEOFContainer) + if (eof) setCodeSectionSize(codeSectionIndex, sectionEnd - sectionStart); } @@ -791,7 +810,7 @@ LinkerObject const& Assembly::assemble() const "Some immutables were read from but never assigned, possibly because of optimization." ); - if (!needsEOFContainer && (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())) + if (!eof && (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())) // Append an INVALID here to help tests find miscompilation. ret.bytecode.push_back(static_cast(Instruction::INVALID)); @@ -819,11 +838,11 @@ LinkerObject const& Assembly::assemble() const } } - for (auto const& i: tagRef) + for (auto const& [bytecodeOffset, ref]: tagRef) { - size_t subId; - size_t tagId; - tie(subId, tagId) = i.second; + size_t subId = ref.subId; + size_t tagId = ref.tagId; + bool relative = ref.isRelative; assertThrow(subId == numeric_limits::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id"); vector const& tagPositions = subId == numeric_limits::max() ? @@ -833,8 +852,26 @@ LinkerObject const& Assembly::assemble() const size_t pos = tagPositions[tagId]; assertThrow(pos != numeric_limits::max(), AssemblyException, "Reference to tag without position."); assertThrow(numberEncodingSize(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space."); - bytesRef r(ret.bytecode.data() + i.first, bytesPerTag); - toBigEndian(pos, r); + if (relative) + { + assertThrow(m_eofVersion.has_value(), AssemblyException, "Relative jump outside EOF"); + assertThrow(subId == numeric_limits::max(), AssemblyException, "Relative jump to sub"); + bytesRef r(ret.bytecode.data() + bytecodeOffset, 2); + assertThrow( + static_cast(pos) - static_cast(bytecodeOffset + 2u) < 0x7FFF && + static_cast(pos) - static_cast(bytecodeOffset + 2u) >= -0x8000, + AssemblyException, + "Relative jump too far" + ); + uint16_t relativeOffset = static_cast(pos - (bytecodeOffset + 2u)); + toBigEndian(relativeOffset, r); + } + else + { + assertThrow(!m_eofVersion.has_value(), AssemblyException, "Dynamic tag reference within EOF"); + bytesRef r(ret.bytecode.data() + bytecodeOffset, bytesPerTag); + toBigEndian(pos, r); + } } for (auto const& [name, tagInfo]: m_namedTags) { @@ -871,7 +908,7 @@ LinkerObject const& Assembly::assemble() const ret.bytecode += m_auxiliaryData; - if (needsEOFContainer && bytesRequiredForDataAndSubsUpperBound > 0 && ret.bytecode.size() == dataStart) + if (eof && bytesRequiredForDataAndSubsUpperBound > 0 && ret.bytecode.size() == dataStart) { // We have commited to a data section, but not actually needed it, so create a fake one. ret.bytecode.push_back(0); @@ -884,25 +921,13 @@ LinkerObject const& Assembly::assemble() const } auto dataLength = ret.bytecode.size() - dataStart; - if (needsEOFContainer) + if (eof) { - if (bytesRequiredForDataAndSubsUpperBound < dataLength) - { - std::cout << "Auxdata: " << m_auxiliaryData.size() << std::endl; - std::cout << "m_data: " << m_data.size() << std::endl; - std::cout << "subRef: " << subRef.size() << std::endl; - for (auto&& [subIdPath, offset]: subRef) - { - (void)offset; - std::cout << "R: " << subAssemblyById(subIdPath) << std::endl; - } - std::cout << "m_subs: " << m_subs.size() << std::endl; - for (auto const& sub: m_subs) - { - std::cout << "sub: " << sub.get() << std::endl; - } - } - assertThrow(bytesRequiredForDataAndSubsUpperBound >= dataLength, AssemblyException, "More data than expected. " + to_string(dataLength) + " > " + to_string(bytesRequiredForDataUpperBound)); + assertThrow( + bytesRequiredForDataAndSubsUpperBound >= dataLength, + AssemblyException, + "More data than expected. " + to_string(dataLength) + " > " + to_string(bytesRequiredForDataUpperBound) + ); if (bytesRequiredForDataAndSubsUpperBound > 0) { assertThrow(0 < dataLength && dataLength <= 0xffff, AssemblyException, "Invalid data section size."); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index ba54a1d3d..d8c3ed7d9 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -59,6 +59,7 @@ public: std::optional eofVersion() const { return m_eofVersion; } bool supportsFunctions() const { return m_eofVersion.has_value(); } + bool supportsRelativeJumps() const { return m_eofVersion.has_value(); } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } AssemblyItem newFunctionCall(uint16_t _functionID) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 71dffc74c..ff851e83d 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -62,7 +62,7 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const pair AssemblyItem::splitForeignPushTag() const { - assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); + assertThrow(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump, util::Exception, ""); u256 combined = u256(data()); size_t subId = static_cast((combined >> 64) - 1); size_t tag = static_cast(combined & 0xffffffffffffffffULL); @@ -109,7 +109,7 @@ pair AssemblyItem::nameAndData() const void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag) { - assertThrow(m_type == PushTag || m_type == Tag, util::Exception, ""); + assertThrow(m_type == PushTag || m_type == Tag || m_type == RelativeJump || m_type == ConditionalRelativeJump , util::Exception, ""); u256 data = _tag; if (_subId != numeric_limits::max()) data |= (u256(_subId) + 1) << 64; @@ -163,6 +163,10 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision) return 3; case RetF: return 1; + case RelativeJump: + return 3; + case ConditionalRelativeJump: + return 3; default: break; } @@ -183,9 +187,9 @@ size_t AssemblyItem::arguments() const return std::get<0>(*m_functionSignature); } else if (type() == RetF) - { return static_cast(data()); - } + else if (type() == ConditionalRelativeJump) + return 1; else return 0; } @@ -333,6 +337,12 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const case RetF: text = "retf"; break; + case RelativeJump: + text = "rjump(" + string("tag_") + to_string(static_cast(data())) + ")"; + break; + case ConditionalRelativeJump: + text = "rjumpi(" + string("tag_") + to_string(static_cast(data())) + ")"; + break; default: assertThrow(false, InvalidOpcode, ""); } @@ -374,6 +384,24 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item) _out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second; break; } + case RelativeJump: + { + size_t subId = _item.splitForeignPushTag().first; + if (subId == numeric_limits::max()) + _out << " RelativeJump " << _item.splitForeignPushTag().second; + else + _out << " RelativeJump " << subId << ":" << _item.splitForeignPushTag().second; + break; + } + case ConditionalRelativeJump: + { + size_t subId = _item.splitForeignPushTag().first; + if (subId == numeric_limits::max()) + _out << " ConditionalRelativeJump " << _item.splitForeignPushTag().second; + else + _out << " ConditionalRelativeJump " << subId << ":" << _item.splitForeignPushTag().second; + break; + } case Tag: _out << " Tag " << _item.data(); break; diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index a13b68566..2278d2491 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -52,7 +52,9 @@ enum AssemblyItemType AssignImmutable, ///< Assigns the current value on the stack to an immutable variable. Only valid during creation code. VerbatimBytecode, ///< Contains data that is inserted into the bytecode code section without modification. CallF, - RetF + RetF, + RelativeJump, + ConditionalRelativeJump }; enum class Precision { Precise , Approximate }; @@ -97,6 +99,14 @@ public: { return AssemblyItem(RetF, _rets, _location); } + static AssemblyItem jumpTo(AssemblyItem _tag, langutil::SourceLocation _location = langutil::SourceLocation()) + { + return AssemblyItem(RelativeJump, _tag.data(), _location); + } + static AssemblyItem conditionalJumpTo(AssemblyItem _tag, langutil::SourceLocation _location = langutil::SourceLocation()) + { + return AssemblyItem(ConditionalRelativeJump, _tag.data(), _location); + } AssemblyItem(AssemblyItem const&) = default; AssemblyItem(AssemblyItem&&) = default; diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index 5f9fa768f..382d79e6e 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -107,7 +107,7 @@ bool BlockDeduplicator::applyTagReplacement( { bool changed = false; for (AssemblyItem& item: _items) - if (item.type() == PushTag) + if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { size_t subId; size_t tagId; diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index e2ce48b7f..21a5111a2 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -93,6 +93,9 @@ std::map const solidity::evmasm::c_instructions = { "MSIZE", Instruction::MSIZE }, { "GAS", Instruction::GAS }, { "JUMPDEST", Instruction::JUMPDEST }, + { "RJUMP", Instruction::RJUMP }, + { "RJUMPI", Instruction::RJUMPI }, + { "RJUMPV", Instruction::RJUMPV }, { "PUSH1", Instruction::PUSH1 }, { "PUSH2", Instruction::PUSH2 }, { "PUSH3", Instruction::PUSH3 }, @@ -240,6 +243,9 @@ static std::map const c_instructionInfo = { Instruction::MSIZE, { "MSIZE", 0, 0, 1, false, Tier::Base } }, { Instruction::GAS, { "GAS", 0, 0, 1, false, Tier::Base } }, { Instruction::JUMPDEST, { "JUMPDEST", 0, 0, 0, true, Tier::Special } }, + { Instruction::RJUMP, { "RJUMP", 0, 0, 0, true, Tier::Low } }, + { Instruction::RJUMPI, { "RJUMPI", 0, 0, 0, true, Tier::Low } }, + { Instruction::RJUMPV, { "RJUMPV", 0, 1, 0, true, Tier::Low } }, { Instruction::PUSH1, { "PUSH1", 1, 0, 1, false, Tier::VeryLow } }, { Instruction::PUSH2, { "PUSH2", 2, 0, 1, false, Tier::VeryLow } }, { Instruction::PUSH3, { "PUSH3", 3, 0, 1, false, Tier::VeryLow } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index e1c97ff79..67b8f09a6 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -101,6 +101,9 @@ enum class Instruction: uint8_t MSIZE, ///< get the size of active memory GAS, ///< get the amount of available gas JUMPDEST, ///< set a potential jump destination + RJUMP, + RJUMPI, + RJUMPV, PUSH1 = 0x60, ///< place 1 byte item on stack PUSH2, ///< place 2 byte item on stack diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp index 2c0c5875e..2226560b4 100644 --- a/libevmasm/JumpdestRemover.cpp +++ b/libevmasm/JumpdestRemover.cpp @@ -59,7 +59,7 @@ set JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t { set ret; for (auto const& item: _items) - if (item.type() == PushTag) + if (item.type() == PushTag || item.type() == RelativeJump || item.type() == ConditionalRelativeJump) { auto subAndTag = item.splitForeignPushTag(); if (subAndTag.first == _subId) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 334903c92..c53676254 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -291,6 +291,29 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod } }; +struct IsZeroIsZeroRJumpI: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _iszero1, + AssemblyItem const& _iszero2, + AssemblyItem const& _rjumpi, + std::back_insert_iterator _out + ) + { + if ( + _iszero1 == Instruction::ISZERO && + _iszero2 == Instruction::ISZERO && + _rjumpi.type() == ConditionalRelativeJump + ) + { + *_out = _rjumpi; + return true; + } + else + return false; + } +}; + struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -318,6 +341,30 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod } }; +struct EqIsZeroRJumpI: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _eq, + AssemblyItem const& _iszero, + AssemblyItem const& _rjumpi, + std::back_insert_iterator _out + ) + { + if ( + _eq == Instruction::EQ && + _iszero == Instruction::ISZERO && + _rjumpi.type() == ConditionalRelativeJump + ) + { + *_out = AssemblyItem(Instruction::SUB, _eq.location()); + *_out = _rjumpi; + return true; + } + else + return false; + } +}; + // push_tag_1 jumpi push_tag_2 jump tag_1: -> iszero push_tag_2 jumpi tag_1: struct DoubleJump: SimplePeepholeOptimizerMethod { @@ -350,6 +397,33 @@ struct DoubleJump: SimplePeepholeOptimizerMethod } }; +// rjumpi(tag_1) rjump(tag_2) tag_1: -> iszero rjumpi(tag_2) tag_1: +struct DoubleRJump: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _rjumpi, + AssemblyItem const& _rjump, + AssemblyItem const& _tag1, + std::back_insert_iterator _out + ) + { + if ( + _rjumpi.type() == ConditionalRelativeJump && + _rjump.type() == RelativeJump && + _tag1.type() == Tag && + _rjumpi.data() == _tag1.data() + ) + { + *_out = AssemblyItem(Instruction::ISZERO, _rjumpi.location()); + *_out = AssemblyItem::conditionalJumpTo(_rjump.tag(), _rjump.location()); + *_out = _tag1; + return true; + } + else + return false; + } +}; + struct JumpToNext: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -376,6 +450,30 @@ struct JumpToNext: SimplePeepholeOptimizerMethod } }; +struct RJumpToNext: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _rjump, + AssemblyItem const& _tag, + std::back_insert_iterator _out + ) + { + if ( + (_rjump.type() == ConditionalRelativeJump || _rjump.type() == RelativeJump) && + _tag.type() == Tag && + _rjump.data() == _tag.data() + ) + { + if (_rjump.type() == ConditionalRelativeJump) + *_out = AssemblyItem(Instruction::POP, _rjump.location()); + *_out = _tag; + return true; + } + else + return false; + } +}; + struct TagConjunctions: SimplePeepholeOptimizerMethod { static bool applySimple( @@ -439,6 +537,7 @@ struct UnreachableCode return false; if ( it[0] != Instruction::JUMP && + it[0] != Instruction::RJUMP && it[0] != Instruction::RETURN && it[0] != Instruction::STOP && it[0] != Instruction::INVALID && @@ -489,8 +588,8 @@ bool PeepholeOptimiser::optimise() applyMethods( state, PushPop(), OpPop(), OpStop(), OpReturnRevert(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), - DupSwap(), IsZeroIsZeroJumpI(), EqIsZeroJumpI(), DoubleJump(), JumpToNext(), UnreachableCode(), - TagConjunctions(), TruthyAnd(), Identity() + DupSwap(), IsZeroIsZeroJumpI(), IsZeroIsZeroRJumpI{}, EqIsZeroJumpI(), DoubleJump(), DoubleRJump(), + JumpToNext(), RJumpToNext(), UnreachableCode(), TagConjunctions(), TruthyAnd(), Identity() ); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 17e06400f..aea6fe38f 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -112,14 +112,31 @@ void EthAssemblyAdapter::appendJump(int _stackDiffAfter, JumpType _jumpType) void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) { - appendLabelReference(_labelId); - appendJump(_stackDiffAfter, _jumpType); + if (m_assembly.supportsRelativeJumps()) + { + m_assembly.append(evmasm::AssemblyItem::jumpTo(evmasm::AssemblyItem(evmasm::PushTag, _labelId))); + yulAssert(_jumpType == JumpType::Ordinary); + m_assembly.adjustDeposit(_stackDiffAfter); + } + else + { + appendLabelReference(_labelId); + appendJump(_stackDiffAfter, _jumpType); + } } void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId, JumpType _jumpType) { - appendLabelReference(_labelId); - appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); + if (m_assembly.supportsRelativeJumps()) + { + m_assembly.append(evmasm::AssemblyItem::conditionalJumpTo(evmasm::AssemblyItem(evmasm::PushTag, _labelId))); + yulAssert(_jumpType == JumpType::Ordinary); + } + else + { + appendLabelReference(_labelId); + appendJumpInstruction(evmasm::Instruction::JUMPI, _jumpType); + } } void EthAssemblyAdapter::appendAssemblySize() diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 94051e801..8c793a8bc 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -267,7 +267,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) checkCompilation(assembly); - string const sourceMappings = AssemblyItem::computeSourceMapping(assembly.items(), indices); + string const sourceMappings = AssemblyItem::computeSourceMapping(assembly.codeSections().at(0).items, indices); auto const numberOfMappings = std::count(sourceMappings.begin(), sourceMappings.end(), ';'); LinkerObject const& obj = assembly.assemble(); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index db93c3257..e48671bbd 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1296,7 +1296,7 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) u256(8) }; BOOST_CHECK_EQUAL_COLLECTIONS( - main.items().begin(), main.items().end(), + main.codeSections().at(0).items.begin(),main.codeSections().at(0).items.end(), expectationMain.begin(), expectationMain.end() ); @@ -1304,7 +1304,7 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) u256(1), t1.tag(), u256(2), Instruction::JUMP, t4.tag(), u256(7), t4.pushTag(), Instruction::JUMP }; BOOST_CHECK_EQUAL_COLLECTIONS( - sub->items().begin(), sub->items().end(), + sub->codeSections().at(0).items.begin(), sub->codeSections().at(0).items.end(), expectationSub.begin(), expectationSub.end() ); } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index ebf3e6dc3..2424d47a1 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -93,7 +93,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) ); compiler.compileContract(*contract, map>{}, bytes()); - return compiler.runtimeAssembly().items(); + return compiler.runtimeAssembly().codeSections().at(0).items; } BOOST_FAIL("No contract found in source."); return AssemblyItems(); diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index 1cb6816d4..f240fa7db 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -444,6 +444,9 @@ u256 EVMInstructionInterpreter::eval( case Instruction::CALLF: case Instruction::RETF: case Instruction::JUMPF: + case Instruction::RJUMP: + case Instruction::RJUMPI: + case Instruction::RJUMPV: { yulAssert(false, ""); return 0;