Binary transform for br and br_if.

This commit is contained in:
chriseth
2020-05-14 11:30:19 +02:00
parent 504b8d29c9
commit 6308ca4a22
10 changed files with 631 additions and 15 deletions
+30 -13
View File
@@ -358,13 +358,13 @@ bytes BinaryTransform::operator()(If const& _if)
toBytes(Opcode::If) +
toBytes(ValueType::Void);
m_labels.push({});
m_labels.emplace_back();
result += visit(_if.statements);
if (_if.elseStatements)
result += toBytes(Opcode::Else) + visit(*_if.elseStatements);
m_labels.pop();
m_labels.pop_back();
result += toBytes(Opcode::End);
return result;
@@ -374,26 +374,24 @@ bytes BinaryTransform::operator()(Loop const& _loop)
{
bytes result = toBytes(Opcode::Loop) + toBytes(ValueType::Void);
m_labels.push(_loop.labelName);
m_labels.emplace_back(_loop.labelName);
result += visit(_loop.statements);
m_labels.pop();
m_labels.pop_back();
result += toBytes(Opcode::End);
return result;
}
bytes BinaryTransform::operator()(Break const&)
bytes BinaryTransform::operator()(Break const& _break)
{
yulAssert(false, "br not yet implemented.");
// TODO the index is just the nesting depth.
return {};
return toBytes(Opcode::Br) + encodeLabelIdx(_break.label.name);
}
bytes BinaryTransform::operator()(BreakIf const&)
bytes BinaryTransform::operator()(BreakIf const& _breakIf)
{
yulAssert(false, "br_if not yet implemented.");
// TODO the index is just the nesting depth.
return {};
bytes result = std::visit(*this, *_breakIf.condition);
result += toBytes(Opcode::BrIf) + encodeLabelIdx(_breakIf.label.name);
return result;
}
bytes BinaryTransform::operator()(Return const&)
@@ -403,11 +401,14 @@ bytes BinaryTransform::operator()(Return const&)
bytes BinaryTransform::operator()(Block const& _block)
{
return
m_labels.emplace_back(_block.labelName);
bytes result =
toBytes(Opcode::Block) +
toBytes(ValueType::Void) +
visit(_block.statements) +
toBytes(Opcode::End);
m_labels.pop_back();
return result;
}
bytes BinaryTransform::operator()(FunctionDefinition const& _function)
@@ -427,9 +428,13 @@ bytes BinaryTransform::operator()(FunctionDefinition const& _function)
for (size_t i = 0; i < _function.locals.size(); ++i)
m_locals[_function.locals[i].variableName] = varIdx++;
yulAssert(m_labels.empty(), "Stray labels.");
ret += visit(_function.body);
ret += toBytes(Opcode::End);
yulAssert(m_labels.empty(), "Stray labels.");
return prefixSize(std::move(ret));
}
@@ -581,6 +586,18 @@ bytes BinaryTransform::visitReversed(vector<Expression> const& _expressions)
return result;
}
bytes BinaryTransform::encodeLabelIdx(string const& _label) const
{
yulAssert(!_label.empty(), "Empty label.");
size_t depth = 0;
for (string const& label: m_labels | boost::adaptors::reversed)
if (label == _label)
return lebEncode(depth);
else
++depth;
yulAssert(false, "Label not found.");
}
bytes BinaryTransform::encodeName(std::string const& _name)
{
// UTF-8 is allowed here by the Wasm spec, but since all names here should stem from
+3 -1
View File
@@ -77,13 +77,15 @@ private:
bytes visit(std::vector<wasm::Expression> const& _expressions);
bytes visitReversed(std::vector<wasm::Expression> const& _expressions);
bytes encodeLabelIdx(std::string const& _label) const;
static bytes encodeName(std::string const& _name);
std::map<std::string, size_t> m_locals;
std::map<std::string, size_t> m_globals;
std::map<std::string, size_t> m_functions;
std::map<std::string, size_t> m_functionTypes;
std::stack<std::string> m_labels;
std::vector<std::string> m_labels;
std::map<std::string, std::pair<size_t, size_t>> m_subModulePosAndSize;
};
+1 -1
View File
@@ -123,7 +123,7 @@ string TextTransform::operator()(wasm::Loop const& _loop)
string TextTransform::operator()(wasm::Break const& _break)
{
return "(break $" + _break.label.name + ")\n";
return "(br $" + _break.label.name + ")\n";
}
string TextTransform::operator()(wasm::BreakIf const& _break)