diff options
author | Yuri Iozzelli <y.iozzelli@gmail.com> | 2022-02-25 16:36:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-25 15:36:35 +0000 |
commit | 1f59b65d8befc8512ff9045bb371ea5ec379a78c (patch) | |
tree | 349621c048c7716a746d3361c8ec6219d32f0250 /src/wast-parser.cc | |
parent | 08cf71aa180674432750a02581f1e214c310042d (diff) | |
download | wabt-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.cc | 46 |
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) { |