summaryrefslogtreecommitdiff
path: root/src/wast-parser.cc
diff options
context:
space:
mode:
authorYuri Iozzelli <y.iozzelli@gmail.com>2022-02-25 16:36:35 +0100
committerGitHub <noreply@github.com>2022-02-25 15:36:35 +0000
commit1f59b65d8befc8512ff9045bb371ea5ec379a78c (patch)
tree349621c048c7716a746d3361c8ec6219d32f0250 /src/wast-parser.cc
parent08cf71aa180674432750a02581f1e214c310042d (diff)
downloadwabt-1f59b65d8befc8512ff9045bb371ea5ec379a78c.tar.gz
wabt-1f59b65d8befc8512ff9045bb371ea5ec379a78c.tar.bz2
wabt-1f59b65d8befc8512ff9045bb371ea5ec379a78c.zip
Add initial support for code metadata (#1840)
See https://github.com/WebAssembly/tool-conventions/blob/main/CodeMetadata.md for the specification. In particular this pr implements the following: - Parsing code metadata sections in BinaryReader, providing appropriate callbacks that a BinaryReaderDelegate can implement: - BinaryReaderObjdump: show the sections in a human-readable form - BinaryReaderIr: add code metadata in the IR as expressions - Parsing code metadata annotations in text format, adding them in the IR like the BinaryReaderIR does - Writing the code metadata present in the IR in the proper sections when converting IR to binary - Support in wasm-decompiler for showing code metadata as comments in the pseudo-code All the features have corresponding tests. Support for code metadata is gated through the --enable-code-metadata feature. For reading/writing in the text format, --enable-annotations is also required. Missing features: Support for function-level code metadata (offset 0) Extensive validation in validator.cc (like making sure that all metadata instances are at the same code offset of an instruction)
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r--src/wast-parser.cc46
1 files changed, 41 insertions, 5 deletions
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 99406786..f07ee8b1 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -194,6 +194,10 @@ bool IsInstr(TokenTypePair pair) {
return IsPlainOrBlockInstr(pair[0]) || IsExpr(pair);
}
+bool IsLparAnn(TokenTypePair pair) {
+ return pair[0] == TokenType::LparAnn;
+}
+
bool IsCatch(TokenType token_type) {
return token_type == TokenType::Catch || token_type == TokenType::CatchAll;
}
@@ -551,12 +555,18 @@ TokenType WastParser::Peek(size_t n) {
if (cur.token_type() != TokenType::LparAnn) {
tokens_.push_back(cur);
} else {
- // Custom annotation. For now, discard until matching Rpar.
+ // Custom annotation. For now, discard until matching Rpar, unless it is
+ // a code metadata annotation. In that case, we know how to parse it.
if (!options_->features.annotations_enabled()) {
Error(cur.loc, "annotations not enabled: %s", cur.to_string().c_str());
tokens_.push_back(Token(cur.loc, TokenType::Invalid));
continue;
}
+ if (options_->features.code_metadata_enabled() &&
+ cur.text().find("metadata.code.") == 0) {
+ tokens_.push_back(cur);
+ continue;
+ }
int indent = 1;
while (indent > 0) {
cur = lexer_->GetToken(this);
@@ -1826,11 +1836,22 @@ Result WastParser::ParseResultList(
Result WastParser::ParseInstrList(ExprList* exprs) {
WABT_TRACE(ParseInstrList);
ExprList new_exprs;
- while (IsInstr(PeekPair())) {
- if (Succeeded(ParseInstr(&new_exprs))) {
- exprs->splice(exprs->end(), new_exprs);
+ while (true) {
+ auto pair = PeekPair();
+ if (IsInstr(pair)) {
+ if (Succeeded(ParseInstr(&new_exprs))) {
+ exprs->splice(exprs->end(), new_exprs);
+ } else {
+ CHECK_RESULT(Synchronize(IsInstr));
+ }
+ } else if (IsLparAnn(pair)) {
+ if (Succeeded(ParseCodeMetadataAnnotation(&new_exprs))) {
+ exprs->splice(exprs->end(), new_exprs);
+ } else {
+ CHECK_RESULT(Synchronize(IsLparAnn));
+ }
} else {
- CHECK_RESULT(Synchronize(IsInstr));
+ break;
}
}
return Result::Ok;
@@ -1866,6 +1887,21 @@ Result WastParser::ParseInstr(ExprList* exprs) {
}
}
+Result WastParser::ParseCodeMetadataAnnotation(ExprList* exprs) {
+ WABT_TRACE(ParseCodeMetadataAnnotation);
+ Token tk = Consume();
+ std::string_view name = tk.text();
+ name.remove_prefix(sizeof("metadata.code.") - 1);
+ std::string data_text;
+ CHECK_RESULT(ParseQuotedText(&data_text));
+ std::vector<uint8_t> data(data_text.begin(), data_text.end());
+ exprs->push_back(MakeUnique<CodeMetadataExpr>(name, std::move(data)));
+ TokenType rpar = Peek();
+ assert(rpar == TokenType::Rpar);
+ Consume();
+ return Result::Ok;
+}
+
template <typename T>
Result WastParser::ParsePlainInstrVar(Location loc,
std::unique_ptr<Expr>* out_expr) {