Initial working version of rjumps.

This commit is contained in:
Daniel Kirchner 2022-12-20 16:33:02 +01:00
parent d4314bb874
commit 0ccc3e3762
14 changed files with 249 additions and 57 deletions

View File

@ -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<u256, pair<string, vector<size_t>>> immutableReferencesBySub;
@ -575,10 +575,11 @@ LinkerObject const& Assembly::assemble() const
std::optional<size_t> 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<uint16_t>(_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<unsigned>(ret.bytecode.size());
unsigned bytesRequiredForCode = codeSize(static_cast<unsigned>(subTagSize));
m_tagPositionsInBytecode = vector<size_t>(m_usedTags, numeric_limits<size_t>::max());
map<size_t, pair<size_t, size_t>> tagRef;
struct TagRef
{
size_t subId = 0;
size_t tagId = 0;
bool isRelative = 0;
};
map<size_t, TagRef> tagRef;
multimap<h256, unsigned> dataRef;
multimap<size_t, size_t> subRef;
vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
unsigned bytesPerTag = numberEncodingSize(headerSize + bytesRequiredForCode + bytesRequiredForDataUpperBound);
uint8_t tagPush = static_cast<uint8_t>(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<uint8_t>(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<size_t>(i.data());
assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large.");
assertThrow(m_tagPositionsInBytecode[tagId] == numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position.");
m_tagPositionsInBytecode[tagId] = ret.bytecode.size() - codeStart;
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
m_tagPositionsInBytecode[tagId] = ret.bytecode.size();
if (!eof)
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
break;
}
case CallF:
{
assertThrow(eof, AssemblyException, "Function call (CALLF) in non-EOF code");
ret.bytecode.push_back(static_cast<uint8_t>(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<uint8_t>(Instruction::RETF));
break;
}
case RelativeJump:
case ConditionalRelativeJump:
{
assertThrow(eof, AssemblyException, "Relative jump in non-EOF code");
ret.bytecode.push_back(static_cast<uint8_t>(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<uint8_t>(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<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id");
vector<size_t> const& tagPositions =
subId == numeric_limits<size_t>::max() ?
@ -833,8 +852,26 @@ LinkerObject const& Assembly::assemble() const
size_t pos = tagPositions[tagId];
assertThrow(pos != numeric_limits<size_t>::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<size_t>::max(), AssemblyException, "Relative jump to sub");
bytesRef r(ret.bytecode.data() + bytecodeOffset, 2);
assertThrow(
static_cast<ssize_t>(pos) - static_cast<ssize_t>(bytecodeOffset + 2u) < 0x7FFF &&
static_cast<ssize_t>(pos) - static_cast<ssize_t>(bytecodeOffset + 2u) >= -0x8000,
AssemblyException,
"Relative jump too far"
);
uint16_t relativeOffset = static_cast<uint16_t>(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.");

View File

@ -59,6 +59,7 @@ public:
std::optional<uint8_t> 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)

View File

@ -62,7 +62,7 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const
pair<size_t, size_t> 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<size_t>((combined >> 64) - 1);
size_t tag = static_cast<size_t>(combined & 0xffffffffffffffffULL);
@ -109,7 +109,7 @@ pair<string, string> 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<size_t>::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<size_t>(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<size_t>(data())) + ")";
break;
case ConditionalRelativeJump:
text = "rjumpi(" + string("tag_") + to_string(static_cast<size_t>(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<size_t>::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<size_t>::max())
_out << " ConditionalRelativeJump " << _item.splitForeignPushTag().second;
else
_out << " ConditionalRelativeJump " << subId << ":" << _item.splitForeignPushTag().second;
break;
}
case Tag:
_out << " Tag " << _item.data();
break;

View File

@ -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;

View File

@ -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;

View File

@ -93,6 +93,9 @@ std::map<std::string, Instruction> 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<Instruction, InstructionInfo> 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 } },

View File

@ -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

View File

@ -59,7 +59,7 @@ set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t
{
set<size_t> 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)

View File

@ -291,6 +291,29 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI>
}
};
struct IsZeroIsZeroRJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI>
{
static size_t applySimple(
AssemblyItem const& _iszero1,
AssemblyItem const& _iszero2,
AssemblyItem const& _rjumpi,
std::back_insert_iterator<AssemblyItems> _out
)
{
if (
_iszero1 == Instruction::ISZERO &&
_iszero2 == Instruction::ISZERO &&
_rjumpi.type() == ConditionalRelativeJump
)
{
*_out = _rjumpi;
return true;
}
else
return false;
}
};
struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
{
static size_t applySimple(
@ -318,6 +341,30 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
}
};
struct EqIsZeroRJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
{
static size_t applySimple(
AssemblyItem const& _eq,
AssemblyItem const& _iszero,
AssemblyItem const& _rjumpi,
std::back_insert_iterator<AssemblyItems> _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<DoubleJump>
{
@ -350,6 +397,33 @@ struct DoubleJump: SimplePeepholeOptimizerMethod<DoubleJump>
}
};
// rjumpi(tag_1) rjump(tag_2) tag_1: -> iszero rjumpi(tag_2) tag_1:
struct DoubleRJump: SimplePeepholeOptimizerMethod<DoubleJump>
{
static size_t applySimple(
AssemblyItem const& _rjumpi,
AssemblyItem const& _rjump,
AssemblyItem const& _tag1,
std::back_insert_iterator<AssemblyItems> _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<JumpToNext>
{
static size_t applySimple(
@ -376,6 +450,30 @@ struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>
}
};
struct RJumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>
{
static size_t applySimple(
AssemblyItem const& _rjump,
AssemblyItem const& _tag,
std::back_insert_iterator<AssemblyItems> _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<TagConjunctions>
{
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() && (

View File

@ -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()

View File

@ -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();

View File

@ -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()
);
}

View File

@ -93,7 +93,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
);
compiler.compileContract(*contract, map<ContractDefinition const*, shared_ptr<Compiler const>>{}, bytes());
return compiler.runtimeAssembly().items();
return compiler.runtimeAssembly().codeSections().at(0).items;
}
BOOST_FAIL("No contract found in source.");
return AssemblyItems();

View File

@ -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;