summaryrefslogtreecommitdiff
path: root/src/binary-reader-ir.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/binary-reader-ir.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/binary-reader-ir.cc')
-rw-r--r--src/binary-reader-ir.cc94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index fbb1b091..ff3eafab 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -21,6 +21,7 @@
#include <cstdarg>
#include <cstdint>
#include <cstdio>
+#include <deque>
#include <vector>
#include "src/binary-reader-nop.h"
@@ -43,6 +44,52 @@ struct LabelNode {
LabelNode::LabelNode(LabelType label_type, ExprList* exprs, Expr* context)
: label_type(label_type), exprs(exprs), context(context) {}
+class CodeMetadataExprQueue {
+ private:
+ struct Entry {
+ Func* func;
+ std::deque<std::unique_ptr<CodeMetadataExpr>> func_queue;
+ Entry(Func* f) : func(f) {}
+ };
+ std::deque<Entry> entries;
+
+ public:
+ CodeMetadataExprQueue() {}
+ void push_func(Func* f) { entries.emplace_back(f); }
+ void push_metadata(std::unique_ptr<CodeMetadataExpr> meta) {
+ assert(!entries.empty());
+ entries.back().func_queue.push_back(std::move(meta));
+ }
+
+ std::unique_ptr<CodeMetadataExpr> pop_match(Func* f, Offset offset) {
+ std::unique_ptr<CodeMetadataExpr> ret;
+ if (entries.empty()) {
+ return ret;
+ }
+
+ auto& current_entry = entries.front();
+
+ if (current_entry.func != f)
+ return ret;
+ if (current_entry.func_queue.empty()) {
+ entries.pop_front();
+ return ret;
+ }
+
+ auto& current_metadata = current_entry.func_queue.front();
+ if (current_metadata->loc.offset + current_entry.func->loc.offset !=
+ offset) {
+ return ret;
+ }
+
+ current_metadata->loc = Location(offset);
+ ret = std::move(current_metadata);
+ current_entry.func_queue.pop_front();
+
+ return ret;
+ }
+};
+
class BinaryReaderIR : public BinaryReaderNop {
public:
BinaryReaderIR(Module* out_module, const char* filename, Errors* errors);
@@ -115,6 +162,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result BeginFunctionBody(Index index, Offset size) override;
Result OnLocalDecl(Index decl_index, Index count, Type type) override;
+ Result OnOpcode(Opcode opcode) override;
Result OnAtomicLoadExpr(Opcode opcode,
Address alignment_log2,
Address offset) override;
@@ -276,6 +324,12 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnSectionSymbol(Index index,
uint32_t flags,
Index section_index) override;
+ /* Code Metadata sections */
+ Result BeginCodeMetadataSection(std::string_view name, Offset size) override;
+ Result OnCodeMetadataFuncCount(Index count) override;
+ Result OnCodeMetadataCount(Index function_index, Index count) override;
+ Result OnCodeMetadata(Offset offset, const void* data, Address size) override;
+
Result OnTagSymbol(Index index,
uint32_t flags,
std::string_view name,
@@ -318,6 +372,9 @@ class BinaryReaderIR : public BinaryReaderNop {
Func* current_func_ = nullptr;
std::vector<LabelNode> label_stack_;
const char* filename_;
+
+ CodeMetadataExprQueue code_metadata_queue_;
+ std::string_view current_metadata_name_;
};
BinaryReaderIR::BinaryReaderIR(Module* out_module,
@@ -660,6 +717,7 @@ Result BinaryReaderIR::OnFunctionBodyCount(Index count) {
Result BinaryReaderIR::BeginFunctionBody(Index index, Offset size) {
current_func_ = module_->funcs[index];
+ current_func_->loc = GetLocation();
PushLabel(LabelType::Func, &current_func_->exprs);
return Result::Ok;
}
@@ -669,6 +727,15 @@ Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) {
return Result::Ok;
}
+Result BinaryReaderIR::OnOpcode(Opcode opcode) {
+ std::unique_ptr<CodeMetadataExpr> metadata =
+ code_metadata_queue_.pop_match(current_func_, GetLocation().offset - 1);
+ if (metadata) {
+ return AppendExpr(std::move(metadata));
+ }
+ return Result::Ok;
+}
+
Result BinaryReaderIR::OnAtomicLoadExpr(Opcode opcode,
Address alignment_log2,
Address offset) {
@@ -1447,6 +1514,33 @@ Result BinaryReaderIR::OnLocalNameLocalCount(Index index, Index count) {
return Result::Ok;
}
+Result BinaryReaderIR::BeginCodeMetadataSection(std::string_view name,
+ Offset size) {
+ current_metadata_name_ = name;
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnCodeMetadataFuncCount(Index count) {
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnCodeMetadataCount(Index function_index, Index count) {
+ code_metadata_queue_.push_func(module_->funcs[function_index]);
+ return Result::Ok;
+}
+
+Result BinaryReaderIR::OnCodeMetadata(Offset offset,
+ const void* data,
+ Address size) {
+ std::vector<uint8_t> data_(static_cast<const uint8_t*>(data),
+ static_cast<const uint8_t*>(data) + size);
+ auto meta =
+ MakeUnique<CodeMetadataExpr>(current_metadata_name_, std::move(data_));
+ meta->loc.offset = offset;
+ code_metadata_queue_.push_metadata(std::move(meta));
+ return Result::Ok;
+}
+
Result BinaryReaderIR::OnLocalName(Index func_index,
Index local_index,
std::string_view name) {