Last active
May 3, 2016 16:13
-
-
Save yurydelendik/6619394d4a47d8448170d429dd74ca99 to your computer and use it in GitHub Desktop.
SM WASM with debug information
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Yury Delendik <[email protected]> | |
# Date 1462291965 18000 | |
# Tue May 03 11:12:45 2016 -0500 | |
# Node ID 88863f30dd23ebd15831f55b73e0e6df0ec614ae | |
# Parent 77cead2cd20300623eea2416bc9bce4d5021df09 | |
Parse code annotations | |
diff --git a/js/src/asmjs/WasmBinary.h b/js/src/asmjs/WasmBinary.h | |
--- a/js/src/asmjs/WasmBinary.h | |
+++ b/js/src/asmjs/WasmBinary.h | |
@@ -30,16 +30,17 @@ static const uint32_t EncodingVersion | |
static const char TypeSectionId[] = "type"; | |
static const char ImportSectionId[] = "import"; | |
static const char FunctionSectionId[] = "function"; | |
static const char TableSectionId[] = "table"; | |
static const char MemorySectionId[] = "memory"; | |
static const char ExportSectionId[] = "export"; | |
static const char CodeSectionId[] = "code"; | |
static const char DataSectionId[] = "data"; | |
+static const char DbgTablesId[] = "_experiment_dbg_tables"; | |
enum class ValType | |
{ | |
I32 = 0x01, | |
I64 = 0x02, | |
F32 = 0x03, | |
F64 = 0x04, | |
@@ -399,24 +400,26 @@ class Encoder | |
offset++; | |
return offset - start + 1; | |
} | |
static const size_t ExprLimit = 2 * UINT8_MAX - 1; | |
public: | |
explicit Encoder(Bytes& bytes) | |
- : bytes_(bytes) | |
+ : bytes_(bytes), data(nullptr) | |
{ | |
MOZ_ASSERT(empty()); | |
} | |
size_t currentOffset() const { return bytes_.length(); } | |
bool empty() const { return currentOffset() == 0; } | |
+ void *data; | |
+ | |
// Fixed-size encoding operations simply copy the literal bytes (without | |
// attempting to align). | |
MOZ_MUST_USE bool writeFixedU8(uint8_t i) { | |
return write<uint8_t>(i); | |
} | |
MOZ_MUST_USE bool writeFixedU32(uint32_t i) { | |
return write<uint32_t>(i); | |
diff --git a/js/src/asmjs/WasmBinaryToText.cpp b/js/src/asmjs/WasmBinaryToText.cpp | |
--- a/js/src/asmjs/WasmBinaryToText.cpp | |
+++ b/js/src/asmjs/WasmBinaryToText.cpp | |
@@ -44,19 +44,20 @@ struct WasmRenderContext | |
uint32_t indent; | |
DeclaredSigVector signatures; | |
Uint32Vector funcSigs; | |
Uint32Vector funcLocals; | |
Uint32Vector importSigs; | |
uint32_t currentFuncIndex; | |
+ bool saveLocs; | |
WasmRenderContext(JSContext* cx, Decoder& d, StringBuffer& buffer) | |
- : cx(cx), d(d), buffer(buffer), indent(0), currentFuncIndex(0) | |
+ : cx(cx), d(d), buffer(buffer), indent(0), currentFuncIndex(0), saveLocs(true) | |
{} | |
}; | |
/*****************************************************************************/ | |
// utilities | |
static bool | |
RenderFail(WasmRenderContext& c, const char* str) | |
@@ -968,18 +969,37 @@ RenderSelect(WasmRenderContext& c) | |
if (!RenderExpr(c)) | |
return false; | |
return c.buffer.append(")"); | |
} | |
static bool | |
+RenderLoc(WasmRenderContext& c) | |
+{ | |
+ if (!c.buffer.append("(;!loc 1 1 ")) | |
+ return false; | |
+ | |
+ if (!RenderInt32(c, (uint32_t)c.d.currentOffset())) | |
+ return false; | |
+ | |
+ if (!c.buffer.append(";)")) | |
+ return false; | |
+ return true; | |
+} | |
+ | |
+static bool | |
RenderExpr(WasmRenderContext& c) | |
{ | |
+ if (c.saveLocs) { | |
+ if (!RenderLoc(c)) | |
+ return RenderFail(c, "unable to save annotation"); | |
+ } | |
+ | |
Expr expr; | |
if (!c.d.readExpr(&expr)) | |
return RenderFail(c, "unable to read expression"); | |
switch (expr) { | |
case Expr::Nop: | |
return RenderNop(c); | |
case Expr::Unreachable: | |
@@ -1626,16 +1646,25 @@ RenderFunctionBody(WasmRenderContext& c, | |
while (c.d.currentPosition() < bodyEnd) { | |
if (!RenderFullLine(c)) | |
return false; | |
} | |
if (c.d.currentPosition() != bodyEnd) | |
return RenderFail(c, "function body length mismatch"); | |
+ if (c.saveLocs) { | |
+ if (!RenderIndent(c)) | |
+ return false; | |
+ if (!RenderLoc(c)) | |
+ return RenderFail(c, "unable to save annotation"); | |
+ if (!c.buffer.append("\n")) | |
+ return false; | |
+ } | |
+ | |
c.indent--; | |
return true; | |
} | |
static bool | |
RenderCodeSection(WasmRenderContext& c) | |
{ | |
@@ -1643,16 +1672,23 @@ RenderCodeSection(WasmRenderContext& c) | |
if (!c.d.startSection(CodeSectionId, §ionStart, §ionSize)) | |
return RenderFail(c, "failed to start section"); | |
if (sectionStart == Decoder::NotStarted) | |
return true; | |
uint32_t numFuncSigs = c.funcSigs.length(); | |
+ if (c.saveLocs) { | |
+ if (!RenderIndent(c)) | |
+ return false; | |
+ if (!c.buffer.append("(;!file 1 \"file.wasm\";)\n")) | |
+ return false; | |
+ } | |
+ | |
uint32_t numFuncBodies; | |
if (!c.d.readVarU32(&numFuncBodies)) | |
return RenderFail(c, "expected function body count"); | |
if (numFuncBodies != numFuncSigs) | |
return RenderFail(c, "function body count does not match function signature count"); | |
for (uint32_t funcIndex = 0; funcIndex < numFuncBodies; funcIndex++) { | |
uint32_t sigIndex = c.funcSigs[funcIndex]; | |
const DeclaredSig& sig = c.signatures[sigIndex]; | |
diff --git a/js/src/asmjs/WasmTextToBinary.cpp b/js/src/asmjs/WasmTextToBinary.cpp | |
--- a/js/src/asmjs/WasmTextToBinary.cpp | |
+++ b/js/src/asmjs/WasmTextToBinary.cpp | |
@@ -185,17 +185,17 @@ class WasmAstSig : public WasmAstBase | |
return AddContainerToHash(sig.args(), HashNumber(sig.ret())); | |
} | |
static bool match(const WasmAstSig* lhs, Lookup rhs) { | |
return *lhs == rhs; | |
} | |
}; | |
class WasmAstNode : public WasmAstBase | |
-{}; | |
+{ }; | |
enum class WasmAstExprKind | |
{ | |
BinaryOperator, | |
Block, | |
Branch, | |
BranchTable, | |
Call, | |
@@ -210,33 +210,55 @@ enum class WasmAstExprKind | |
Return, | |
SetLocal, | |
Store, | |
TernaryOperator, | |
UnaryOperator, | |
Unreachable | |
}; | |
+struct WasmExprAnnotation { | |
+ uint32_t locAnnotationId; | |
+ uint32_t bookmarkAnnotationId; | |
+ | |
+ WasmExprAnnotation() : locAnnotationId(0), bookmarkAnnotationId(0) {} | |
+ WasmExprAnnotation(uint32_t locAnnotationId, uint32_t bookmarkAnnotationId) : locAnnotationId(locAnnotationId), bookmarkAnnotationId(bookmarkAnnotationId) {} | |
+ | |
+ bool operator==(WasmExprAnnotation rhs) const { | |
+ if (locAnnotationId != rhs.locAnnotationId) | |
+ return false; | |
+ if (bookmarkAnnotationId != rhs.bookmarkAnnotationId) | |
+ return false; | |
+ return true; | |
+ } | |
+ bool operator!=(WasmExprAnnotation rhs) const { | |
+ return !(*this == rhs); | |
+ } | |
+}; | |
+ | |
class WasmAstExpr : public WasmAstNode | |
{ | |
const WasmAstExprKind kind_; | |
protected: | |
explicit WasmAstExpr(WasmAstExprKind kind) | |
- : kind_(kind) | |
+ : kind_(kind), | |
+ annotation() | |
{} | |
public: | |
WasmAstExprKind kind() const { return kind_; } | |
template <class T> | |
T& as() { | |
MOZ_ASSERT(kind() == T::Kind); | |
return static_cast<T&>(*this); | |
} | |
+ | |
+ WasmExprAnnotation annotation; | |
}; | |
struct WasmAstNop : WasmAstExpr | |
{ | |
WasmAstNop() | |
: WasmAstExpr(WasmAstExprKind::Nop) | |
{} | |
}; | |
@@ -499,23 +521,28 @@ class WasmAstFunc : public WasmAstNode | |
public: | |
WasmAstFunc(WasmName name, WasmRef sig, WasmAstValTypeVector&& vars, | |
WasmNameVector&& locals, WasmAstExprVector&& body) | |
: name_(name), | |
sig_(sig), | |
vars_(Move(vars)), | |
localNames_(Move(locals)), | |
- body_(Move(body)) | |
+ body_(Move(body)), | |
+ annotationBegin(), | |
+ annotationEnd() | |
{} | |
WasmRef& sig() { return sig_; } | |
const WasmAstValTypeVector& vars() const { return vars_; } | |
const WasmNameVector& locals() const { return localNames_; } | |
const WasmAstExprVector& body() const { return body_; } | |
WasmName name() const { return name_; } | |
+ | |
+ WasmExprAnnotation annotationBegin; | |
+ WasmExprAnnotation annotationEnd; | |
}; | |
class WasmAstImport : public WasmAstNode | |
{ | |
WasmName name_; | |
WasmName module_; | |
WasmName func_; | |
uint32_t sigIndex_; | |
@@ -589,43 +616,57 @@ class WasmAstMemory : public WasmAstNode | |
maxSize_(maxSize), | |
segments_(Move(segments)) | |
{} | |
uint32_t initialSize() const { return initialSize_; } | |
const Maybe<uint32_t>& maxSize() const { return maxSize_; } | |
const WasmAstSegmentVector& segments() const { return segments_; } | |
}; | |
+struct WasmAstModuleDbgInfo { | |
+ WasmNameVector dbgTables; | |
+ WasmNameVector annotations; | |
+ WasmNameVector files; | |
+ | |
+ WasmAstModuleDbgInfo(LifoAlloc& lifo) | |
+ : dbgTables(lifo), | |
+ annotations(lifo), | |
+ files(lifo) | |
+ {} | |
+}; | |
+ | |
class WasmAstModule : public WasmAstNode | |
{ | |
typedef WasmAstVector<WasmAstFunc*> FuncVector; | |
typedef WasmAstVector<WasmAstImport*> ImportVector; | |
typedef WasmAstVector<WasmAstExport*> ExportVector; | |
typedef WasmAstVector<WasmAstSig*> SigVector; | |
typedef WasmAstHashMap<WasmAstSig*, uint32_t, WasmAstSig> SigMap; | |
LifoAlloc& lifo_; | |
WasmAstMemory* memory_; | |
SigVector sigs_; | |
SigMap sigMap_; | |
ImportVector imports_; | |
ExportVector exports_; | |
WasmAstTable* table_; | |
FuncVector funcs_; | |
+ WasmAstModuleDbgInfo dbgInfo_; | |
public: | |
explicit WasmAstModule(LifoAlloc& lifo) | |
: lifo_(lifo), | |
memory_(nullptr), | |
sigs_(lifo), | |
sigMap_(lifo), | |
imports_(lifo), | |
exports_(lifo), | |
table_(nullptr), | |
- funcs_(lifo) | |
+ funcs_(lifo), | |
+ dbgInfo_(lifo) | |
{} | |
bool init() { | |
return sigMap_.init(); | |
} | |
bool setMemory(WasmAstMemory* memory) { | |
if (memory_) | |
return false; | |
memory_ = memory; | |
@@ -669,16 +710,19 @@ class WasmAstModule : public WasmAstNode | |
return imports_.append(imp); | |
} | |
bool append(WasmAstExport* exp) { | |
return exports_.append(exp); | |
} | |
const ExportVector& exports() const { | |
return exports_; | |
} | |
+ WasmAstModuleDbgInfo& dbgInfo() { | |
+ return dbgInfo_; | |
+ } | |
bool initTable(WasmAstTable* table) { | |
if (table_) | |
return false; | |
table_ = table; | |
return true; | |
} | |
WasmAstTable* maybeTable() const { | |
return table_; | |
@@ -835,29 +879,34 @@ class WasmToken | |
SetLocal, | |
Store, | |
Table, | |
TernaryOpcode, | |
Text, | |
Type, | |
UnaryOpcode, | |
Unreachable, | |
- ValueType | |
+ ValueType, | |
+ Annotation | |
}; | |
private: | |
Kind kind_; | |
const char16_t* begin_; | |
const char16_t* end_; | |
union { | |
uint32_t index_; | |
uint64_t uint_; | |
int64_t sint_; | |
FloatLiteralKind floatLiteralKind_; | |
ValType valueType_; | |
Expr expr_; | |
+ struct { | |
+ const char16_t* begin; | |
+ const char16_t* end; | |
+ } annotationType_; | |
} u; | |
public: | |
explicit WasmToken() = default; | |
WasmToken(Kind kind, const char16_t* begin, const char16_t* end) | |
: kind_(kind), | |
begin_(begin), | |
end_(end) | |
{ | |
@@ -892,16 +941,27 @@ class WasmToken | |
const char16_t* begin, const char16_t* end) | |
: kind_(Float), | |
begin_(begin), | |
end_(end) | |
{ | |
MOZ_ASSERT(begin != end); | |
u.floatLiteralKind_ = floatLiteralKind; | |
} | |
+ explicit WasmToken(const char16_t* typeBegin, const char16_t* typeEnd, | |
+ const char16_t* begin, const char16_t* end) | |
+ : kind_(Annotation), | |
+ begin_(begin), | |
+ end_(end) | |
+ { | |
+ MOZ_ASSERT(typeBegin != typeEnd); | |
+ MOZ_ASSERT(begin != end); | |
+ u.annotationType_.begin = typeBegin; | |
+ u.annotationType_.end = typeEnd; | |
+ } | |
explicit WasmToken(Kind kind, ValType valueType, const char16_t* begin, const char16_t* end) | |
: kind_(kind), | |
begin_(begin), | |
end_(end) | |
{ | |
MOZ_ASSERT(begin != end); | |
MOZ_ASSERT(kind_ == ValueType || kind_ == Const); | |
u.valueType_ = valueType; | |
@@ -962,16 +1022,20 @@ class WasmToken | |
return u.valueType_; | |
} | |
Expr expr() const { | |
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode || | |
kind_ == ComparisonOpcode || kind_ == ConversionOpcode || | |
kind_ == Load || kind_ == Store); | |
return u.expr_; | |
} | |
+ WasmName annotationName() const { | |
+ MOZ_ASSERT(kind_ == Annotation); | |
+ return WasmName(u.annotationType_.begin, u.annotationType_.end - u.annotationType_.begin); | |
+ } | |
}; | |
} // end anonymous namespace | |
static bool | |
IsWasmNewLine(char16_t c) | |
{ | |
return c == '\n'; | |
@@ -1141,16 +1205,38 @@ ConsumeTextByte(const char16_t** curp, c | |
} | |
if (byte) | |
*byte = u8; | |
cur++; | |
return true; | |
} | |
+static bool | |
+ConsumeAnnotation(const char16_t** curp, const char16_t* end) | |
+{ | |
+ // Skipping similar to multi-line comment. | |
+ const char16_t* cur = *curp; | |
+ size_t level = 1; | |
+ while (cur != end) { | |
+ char16_t ch = *(cur++); | |
+ if (ch == '(' && cur != end && *cur == ';') { | |
+ cur++; | |
+ level++; | |
+ } else if (ch == ';' && cur != end && *cur == ')') { | |
+ cur++; | |
+ if (--level == 0) { | |
+ *curp = cur; | |
+ return true; | |
+ } | |
+ } | |
+ } | |
+ return false; | |
+} | |
+ | |
namespace { | |
class WasmTokenStream | |
{ | |
static const uint32_t LookaheadSize = 2; | |
const char16_t* cur_; | |
const char16_t* const end_; | |
@@ -1170,16 +1256,17 @@ class WasmTokenStream | |
return true; | |
} | |
WasmToken fail(const char16_t* begin) const { | |
return WasmToken(begin); | |
} | |
WasmToken nan(const char16_t* begin); | |
WasmToken literal(const char16_t* begin); | |
+ WasmToken annotation(const char16_t* begin, const char16_t* end); | |
WasmToken next(); | |
void skipSpaces(); | |
public: | |
WasmTokenStream(const char16_t* text, UniqueChars* error) | |
: cur_(text), | |
end_(text + js_strlen(text)), | |
lineStart_(text), | |
@@ -1350,26 +1437,47 @@ WasmTokenStream::literal(const char16_t* | |
CheckedInt<uint32_t> index = u.value(); | |
if (index.isValid()) | |
return WasmToken(index.value(), begin, cur_); | |
return WasmToken(u.value(), begin, cur_); | |
} | |
+WasmToken | |
+WasmTokenStream::annotation(const char16_t* begin, const char16_t* end) | |
+{ | |
+ MOZ_ASSERT(begin[0] == '(' && begin[1] == ';' && begin[2] == '!'); | |
+ begin += 3; | |
+ end -= 2; | |
+ MOZ_ASSERT(end[0] == ';' && end[1] == ')'); | |
+ const char16_t* cur = begin; | |
+ const char16_t* typeBegin = cur; | |
+ while (cur != end && !IsWasmSpace(*cur)) | |
+ cur++; | |
+ const char16_t* typeEnd = cur; | |
+ while (cur != end && IsWasmSpace(*cur)) | |
+ cur++; | |
+ return WasmToken(typeBegin, typeEnd, cur, end); | |
+} | |
+ | |
void | |
WasmTokenStream::skipSpaces() | |
{ | |
while (cur_ != end_) { | |
char16_t ch = *cur_; | |
if (ch == ';' && consume(MOZ_UTF16(";;"))) { | |
// Skipping single line comment. | |
while (cur_ != end_ && !IsWasmNewLine(*cur_)) | |
cur_++; | |
} else if (ch == '(' && consume(MOZ_UTF16("(;"))) { | |
+ if (*cur_ == '!') { | |
+ cur_ -= 2; // set position before "(;" | |
+ return; // and return | |
+ } | |
// Skipping multi-line and possibly nested comments. | |
size_t level = 1; | |
while (cur_ != end_) { | |
char16_t ch = *cur_; | |
if (ch == '(' && consume(MOZ_UTF16("(;"))) { | |
level++; | |
} else if (ch == ';' && consume(MOZ_UTF16(";)"))) { | |
if (--level == 0) | |
@@ -1418,16 +1526,21 @@ WasmTokenStream::next() | |
case '$': | |
cur_++; | |
while (cur_ != end_ && IsNameAfterDollar(*cur_)) | |
cur_++; | |
return WasmToken(WasmToken::Name, begin, cur_); | |
case '(': | |
+ if (consume(MOZ_UTF16("(;!"))) { | |
+ if (!ConsumeAnnotation(&cur_, end_)) | |
+ fail(begin); | |
+ return annotation(begin, cur_); | |
+ } | |
cur_++; | |
return WasmToken(WasmToken::OpenParen, begin, cur_); | |
case ')': | |
cur_++; | |
return WasmToken(WasmToken::CloseParen, begin, cur_); | |
case '=': | |
@@ -2050,53 +2163,97 @@ WasmTokenStream::next() | |
return fail(begin); | |
} | |
/*****************************************************************************/ | |
// wasm text format parser | |
namespace { | |
+struct WasmAnnotationState { | |
+ WasmExprAnnotation currentAnnotation; | |
+ WasmNameVector dbgTables; | |
+ WasmNameVector annotations; | |
+ WasmNameVector files; | |
+ | |
+ WasmAnnotationState(LifoAlloc& lifo) | |
+ : currentAnnotation(), | |
+ dbgTables(lifo), | |
+ annotations(lifo), | |
+ files(lifo) | |
+ {} | |
+}; | |
+ | |
struct WasmParseContext | |
{ | |
WasmTokenStream ts; | |
LifoAlloc& lifo; | |
UniqueChars* error; | |
DtoaState* dtoaState; | |
+ WasmAnnotationState annotationState; | |
WasmParseContext(const char16_t* text, LifoAlloc& lifo, UniqueChars* error) | |
: ts(text, error), | |
lifo(lifo), | |
error(error), | |
- dtoaState(NewDtoaState()) | |
+ dtoaState(NewDtoaState()), | |
+ annotationState(lifo) | |
{} | |
bool fail(const char* message) { | |
error->reset(JS_smprintf(message)); | |
return false; | |
} | |
~WasmParseContext() { | |
DestroyDtoaState(dtoaState); | |
} | |
}; | |
} // end anonymous namespace | |
static WasmAstExpr* | |
ParseExprInsideParens(WasmParseContext& c); | |
+static void | |
+ParseAnnotations(WasmParseContext& c) | |
+{ | |
+ WasmToken token; | |
+ while (c.ts.getIf(WasmToken::Annotation, &token)) { | |
+ const WasmName &name = token.annotationName(); | |
+ bool result; | |
+ if (name == WasmName(MOZ_UTF16("dbg_section"), 11)) { | |
+ result = c.annotationState.dbgTables.append(token.name()); | |
+ } else if (name == WasmName(MOZ_UTF16("loc"), 3)) { | |
+ result = c.annotationState.annotations.append(token.name()); | |
+ c.annotationState.currentAnnotation.locAnnotationId = | |
+ c.annotationState.annotations.length(); | |
+ } else if (name == WasmName(MOZ_UTF16("bookmark"), 8)) { | |
+ result = c.annotationState.annotations.append(token.name()); | |
+ c.annotationState.currentAnnotation.bookmarkAnnotationId = | |
+ c.annotationState.annotations.length(); | |
+ } else if (name == WasmName(MOZ_UTF16("file"), 4)) { | |
+ result = c.annotationState.files.append(token.name()); | |
+ } | |
+ } | |
+} | |
+ | |
static WasmAstExpr* | |
ParseExpr(WasmParseContext& c) | |
{ | |
+ ParseAnnotations(c); | |
+ | |
if (!c.ts.match(WasmToken::OpenParen, c.error)) | |
return nullptr; | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
WasmAstExpr* expr = ParseExprInsideParens(c); | |
if (!expr) | |
return nullptr; | |
+ expr->annotation = annotation; | |
+ c.annotationState.currentAnnotation = annotation; | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
return expr; | |
} | |
static WasmAstBlock* | |
@@ -2105,71 +2262,91 @@ ParseBlock(WasmParseContext& c, Expr exp | |
WasmAstExprVector exprs(c.lifo); | |
WasmName breakName = c.ts.getIfName(); | |
WasmName continueName; | |
if (expr == Expr::Loop) | |
continueName = c.ts.getIfName(); | |
+ ParseAnnotations(c); | |
while (c.ts.getIf(WasmToken::OpenParen)) { | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
WasmAstExpr* expr = ParseExprInsideParens(c); | |
if (!expr || !exprs.append(expr)) | |
return nullptr; | |
+ expr->annotation = annotation; | |
+ ParseAnnotations(c); | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} | |
return new(c.lifo) WasmAstBlock(expr, breakName, continueName, Move(exprs)); | |
} | |
static WasmAstBranch* | |
ParseBranch(WasmParseContext& c, Expr expr) | |
{ | |
MOZ_ASSERT(expr == Expr::Br || expr == Expr::BrIf); | |
WasmRef target; | |
if (!c.ts.matchRef(&target, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
+ | |
WasmAstExpr* value = nullptr; | |
if (c.ts.getIf(WasmToken::OpenParen)) { | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
value = ParseExprInsideParens(c); | |
if (!value) | |
return nullptr; | |
+ value->annotation = annotation; | |
+ ParseAnnotations(c); | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} | |
WasmAstExpr* cond = nullptr; | |
if (expr == Expr::BrIf) { | |
if (c.ts.getIf(WasmToken::OpenParen)) { | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
cond = ParseExprInsideParens(c); | |
if (!cond) | |
return nullptr; | |
+ cond->annotation = annotation; | |
+ ParseAnnotations(c); | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} else { | |
cond = value; | |
value = nullptr; | |
} | |
} | |
return new(c.lifo) WasmAstBranch(expr, cond, target, value); | |
} | |
static bool | |
ParseArgs(WasmParseContext& c, WasmAstExprVector* args) | |
{ | |
+ ParseAnnotations(c); | |
while (c.ts.getIf(WasmToken::OpenParen)) { | |
WasmAstExpr* arg = ParseExprInsideParens(c); | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
if (!arg || !args->append(arg)) | |
return false; | |
+ arg->annotation = annotation; | |
+ ParseAnnotations(c); | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return false; | |
+ ParseAnnotations(c); | |
} | |
return true; | |
} | |
static WasmAstCall* | |
ParseCall(WasmParseContext& c, Expr expr) | |
{ | |
@@ -2636,23 +2813,29 @@ ParseIf(WasmParseContext& c) | |
WasmAstExpr* cond = ParseExpr(c); | |
if (!cond) | |
return nullptr; | |
WasmAstExpr* thenBranch = ParseExpr(c); | |
if (!thenBranch) | |
return nullptr; | |
+ ParseAnnotations(c); | |
+ | |
WasmAstExpr* elseBranch = nullptr; | |
if (c.ts.getIf(WasmToken::OpenParen)) { | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
elseBranch = ParseExprInsideParens(c); | |
if (!elseBranch) | |
return nullptr; | |
+ elseBranch->annotation = annotation; | |
+ ParseAnnotations(c); | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} | |
return new(c.lifo) WasmAstIf(cond, thenBranch, elseBranch); | |
} | |
static bool | |
ParseLoadStoreAddress(WasmParseContext& c, int32_t* offset, uint32_t* alignLog2, WasmAstExpr** base) | |
{ | |
@@ -2932,23 +3115,28 @@ ParseFunc(WasmParseContext& c, WasmAstMo | |
WasmAstValTypeVector vars(c.lifo); | |
WasmAstValTypeVector args(c.lifo); | |
WasmNameVector locals(c.lifo); | |
WasmName funcName = c.ts.getIfName(); | |
WasmRef sig; | |
+ c.annotationState.currentAnnotation = WasmExprAnnotation(); | |
+ ParseAnnotations(c); | |
+ WasmExprAnnotation annotationBegin = c.annotationState.currentAnnotation; | |
+ | |
WasmToken openParen; | |
if (c.ts.getIf(WasmToken::OpenParen, &openParen)) { | |
if (c.ts.getIf(WasmToken::Type)) { | |
if (!c.ts.matchRef(&sig, c.error)) | |
return nullptr; | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} else { | |
c.ts.unget(openParen); | |
} | |
} | |
WasmAstExprVector body(c.lifo); | |
ExprType result = ExprType::Void; | |
@@ -2968,33 +3156,42 @@ ParseFunc(WasmParseContext& c, WasmAstMo | |
return nullptr; | |
break; | |
case WasmToken::Result: | |
if (!ParseResult(c, &result)) | |
return nullptr; | |
break; | |
default: | |
c.ts.unget(token); | |
+ WasmExprAnnotation annotation = c.annotationState.currentAnnotation; | |
WasmAstExpr* expr = ParseExprInsideParens(c); | |
if (!expr || !body.append(expr)) | |
return nullptr; | |
+ expr->annotation = annotation; | |
+ c.annotationState.currentAnnotation = annotation; | |
break; | |
} | |
+ ParseAnnotations(c); | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} | |
if (sig.isInvalid()) { | |
uint32_t sigIndex; | |
if (!module->declare(WasmAstSig(Move(args), result), &sigIndex)) | |
return nullptr; | |
sig.setIndex(sigIndex); | |
} | |
- return new(c.lifo) WasmAstFunc(funcName, sig, Move(vars), Move(locals), Move(body)); | |
+ WasmAstFunc* f = | |
+ new(c.lifo) WasmAstFunc(funcName, sig, Move(vars), Move(locals), Move(body)); | |
+ f->annotationBegin = annotationBegin; | |
+ f->annotationEnd = c.annotationState.currentAnnotation; | |
+ return f; | |
} | |
static bool | |
ParseFuncType(WasmParseContext& c, WasmAstSig* sig) | |
{ | |
WasmAstValTypeVector args(c.lifo); | |
ExprType result = ExprType::Void; | |
@@ -3157,16 +3354,18 @@ ParseModule(const char16_t* text, LifoAl | |
return nullptr; | |
if (!c.ts.match(WasmToken::Module, c.error)) | |
return nullptr; | |
auto module = new(c.lifo) WasmAstModule(c.lifo); | |
if (!module || !module->init()) | |
return nullptr; | |
+ ParseAnnotations(c); | |
+ | |
while (c.ts.getIf(WasmToken::OpenParen)) { | |
WasmToken section = c.ts.get(); | |
switch (section.kind()) { | |
case WasmToken::Type: { | |
WasmAstSig* sig = ParseTypeDef(c); | |
if (!sig || !module->append(sig)) | |
return nullptr; | |
@@ -3212,23 +3411,29 @@ ParseModule(const char16_t* text, LifoAl | |
} | |
default: | |
c.ts.generateError(section, c.error); | |
return nullptr; | |
} | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
+ ParseAnnotations(c); | |
} | |
if (!c.ts.match(WasmToken::CloseParen, c.error)) | |
return nullptr; | |
if (!c.ts.match(WasmToken::EndOfFile, c.error)) | |
return nullptr; | |
+ WasmAstModuleDbgInfo& dbgInfo = module->dbgInfo(); | |
+ dbgInfo.dbgTables.swap(c.annotationState.dbgTables); | |
+ dbgInfo.annotations.swap(c.annotationState.annotations); | |
+ dbgInfo.files.swap(c.annotationState.files); | |
+ | |
return module; | |
} | |
/*****************************************************************************/ | |
// wasm name resolution | |
namespace { | |
@@ -3662,268 +3867,401 @@ ResolveModule(LifoAlloc& lifo, WasmAstMo | |
} | |
return true; | |
} | |
/*****************************************************************************/ | |
// wasm function body serialization | |
+typedef Vector<char16_t, 0, SystemAllocPolicy> WasmCharsVector; | |
+ | |
+class CodeAnnotationWriter | |
+{ | |
+ WasmCharsVector chars; | |
+ const WasmNameVector& annotations_; | |
+ const WasmNameVector& files_; | |
+ WasmExprAnnotation currentAnnotation_; | |
+ uint32_t baseOffset_; | |
+ | |
+public: | |
+ CodeAnnotationWriter(const WasmNameVector& annotations, const WasmNameVector& files) | |
+ : chars(), | |
+ annotations_(annotations), | |
+ files_(files), | |
+ currentAnnotation_(), | |
+ baseOffset_(0) | |
+ { } | |
+ | |
+ bool initialize() | |
+ { | |
+ if (!writeName(WasmName(MOZ_UTF16(".code_annotations\n"), 18))) | |
+ return false; | |
+ size_t numFiles = files_.length(); | |
+ for (size_t i = 0; i < numFiles; i++) { | |
+ bool result = writeName(WasmName(MOZ_UTF16(" .file "), 10)) && | |
+ writeName(files_[i]) && | |
+ writeName(WasmName(MOZ_UTF16("\n"), 1)); | |
+ if (!result) | |
+ return false; | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ bool writeFunctionBegin(const WasmExprAnnotation& annotationBegin, uint32_t offset) | |
+ { | |
+ currentAnnotation_ = WasmExprAnnotation(); | |
+ baseOffset_ = offset; | |
+ writeOffset(annotationBegin, offset); | |
+ return writeName(WasmName(MOZ_UTF16(" .function"), 13)); | |
+ } | |
+ | |
+ bool writeFunctionEnd(const WasmExprAnnotation& annotationEnd, uint32_t offset) | |
+ { | |
+ writeOffset(annotationEnd, offset); | |
+ return writeName(WasmName(MOZ_UTF16("\n"), 1)); | |
+ } | |
+ | |
+ bool writeOffset(const WasmExprAnnotation &annotation, uint32_t offset) | |
+ { | |
+ if (annotation == currentAnnotation_) | |
+ return true; // no need | |
+ | |
+ if (!writeAnnotation(annotation)) | |
+ return false; | |
+ | |
+ MOZ_ASSERT(baseOffset_ <= offset); | |
+ uint32_t n = offset - baseOffset_; | |
+ return chars.append(MOZ_UTF16(' ')) && writeNumber(n); | |
+ } | |
+ | |
+ bool writeNumber(uint32_t value) | |
+ { | |
+ uint32_t tmp = value; | |
+ do { | |
+ if (!chars.append(MOZ_UTF16('0'))) | |
+ return false; | |
+ tmp /= 10; | |
+ } while (tmp); | |
+ | |
+ char16_t *p = chars.end(); | |
+ tmp = value; | |
+ while (tmp) { | |
+ *(--p) = MOZ_UTF16('0') + (tmp % 10); | |
+ tmp /= 10; | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ bool writeAnnotation(const WasmExprAnnotation &annotation) | |
+ { | |
+ if (annotation.locAnnotationId != currentAnnotation_.locAnnotationId && | |
+ (annotation.locAnnotationId == 0 || currentAnnotation_.locAnnotationId == 0 || | |
+ annotations_[annotation.locAnnotationId - 1] != annotations_[currentAnnotation_.locAnnotationId - 1])) { | |
+ bool result = chars.append(MOZ_UTF16(" loc("), 5) && | |
+ (annotation.locAnnotationId > 0 ? writeName(annotations_[annotation.locAnnotationId - 1]) : true) && | |
+ chars.append(MOZ_UTF16(')')); | |
+ if (!result) | |
+ return false; | |
+ } | |
+ if (annotation.bookmarkAnnotationId != currentAnnotation_.bookmarkAnnotationId && | |
+ (annotation.bookmarkAnnotationId == 0 || currentAnnotation_.bookmarkAnnotationId == 0 || | |
+ annotations_[annotation.bookmarkAnnotationId - 1] != annotations_[currentAnnotation_.bookmarkAnnotationId - 1])) { | |
+ bool result = chars.append(MOZ_UTF16(" b("), 3) && | |
+ (annotation.bookmarkAnnotationId > 0 ? writeName(annotations_[annotation.bookmarkAnnotationId - 1]) : true) && | |
+ chars.append(MOZ_UTF16(')')); | |
+ if (!result) | |
+ return false; | |
+ } | |
+ currentAnnotation_ = annotation; | |
+ return true; | |
+ } | |
+ | |
+ bool writeName(const WasmName &wasmName) | |
+ { | |
+ return chars.append(wasmName.begin(), wasmName.end()); | |
+ } | |
+ | |
+ WasmName finalize() | |
+ { | |
+ return WasmName(chars.begin(), chars.length()); | |
+ } | |
+}; | |
+ | |
+ | |
+class EncoderWithAnnotation : public Encoder | |
+{ | |
+ public: | |
+ CodeAnnotationWriter& cw; | |
+ | |
+ EncoderWithAnnotation(Bytes& bytes, CodeAnnotationWriter& cw) | |
+ : Encoder(bytes), cw(cw) | |
+ { } | |
+ | |
+ MOZ_MUST_USE bool writeExprAndAnnotation(Expr expr, const WasmExprAnnotation& annotation) | |
+ { | |
+ if (!cw.writeOffset(annotation, currentOffset())) | |
+ return false; | |
+ return Encoder::writeExpr(expr); | |
+ } | |
+}; | |
+ | |
+ | |
static bool | |
-EncodeExpr(Encoder& e, WasmAstExpr& expr); | |
+EncodeExpr(EncoderWithAnnotation& e, WasmAstExpr& expr); | |
static bool | |
-EncodeBlock(Encoder& e, WasmAstBlock& b) | |
+EncodeBlock(EncoderWithAnnotation& e, WasmAstBlock& b) | |
{ | |
- if (!e.writeExpr(b.expr())) | |
+ if (!e.writeExprAndAnnotation(b.expr(), b.annotation)) | |
return false; | |
size_t numExprs = b.exprs().length(); | |
for (size_t i = 0; i < numExprs; i++) { | |
if (!EncodeExpr(e, *b.exprs()[i])) | |
return false; | |
} | |
if (!e.writeExpr(Expr::End)) | |
return false; | |
return true; | |
} | |
static bool | |
-EncodeBranch(Encoder& e, WasmAstBranch& br) | |
+EncodeBranch(EncoderWithAnnotation& e, WasmAstBranch& br) | |
{ | |
MOZ_ASSERT(br.expr() == Expr::Br || br.expr() == Expr::BrIf); | |
uint32_t arity = 0; | |
if (br.maybeValue()) { | |
arity = 1; | |
if (!EncodeExpr(e, *br.maybeValue())) | |
return false; | |
} | |
if (br.expr() == Expr::BrIf) { | |
if (!EncodeExpr(e, br.cond())) | |
return false; | |
} | |
- if (!e.writeExpr(br.expr())) | |
+ if (!e.writeExprAndAnnotation(br.expr(), br.annotation)) | |
return false; | |
if (!e.writeVarU32(arity)) | |
return false; | |
if (!e.writeVarU32(br.target().index())) | |
return false; | |
return true; | |
} | |
static bool | |
-EncodeArgs(Encoder& e, const WasmAstExprVector& args) | |
+EncodeArgs(EncoderWithAnnotation& e, const WasmAstExprVector& args) | |
{ | |
for (WasmAstExpr* arg : args) { | |
if (!EncodeExpr(e, *arg)) | |
return false; | |
} | |
return true; | |
} | |
static bool | |
-EncodeCall(Encoder& e, WasmAstCall& c) | |
+EncodeCall(EncoderWithAnnotation& e, WasmAstCall& c) | |
{ | |
if (!EncodeArgs(e, c.args())) | |
return false; | |
- if (!e.writeExpr(c.expr())) | |
+ if (!e.writeExprAndAnnotation(c.expr(), c.annotation)) | |
return false; | |
if (!e.writeVarU32(c.args().length())) | |
return false; | |
if (!e.writeVarU32(c.func().index())) | |
return false; | |
return true; | |
} | |
static bool | |
-EncodeCallIndirect(Encoder& e, WasmAstCallIndirect& c) | |
+EncodeCallIndirect(EncoderWithAnnotation& e, WasmAstCallIndirect& c) | |
{ | |
if (!EncodeExpr(e, *c.index())) | |
return false; | |
if (!EncodeArgs(e, c.args())) | |
return false; | |
- if (!e.writeExpr(Expr::CallIndirect)) | |
+ if (!e.writeExprAndAnnotation(Expr::CallIndirect, c.annotation)) | |
return false; | |
if (!e.writeVarU32(c.args().length())) | |
return false; | |
if (!e.writeVarU32(c.sig().index())) | |
return false; | |
return true; | |
} | |
static bool | |
-EncodeConst(Encoder& e, WasmAstConst& c) | |
+EncodeConst(EncoderWithAnnotation& e, WasmAstConst& c) | |
{ | |
switch (c.val().type()) { | |
case ValType::I32: | |
- return e.writeExpr(Expr::I32Const) && | |
+ return e.writeExprAndAnnotation(Expr::I32Const, c.annotation) && | |
e.writeVarS32(c.val().i32()); | |
case ValType::I64: | |
- return e.writeExpr(Expr::I64Const) && | |
+ return e.writeExprAndAnnotation(Expr::I64Const, c.annotation) && | |
e.writeVarS64(c.val().i64()); | |
case ValType::F32: | |
- return e.writeExpr(Expr::F32Const) && | |
+ return e.writeExprAndAnnotation(Expr::F32Const, c.annotation) && | |
e.writeFixedF32(c.val().f32()); | |
case ValType::F64: | |
- return e.writeExpr(Expr::F64Const) && | |
+ return e.writeExprAndAnnotation(Expr::F64Const, c.annotation) && | |
e.writeFixedF64(c.val().f64()); | |
default: | |
break; | |
} | |
MOZ_CRASH("Bad value type"); | |
} | |
static bool | |
-EncodeGetLocal(Encoder& e, WasmAstGetLocal& gl) | |
+EncodeGetLocal(EncoderWithAnnotation& e, WasmAstGetLocal& gl) | |
{ | |
- return e.writeExpr(Expr::GetLocal) && | |
+ return e.writeExprAndAnnotation(Expr::GetLocal, gl.annotation) && | |
e.writeVarU32(gl.local().index()); | |
} | |
static bool | |
-EncodeSetLocal(Encoder& e, WasmAstSetLocal& sl) | |
+EncodeSetLocal(EncoderWithAnnotation& e, WasmAstSetLocal& sl) | |
{ | |
return EncodeExpr(e, sl.value()) && | |
- e.writeExpr(Expr::SetLocal) && | |
+ e.writeExprAndAnnotation(Expr::SetLocal, sl.annotation) && | |
e.writeVarU32(sl.local().index()); | |
} | |
static bool | |
-EncodeUnaryOperator(Encoder& e, WasmAstUnaryOperator& b) | |
+EncodeUnaryOperator(EncoderWithAnnotation& e, WasmAstUnaryOperator& b) | |
{ | |
return EncodeExpr(e, *b.op()) && | |
- e.writeExpr(b.expr()); | |
+ e.writeExprAndAnnotation(b.expr(), b.annotation); | |
} | |
static bool | |
-EncodeBinaryOperator(Encoder& e, WasmAstBinaryOperator& b) | |
+EncodeBinaryOperator(EncoderWithAnnotation& e, WasmAstBinaryOperator& b) | |
{ | |
return EncodeExpr(e, *b.lhs()) && | |
EncodeExpr(e, *b.rhs()) && | |
- e.writeExpr(b.expr()); | |
+ e.writeExprAndAnnotation(b.expr(), b.annotation); | |
} | |
static bool | |
-EncodeTernaryOperator(Encoder& e, WasmAstTernaryOperator& b) | |
+EncodeTernaryOperator(EncoderWithAnnotation& e, WasmAstTernaryOperator& b) | |
{ | |
return EncodeExpr(e, *b.op0()) && | |
EncodeExpr(e, *b.op1()) && | |
EncodeExpr(e, *b.op2()) && | |
- e.writeExpr(b.expr()); | |
+ e.writeExprAndAnnotation(b.expr(), b.annotation); | |
} | |
static bool | |
-EncodeComparisonOperator(Encoder& e, WasmAstComparisonOperator& b) | |
+EncodeComparisonOperator(EncoderWithAnnotation& e, WasmAstComparisonOperator& b) | |
{ | |
return EncodeExpr(e, *b.lhs()) && | |
EncodeExpr(e, *b.rhs()) && | |
- e.writeExpr(b.expr()); | |
+ e.writeExprAndAnnotation(b.expr(), b.annotation); | |
} | |
static bool | |
-EncodeConversionOperator(Encoder& e, WasmAstConversionOperator& b) | |
+EncodeConversionOperator(EncoderWithAnnotation& e, WasmAstConversionOperator& b) | |
{ | |
return EncodeExpr(e, *b.op()) && | |
- e.writeExpr(b.expr()); | |
+ e.writeExprAndAnnotation(b.expr(), b.annotation); | |
} | |
static bool | |
-EmitIf(Encoder& e, WasmAstIf& i) | |
+EmitIf(EncoderWithAnnotation& e, WasmAstIf& i) | |
{ | |
return EncodeExpr(e, i.cond()) && | |
- e.writeExpr(Expr::If) && | |
+ e.writeExprAndAnnotation(Expr::If, i.annotation) && | |
EncodeExpr(e, i.thenBranch()) && | |
(!i.hasElse() || | |
(e.writeExpr(Expr::Else) && | |
EncodeExpr(e, i.elseBranch()))) && | |
e.writeExpr(Expr::End); | |
} | |
static bool | |
-EncodeLoadStoreAddress(Encoder &e, const WasmAstLoadStoreAddress &address) | |
+EncodeLoadStoreAddress(EncoderWithAnnotation &e, const WasmAstLoadStoreAddress &address) | |
{ | |
return EncodeExpr(e, address.base()); | |
} | |
static bool | |
-EncodeLoadStoreFlags(Encoder &e, const WasmAstLoadStoreAddress &address) | |
+EncodeLoadStoreFlags(EncoderWithAnnotation &e, const WasmAstLoadStoreAddress &address) | |
{ | |
return e.writeVarU32(address.flags()) && | |
e.writeVarU32(address.offset()); | |
} | |
static bool | |
-EncodeLoad(Encoder& e, WasmAstLoad& l) | |
+EncodeLoad(EncoderWithAnnotation& e, WasmAstLoad& l) | |
{ | |
return EncodeLoadStoreAddress(e, l.address()) && | |
- e.writeExpr(l.expr()) && | |
+ e.writeExprAndAnnotation(l.expr(), l.annotation) && | |
EncodeLoadStoreFlags(e, l.address()); | |
} | |
static bool | |
-EncodeStore(Encoder& e, WasmAstStore& s) | |
+EncodeStore(EncoderWithAnnotation& e, WasmAstStore& s) | |
{ | |
return EncodeLoadStoreAddress(e, s.address()) && | |
EncodeExpr(e, s.value()) && | |
- e.writeExpr(s.expr()) && | |
+ e.writeExprAndAnnotation(s.expr(), s.annotation) && | |
EncodeLoadStoreFlags(e, s.address()); | |
} | |
static bool | |
-EncodeReturn(Encoder& e, WasmAstReturn& r) | |
+EncodeReturn(EncoderWithAnnotation& e, WasmAstReturn& r) | |
{ | |
uint32_t arity = 0; | |
if (r.maybeExpr()) { | |
arity = 1; | |
if (!EncodeExpr(e, *r.maybeExpr())) | |
return false; | |
} | |
- if (!e.writeExpr(Expr::Return)) | |
+ if (!e.writeExprAndAnnotation(Expr::Return, r.annotation)) | |
return false; | |
if (!e.writeVarU32(arity)) | |
return false; | |
return true; | |
} | |
static bool | |
-EncodeBranchTable(Encoder& e, WasmAstBranchTable& bt) | |
+EncodeBranchTable(EncoderWithAnnotation& e, WasmAstBranchTable& bt) | |
{ | |
uint32_t arity = 0; | |
if (bt.maybeValue()) { | |
arity = 1; | |
if (!EncodeExpr(e, *bt.maybeValue())) | |
return false; | |
} | |
if (!EncodeExpr(e, bt.index())) | |
return false; | |
- if (!e.writeExpr(Expr::BrTable)) | |
+ if (!e.writeExprAndAnnotation(Expr::BrTable, bt.annotation)) | |
return false; | |
if (!e.writeVarU32(arity)) | |
return false; | |
if (!e.writeVarU32(bt.table().length())) | |
return false; | |
@@ -3934,23 +4272,23 @@ EncodeBranchTable(Encoder& e, WasmAstBra | |
if (!e.writeFixedU32(bt.def().index())) | |
return false; | |
return true; | |
} | |
static bool | |
-EncodeExpr(Encoder& e, WasmAstExpr& expr) | |
+EncodeExpr(EncoderWithAnnotation& e, WasmAstExpr& expr) | |
{ | |
switch (expr.kind()) { | |
case WasmAstExprKind::Nop: | |
- return e.writeExpr(Expr::Nop); | |
+ return e.writeExprAndAnnotation(Expr::Nop, expr.annotation); | |
case WasmAstExprKind::Unreachable: | |
- return e.writeExpr(Expr::Unreachable); | |
+ return e.writeExprAndAnnotation(Expr::Unreachable, expr.annotation); | |
case WasmAstExprKind::BinaryOperator: | |
return EncodeBinaryOperator(e, expr.as<WasmAstBinaryOperator>()); | |
case WasmAstExprKind::Block: | |
return EncodeBlock(e, expr.as<WasmAstBlock>()); | |
case WasmAstExprKind::Branch: | |
return EncodeBranch(e, expr.as<WasmAstBranch>()); | |
case WasmAstExprKind::Call: | |
return EncodeCall(e, expr.as<WasmAstCall>()); | |
@@ -4190,41 +4528,47 @@ EncodeTableSection(Encoder& e, WasmAstMo | |
return false; | |
} | |
e.finishSection(offset); | |
return true; | |
} | |
static bool | |
-EncodeFunctionBody(Encoder& e, WasmAstFunc& func) | |
+EncodeFunctionBody(EncoderWithAnnotation& e, WasmAstFunc& func) | |
{ | |
size_t bodySizeAt; | |
if (!e.writePatchableVarU32(&bodySizeAt)) | |
return false; | |
size_t beforeBody = e.currentOffset(); | |
+ if (!e.cw.writeFunctionBegin(func.annotationBegin, e.currentOffset())) | |
+ return false; | |
+ | |
ValTypeVector varTypes; | |
if (!varTypes.appendAll(func.vars())) | |
return false; | |
if (!EncodeLocalEntries(e, varTypes)) | |
return false; | |
for (WasmAstExpr* expr : func.body()) { | |
if (!EncodeExpr(e, *expr)) | |
return false; | |
} | |
+ if (!e.cw.writeFunctionEnd(func.annotationEnd, e.currentOffset())) | |
+ return false; | |
+ | |
e.patchVarU32(bodySizeAt, e.currentOffset() - beforeBody); | |
return true; | |
} | |
static bool | |
-EncodeCodeSection(Encoder& e, WasmAstModule& module) | |
+EncodeCodeSection(EncoderWithAnnotation& e, WasmAstModule& module) | |
{ | |
if (module.funcs().empty()) | |
return true; | |
size_t offset; | |
if (!e.startSection(CodeSectionId, &offset)) | |
return false; | |
@@ -4286,19 +4630,49 @@ EncodeDataSection(Encoder& e, WasmAstMod | |
return false; | |
} | |
e.finishSection(offset); | |
return true; | |
} | |
static bool | |
+EncodeDbgTables(Encoder& e, WasmAstModule& module, CodeAnnotationWriter &cw) | |
+{ | |
+ if (module.dbgInfo().dbgTables.empty() && module.dbgInfo().files.empty()) | |
+ return true; | |
+ | |
+ size_t offset; | |
+ if (!e.startSection(DbgTablesId, &offset)) | |
+ return false; | |
+ | |
+ if (!e.writeVarU32(module.dbgInfo().dbgTables.length() + 1)) | |
+ return false; | |
+ | |
+ WasmName annotationsTable = cw.finalize(); | |
+ if (!EncodeBytes(e, annotationsTable)) | |
+ return false; | |
+ | |
+ for (WasmName dbgTable : module.dbgInfo().dbgTables) { | |
+ if (!EncodeBytes(e, dbgTable)) | |
+ return false; | |
+ } | |
+ | |
+ e.finishSection(offset); | |
+ return true; | |
+} | |
+ | |
+static bool | |
EncodeModule(WasmAstModule& module, Bytes* bytes) | |
{ | |
- Encoder e(*bytes); | |
+ CodeAnnotationWriter cw(module.dbgInfo().annotations, module.dbgInfo().files); | |
+ if (!cw.initialize()) | |
+ return false; | |
+ | |
+ EncoderWithAnnotation e(*bytes, cw); | |
if (!e.writeFixedU32(MagicNumber)) | |
return false; | |
if (!e.writeFixedU32(EncodingVersion)) | |
return false; | |
if (!EncodeTypeSection(e, module)) | |
@@ -4320,16 +4694,19 @@ EncodeModule(WasmAstModule& module, Byte | |
return false; | |
if (!EncodeCodeSection(e, module)) | |
return false; | |
if (!EncodeDataSection(e, module)) | |
return false; | |
+ if (!EncodeDbgTables(e, module, cw)) | |
+ return false; | |
+ | |
return true; | |
} | |
/*****************************************************************************/ | |
bool | |
wasm::TextToBinary(const char16_t* text, Bytes* bytes, UniqueChars* error) | |
{ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment