Skip to content

Commit 53f8d5f

Browse files
authored
[Parser] Support prologue and epilogue sourcemap annotations (#6370)
and fix a bug with sourcemap annotations on folded `if` conditions. Update IRBuilder to apply prologue and epilogue source locations when beginning and ending a function scope. Add basic support in the parser for explicitly tracking annotations on module fields, although only do anything with them in the case of prologue source location annotations.
1 parent e6cd456 commit 53f8d5f

File tree

7 files changed

+91
-33
lines changed

7 files changed

+91
-33
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ full changeset diff at the end of each section.
1515
Current Trunk
1616
-------------
1717

18+
- (If new wat parser is enabled) Source map comments on `else` branches must
19+
now be placed above the instruction inside the `else` branch rather than on
20+
the `else` branch itself.
21+
1822
v117
1923
----
2024

src/parser/context-decls.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,14 @@ Result<> ParseDeclsCtx::addFunc(Name name,
6868
ImportNames* import,
6969
TypeUseT type,
7070
std::optional<LocalsT>,
71+
std::vector<Annotation>&& annotations,
7172
Index pos) {
7273
CHECK_ERR(checkImport(pos, import));
7374
auto f = addFuncDecl(pos, name, import);
7475
CHECK_ERR(f);
7576
CHECK_ERR(addExports(in, wasm, *f, exports, ExternalKind::Function));
76-
funcDefs.push_back({name, pos, Index(funcDefs.size())});
77+
funcDefs.push_back(
78+
{name, pos, Index(funcDefs.size()), std::move(annotations)});
7779
return Ok{};
7880
}
7981

@@ -109,7 +111,8 @@ Result<> ParseDeclsCtx::addTable(Name name,
109111
auto t = addTableDecl(pos, name, import, limits);
110112
CHECK_ERR(t);
111113
CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Table));
112-
tableDefs.push_back({name, pos, Index(tableDefs.size())});
114+
// TODO: table annotations
115+
tableDefs.push_back({name, pos, Index(tableDefs.size()), {}});
113116
return Ok{};
114117
}
115118

@@ -164,7 +167,8 @@ Result<> ParseDeclsCtx::addMemory(Name name,
164167
auto m = addMemoryDecl(pos, name, import, type);
165168
CHECK_ERR(m);
166169
CHECK_ERR(addExports(in, wasm, *m, exports, ExternalKind::Memory));
167-
memoryDefs.push_back({name, pos, Index(memoryDefs.size())});
170+
// TODO: memory annotations
171+
memoryDefs.push_back({name, pos, Index(memoryDefs.size()), {}});
168172
return Ok{};
169173
}
170174

@@ -209,7 +213,8 @@ Result<> ParseDeclsCtx::addGlobal(Name name,
209213
auto g = addGlobalDecl(pos, name, import);
210214
CHECK_ERR(g);
211215
CHECK_ERR(addExports(in, wasm, *g, exports, ExternalKind::Global));
212-
globalDefs.push_back({name, pos, Index(globalDefs.size())});
216+
// TODO: global annotations
217+
globalDefs.push_back({name, pos, Index(globalDefs.size()), {}});
213218
return Ok{};
214219
}
215220

@@ -228,7 +233,8 @@ Result<> ParseDeclsCtx::addElem(
228233
name = Names::getValidElementSegmentName(wasm, name);
229234
e->name = name;
230235
}
231-
elemDefs.push_back({name, pos, Index(wasm.elementSegments.size())});
236+
// TODO: element segment annotations
237+
elemDefs.push_back({name, pos, Index(wasm.elementSegments.size()), {}});
232238
wasm.addElementSegment(std::move(e));
233239
return Ok{};
234240
}
@@ -252,7 +258,8 @@ Result<> ParseDeclsCtx::addData(Name name,
252258
d->name = name;
253259
}
254260
d->data = std::move(data);
255-
dataDefs.push_back({name, pos, Index(wasm.dataSegments.size())});
261+
// TODO: data segment annotations
262+
dataDefs.push_back({name, pos, Index(wasm.dataSegments.size()), {}});
256263
wasm.addDataSegment(std::move(d));
257264
return Ok{};
258265
}
@@ -285,7 +292,8 @@ Result<> ParseDeclsCtx::addTag(Name name,
285292
auto t = addTagDecl(pos, name, import);
286293
CHECK_ERR(t);
287294
CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Tag));
288-
tagDefs.push_back({name, pos, Index(tagDefs.size())});
295+
// TODO: tag annotations
296+
tagDefs.push_back({name, pos, Index(tagDefs.size()), {}});
289297
return Ok{};
290298
}
291299

src/parser/contexts.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct DefPos {
6161
Name name;
6262
Index pos;
6363
Index index;
64+
std::vector<Annotation> annotations;
6465
};
6566

6667
struct GlobalType {
@@ -406,7 +407,7 @@ struct NullInstrParserCtx {
406407
TagLabelListT makeTagLabelList() { return Ok{}; }
407408
void appendTagLabel(TagLabelListT&, TagIdxT, LabelIdxT) {}
408409

409-
void setSrcLoc(const Annotation&) {}
410+
void setSrcLoc(const std::vector<Annotation>&) {}
410411

411412
Result<> makeUnreachable(Index, const std::vector<Annotation>&) {
412413
return Ok{};
@@ -908,12 +909,14 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
908909
void setOpen() {}
909910
Result<> addSubtype(Index) { return Ok{}; }
910911
void finishSubtype(Name name, Index pos) {
911-
subtypeDefs.push_back({name, pos, Index(subtypeDefs.size())});
912+
// TODO: type annotations
913+
subtypeDefs.push_back({name, pos, Index(subtypeDefs.size()), {}});
912914
}
913915
size_t getRecGroupStartIndex() { return 0; }
914916
void addRecGroup(Index, size_t) {}
915917
void finishDeftype(Index pos) {
916-
typeDefs.push_back({{}, pos, Index(typeDefs.size())});
918+
// TODO: type annotations
919+
typeDefs.push_back({{}, pos, Index(typeDefs.size()), {}});
917920
}
918921

919922
Limits makeLimits(uint64_t n, std::optional<uint64_t> m) {
@@ -957,6 +960,7 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
957960
ImportNames* import,
958961
TypeUseT type,
959962
std::optional<LocalsT>,
963+
std::vector<Annotation>&&,
960964
Index pos);
961965

962966
Result<Table*>
@@ -991,7 +995,8 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
991995
if (!startDefs.empty()) {
992996
return Err{"unexpected extra 'start' function"};
993997
}
994-
startDefs.push_back({{}, pos, 0});
998+
// TODO: start function annotations.
999+
startDefs.push_back({{}, pos, 0, {}});
9951000
return Ok{};
9961001
}
9971002

@@ -1245,6 +1250,7 @@ struct ParseModuleTypesCtx : TypeParserCtx<ParseModuleTypesCtx>,
12451250
ImportNames*,
12461251
TypeUse type,
12471252
std::optional<LocalsT> locals,
1253+
std::vector<Annotation>&&,
12481254
Index pos) {
12491255
auto& f = wasm.functions[index];
12501256
if (!type.type.isSignature()) {
@@ -1606,6 +1612,7 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
16061612
ImportNames*,
16071613
TypeUseT,
16081614
std::optional<LocalsT>,
1615+
std::vector<Annotation>&&,
16091616
Index) {
16101617
return Ok{};
16111618
}
@@ -1692,9 +1699,17 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
16921699
return wasm.memories[0]->name;
16931700
}
16941701

1695-
void setSrcLoc(const Annotation& annotation) {
1696-
assert(annotation.kind == srcAnnotationKind);
1697-
Lexer lexer(annotation.contents);
1702+
void setSrcLoc(const std::vector<Annotation>& annotations) {
1703+
const Annotation* annotation = nullptr;
1704+
for (auto& a : annotations) {
1705+
if (a.kind == srcAnnotationKind) {
1706+
annotation = &a;
1707+
}
1708+
}
1709+
if (!annotation) {
1710+
return;
1711+
}
1712+
Lexer lexer(annotation->contents);
16981713
auto contents = lexer.takeKeyword();
16991714
if (!contents || !lexer.empty()) {
17001715
return;

src/parser/parsers.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -844,20 +844,11 @@ template<typename Ctx> Result<uint32_t> tupleArity(Ctx& ctx) {
844844
// Instructions
845845
// ============
846846

847-
template<typename Ctx>
848-
void setSrcLoc(Ctx& ctx, const std::vector<Annotation>& annotations) {
849-
for (const auto& annotation : annotations) {
850-
if (annotation.kind == srcAnnotationKind) {
851-
ctx.setSrcLoc(annotation);
852-
}
853-
}
854-
}
855-
856847
// blockinstr ::= block | loop | if-else | try-catch | try_table
857848
template<typename Ctx>
858849
MaybeResult<> foldedBlockinstr(Ctx& ctx,
859850
const std::vector<Annotation>& annotations) {
860-
setSrcLoc(ctx, annotations);
851+
ctx.setSrcLoc(annotations);
861852
if (auto i = block(ctx, annotations, true)) {
862853
return i;
863854
}
@@ -879,7 +870,7 @@ MaybeResult<> foldedBlockinstr(Ctx& ctx,
879870
template<typename Ctx>
880871
MaybeResult<> unfoldedBlockinstr(Ctx& ctx,
881872
const std::vector<Annotation>& annotations) {
882-
setSrcLoc(ctx, annotations);
873+
ctx.setSrcLoc(annotations);
883874
if (auto i = block(ctx, annotations, false)) {
884875
return i;
885876
}
@@ -912,7 +903,7 @@ MaybeResult<> blockinstr(Ctx& ctx, const std::vector<Annotation>& annotations) {
912903
// plaininstr ::= ... all plain instructions ...
913904
template<typename Ctx>
914905
MaybeResult<> plaininstr(Ctx& ctx, const std::vector<Annotation>& annotations) {
915-
setSrcLoc(ctx, annotations);
906+
ctx.setSrcLoc(annotations);
916907
auto pos = ctx.in.getPos();
917908
auto keyword = ctx.in.takeKeyword();
918909
if (!keyword) {
@@ -1061,6 +1052,7 @@ Result<typename Ctx::MemargT> memarg(Ctx& ctx, uint32_t n) {
10611052
// blocktype ::= (t:result)? => t? | x,I:typeuse => x if I = {}
10621053
template<typename Ctx> Result<typename Ctx::BlockTypeT> blocktype(Ctx& ctx) {
10631054
auto pos = ctx.in.getPos();
1055+
auto initialLexer = ctx.in;
10641056

10651057
if (auto res = results(ctx)) {
10661058
CHECK_ERR(res);
@@ -1071,7 +1063,7 @@ template<typename Ctx> Result<typename Ctx::BlockTypeT> blocktype(Ctx& ctx) {
10711063

10721064
// We either had no results or multiple results. Reset and parse again as a
10731065
// type use.
1074-
ctx.in.setIndex(pos);
1066+
ctx.in = initialLexer;
10751067
auto use = typeuse(ctx);
10761068
CHECK_ERR(use);
10771069

@@ -1138,6 +1130,7 @@ ifelse(Ctx& ctx, const std::vector<Annotation>& annotations, bool folded) {
11381130

11391131
if (folded) {
11401132
CHECK_ERR(foldedinstrs(ctx));
1133+
ctx.setSrcLoc(annotations);
11411134
}
11421135

11431136
ctx.makeIf(pos, annotations, label, *type);
@@ -2928,8 +2921,9 @@ template<typename Ctx> MaybeResult<> import_(Ctx& ctx) {
29282921
auto name = ctx.in.takeID();
29292922
auto type = typeuse(ctx);
29302923
CHECK_ERR(type);
2931-
CHECK_ERR(
2932-
ctx.addFunc(name ? *name : Name{}, {}, &names, *type, std::nullopt, pos));
2924+
// TODO: function import annotations
2925+
CHECK_ERR(ctx.addFunc(
2926+
name ? *name : Name{}, {}, &names, *type, std::nullopt, {}, pos));
29332927
} else if (ctx.in.takeSExprStart("table"sv)) {
29342928
auto name = ctx.in.takeID();
29352929
auto type = tabletype(ctx);
@@ -2971,6 +2965,8 @@ template<typename Ctx> MaybeResult<> import_(Ctx& ctx) {
29712965
// '(' 'import' mod:name nm:name ')' typeuse ')'
29722966
template<typename Ctx> MaybeResult<> func(Ctx& ctx) {
29732967
auto pos = ctx.in.getPos();
2968+
auto annotations = ctx.in.getAnnotations();
2969+
29742970
if (!ctx.in.takeSExprStart("func"sv)) {
29752971
return {};
29762972
}
@@ -2996,14 +2992,20 @@ template<typename Ctx> MaybeResult<> func(Ctx& ctx) {
29962992
localVars = *l;
29972993
}
29982994
CHECK_ERR(instrs(ctx));
2995+
ctx.setSrcLoc(ctx.in.takeAnnotations());
29992996
}
30002997

30012998
if (!ctx.in.takeRParen()) {
30022999
return ctx.in.err("expected end of function");
30033000
}
30043001

3005-
CHECK_ERR(
3006-
ctx.addFunc(name, *exports, import.getPtr(), *type, localVars, pos));
3002+
CHECK_ERR(ctx.addFunc(name,
3003+
*exports,
3004+
import.getPtr(),
3005+
*type,
3006+
localVars,
3007+
std::move(annotations),
3008+
pos));
30073009
return Ok{};
30083010
}
30093011

src/parser/wat-parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,11 @@ Result<> parseModule(Module& wasm, std::string_view input) {
184184
for (Index i = 0; i < decls.funcDefs.size(); ++i) {
185185
ctx.index = i;
186186
auto* f = wasm.functions[i].get();
187+
WithPosition with(ctx, decls.funcDefs[i].pos);
188+
ctx.setSrcLoc(decls.funcDefs[i].annotations);
187189
if (!f->imported()) {
188190
CHECK_ERR(ctx.visitFunctionStart(f));
189191
}
190-
WithPosition with(ctx, decls.funcDefs[i].pos);
191192
if (auto parsed = func(ctx)) {
192193
CHECK_ERR(parsed);
193194
} else {

src/wasm/wasm-ir-builder.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,17 @@ Result<Expression*> IRBuilder::build() {
211211
}
212212

213213
void IRBuilder::setDebugLocation(const Function::DebugLocation& loc) {
214+
DBG(std::cerr << "setting debugloc " << loc.fileIndex << ":" << loc.lineNumber
215+
<< ":" << loc.columnNumber << "\n";);
214216
debugLoc = loc;
215217
}
216218

217219
void IRBuilder::applyDebugLoc(Expression* expr) {
218220
if (debugLoc) {
219221
if (func) {
222+
DBG(std::cerr << "applying debugloc " << debugLoc->fileIndex << ":"
223+
<< debugLoc->lineNumber << ":" << debugLoc->columnNumber
224+
<< " to expression " << ShallowExpression{expr} << "\n");
220225
func->debugLocations[expr] = *debugLoc;
221226
}
222227
debugLoc.reset();
@@ -698,6 +703,10 @@ Result<> IRBuilder::visitFunctionStart(Function* func) {
698703
if (!scopeStack.empty()) {
699704
return Err{"unexpected start of function"};
700705
}
706+
if (debugLoc) {
707+
func->prologLocation.insert(*debugLoc);
708+
debugLoc.reset();
709+
}
701710
scopeStack.push_back(ScopeCtx::makeFunc(func));
702711
this->func = func;
703712
return Ok{};
@@ -740,6 +749,11 @@ Result<> IRBuilder::visitTryTableStart(TryTable* trytable, Name label) {
740749
}
741750

742751
Result<Expression*> IRBuilder::finishScope(Block* block) {
752+
if (debugLoc) {
753+
DBG(std::cerr << "discarding debugloc " << debugLoc->fileIndex << ":"
754+
<< debugLoc->lineNumber << ":" << debugLoc->columnNumber
755+
<< "\n");
756+
}
743757
debugLoc.reset();
744758

745759
if (scopeStack.empty() || scopeStack.back().isNone()) {
@@ -966,6 +980,10 @@ Result<> IRBuilder::visitEnd() {
966980
if (scope.isNone()) {
967981
return Err{"unexpected end"};
968982
}
983+
if (auto* func = scope.getFunction(); func && debugLoc) {
984+
func->epilogLocation.insert(*debugLoc);
985+
debugLoc.reset();
986+
}
969987
auto expr = finishScope(scope.getBlock());
970988
CHECK_ERR(expr);
971989

test/lit/source-map.wast

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
;; RUN: wasm-opt %s -o %t.wasm -osm %t.map -g -q
22
;; RUN: wasm-opt %t.wasm -ism %t.map -q -o - -S | filecheck %s
33

4+
;; RUN: wasm-opt %s --new-wat-parser -S -o - | filecheck %s
5+
46
(module
7+
;;@ src.cpp:0:1
58
(func $foo (param $x i32) (param $y i32)
69
;;@ src.cpp:10:1
710
(if
@@ -12,8 +15,11 @@
1215
;;@ src.cpp:40:1
1316
(local.get $y)
1417
)
18+
;; For the legacy parser
1519
;;@ src.cpp:50:1
1620
(then
21+
;; For the new parser
22+
;;@ src.cpp:50:1
1723
(return)
1824
)
1925
)
@@ -24,10 +30,12 @@
2430
;;@ src.cpp:80:1
2531
(local.get $y)
2632
)
33+
;;@ src.cpp:90:1
2734
)
2835
)
2936

30-
;; CHECK: (func $foo (param $x i32) (param $y i32)
37+
;; CHECK: ;;@ src.cpp:0:1
38+
;; CHECK-NEXT: (func $foo (param $x i32) (param $y i32)
3139
;; CHECK-NEXT: ;;@ src.cpp:10:1
3240
;; CHECK-NEXT: (if
3341
;; CHECK-NEXT: ;;@ src.cpp:20:1
@@ -49,3 +57,5 @@
4957
;; CHECK-NEXT: ;;@ src.cpp:80:1
5058
;; CHECK-NEXT: (local.get $y)
5159
;; CHECK-NEXT: )
60+
;; CHECK-NEXT: ;;@ src.cpp:90:1
61+
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)