Skip to content

Commit 8171be8

Browse files
committed
Extends wasm-as, wasm-dis and s2wasm to consume debug locations.
1 parent 4ab8088 commit 8171be8

23 files changed

+360
-135
lines changed

src/asm2wasm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,13 +1382,13 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
13821382
while (i < expressionStack.size()) {
13831383
exp = expressionStack[i];
13841384
if (debugLocations.count(exp) == 0) {
1385-
debugLocations[exp] = { fileIndex, lineNumber };
1385+
debugLocations[exp] = { fileIndex, lineNumber, 0 };
13861386
break;
13871387
}
13881388
i++;
13891389
}
13901390
} else {
1391-
debugLocations[exp] = { fileIndex, lineNumber };
1391+
debugLocations[exp] = { fileIndex, lineNumber, 0 };
13921392
}
13931393
break;
13941394
}

src/passes/Print.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
4545

4646
Module* currModule = nullptr;
4747
Function* currFunction = nullptr;
48+
Function::DebugLocation lastPrintedLocation;
4849

4950
PrintSExpression(std::ostream& o) : o(o) {
5051
setMinify(false);
@@ -58,8 +59,11 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
5859
auto iter = debugLocations.find(curr);
5960
if (iter != debugLocations.end()) {
6061
auto fileName = currModule->debugInfoFileNames[iter->second.fileIndex];
61-
o << ";; " << fileName << ":" << iter->second.lineNumber << '\n';
62-
doIndent(o, indent);
62+
if (lastPrintedLocation != iter->second) {
63+
lastPrintedLocation = iter->second;
64+
o << ";;@ " << fileName << ":" << iter->second.lineNumber << ":" << iter->second.columnNumber << '\n';
65+
doIndent(o, indent);
66+
}
6367
}
6468
}
6569
Visitor<PrintSExpression>::visit(curr);
@@ -599,6 +603,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
599603
}
600604
void visitFunction(Function *curr) {
601605
currFunction = curr;
606+
lastPrintedLocation = { 0, 0, 0 };
602607
printOpening(o, "func ", true);
603608
printName(curr->name);
604609
if (curr->type.is()) {

src/s2wasm.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class S2WasmBuilder {
4444
MixedArena* allocator;
4545
LinkerObject* linkerObj;
4646
std::unique_ptr<LinkerObject::SymbolInfo> symbolInfo;
47+
std::unordered_map<uint32_t, uint32_t> fileIndexMap;
4748

4849
public:
4950
S2WasmBuilder(const char* input, bool debug)
@@ -601,7 +602,9 @@ class S2WasmBuilder {
601602
size_t fileId = getInt();
602603
skipWhitespace();
603604
auto quoted = getQuoted();
604-
WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted
605+
uint32_t index = wasm->debugInfoFileNames.size();
606+
fileIndexMap[fileId] = index;
607+
wasm->debugInfoFileNames.push_back(std::string(quoted.begin(), quoted.end()));
605608
s = strchr(s, '\n');
606609
return;
607610
}
@@ -665,22 +668,31 @@ class S2WasmBuilder {
665668

666669
mustMatch(":");
667670

671+
Function::DebugLocation debugLocation = {0,0,0};
672+
bool useDebugLocation = false;
668673
auto recordFile = [&]() {
669674
if (debug) dump("file");
670675
size_t fileId = getInt();
671676
skipWhitespace();
672677
auto quoted = getQuoted();
673-
WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted
678+
uint32_t index = wasm->debugInfoFileNames.size();
679+
fileIndexMap[fileId] = index;
680+
wasm->debugInfoFileNames.push_back(std::string(quoted.begin(), quoted.end()));
674681
s = strchr(s, '\n');
675682
};
676683
auto recordLoc = [&]() {
677684
if (debug) dump("loc");
678685
size_t fileId = getInt();
679686
skipWhitespace();
680-
size_t row = getInt();
687+
uint32_t row = getInt();
681688
skipWhitespace();
682-
size_t column = getInt();
683-
WASM_UNUSED(fileId); WASM_UNUSED(row); WASM_UNUSED(column); // TODO: use the fileId, row and column
689+
uint32_t column = getInt();
690+
auto iter = fileIndexMap.find(fileId);
691+
if (iter == fileIndexMap.end()) {
692+
abort_on("idx");
693+
}
694+
useDebugLocation = true;
695+
debugLocation = {iter->second, row, column};
684696
s = strchr(s, '\n');
685697
};
686698
auto recordLabel = [&]() {
@@ -746,7 +758,10 @@ class S2WasmBuilder {
746758
// parse body
747759
func->body = allocator->alloc<Block>();
748760
std::vector<Expression*> bstack;
749-
auto addToBlock = [&bstack](Expression* curr) {
761+
auto addToBlock = [&](Expression* curr) {
762+
if (useDebugLocation) {
763+
func->debugLocations[curr] = debugLocation;
764+
}
750765
Expression* last = bstack.back();
751766
if (last->is<Loop>()) {
752767
last = last->cast<Loop>()->body;

src/tools/wasm-as.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ using namespace wasm;
3030
int main(int argc, const char *argv[]) {
3131
bool debugInfo = false;
3232
std::string symbolMap;
33+
std::string binaryMapFilename;
34+
std::string binaryMapUrl;
3335
Options options("wasm-as", "Assemble a .wast (WebAssembly text format) into a .wasm (WebAssembly binary format)");
3436
options.extra["validate"] = "wasm";
3537
options
@@ -51,6 +53,12 @@ int main(int argc, const char *argv[]) {
5153
.add("--debuginfo", "-g", "Emit names section and debug info",
5254
Options::Arguments::Zero,
5355
[&](Options *o, const std::string &arguments) { debugInfo = true; })
56+
.add("--binarymap-file", "-bm", "Emit binary map to the specified file",
57+
Options::Arguments::One,
58+
[&binaryMapFilename](Options *o, const std::string &argument) { binaryMapFilename = argument; })
59+
.add("--binarymap-url", "-bu", "Use specified string as binary map URL",
60+
Options::Arguments::One,
61+
[&binaryMapUrl](Options *o, const std::string &argument) { binaryMapUrl = argument; })
5462
.add("--symbolmap", "-s", "Emit a symbol map (indexes => names)",
5563
Options::Arguments::One,
5664
[&](Options *o, const std::string &argument) { symbolMap = argument; })
@@ -87,12 +95,21 @@ int main(int argc, const char *argv[]) {
8795
BufferWithRandomAccess buffer(options.debug);
8896
WasmBinaryWriter writer(&wasm, buffer, options.debug);
8997
writer.setNamesSection(debugInfo);
98+
std::unique_ptr<std::ofstream> binaryMapStream = nullptr;
99+
if (binaryMapFilename.size()) {
100+
binaryMapStream = make_unique<std::ofstream>();
101+
binaryMapStream->open(binaryMapFilename);
102+
writer.setBinaryMap(binaryMapStream.get(), binaryMapUrl);
103+
}
90104
if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap);
91105
writer.write();
92106

93107
if (options.debug) std::cerr << "writing to output..." << std::endl;
94108
Output output(options.extra["output"], Flags::Binary, options.debug ? Flags::Debug : Flags::Release);
95109
buffer.writeTo(output);
110+
if (binaryMapStream) {
111+
binaryMapStream->close();
112+
}
96113

97114
if (options.debug) std::cerr << "Done." << std::endl;
98115
}

src/tools/wasm-dis.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,17 @@ using namespace cashew;
2828
using namespace wasm;
2929

3030
int main(int argc, const char *argv[]) {
31+
std::string binaryMapFilename;
3132
Options options("wasm-dis", "Un-assemble a .wasm (WebAssembly binary format) into a .wast (WebAssembly text format)");
3233
options.add("--output", "-o", "Output file (stdout if not specified)",
3334
Options::Arguments::One,
3435
[](Options *o, const std::string &argument) {
3536
o->extra["output"] = argument;
3637
Colors::disable();
3738
})
39+
.add("--binarymap-file", "-bm", "Consume binary map from the specified file to add location information",
40+
Options::Arguments::One,
41+
[&binaryMapFilename](Options *o, const std::string &argument) { binaryMapFilename = argument; })
3842
.add_positional("INFILE", Options::Arguments::One,
3943
[](Options *o, const std::string &argument) {
4044
o->extra["infile"] = argument;
@@ -46,8 +50,17 @@ int main(int argc, const char *argv[]) {
4650
if (options.debug) std::cerr << "parsing binary..." << std::endl;
4751
Module wasm;
4852
try {
53+
std::unique_ptr<std::ifstream> binaryMapStream;
4954
WasmBinaryBuilder parser(wasm, input, options.debug);
55+
if (binaryMapFilename.size()) {
56+
binaryMapStream = make_unique<std::ifstream>();
57+
binaryMapStream->open(binaryMapFilename);
58+
parser.setDebugLocations(binaryMapStream.get());
59+
}
5060
parser.read();
61+
if (binaryMapStream) {
62+
binaryMapStream->close();
63+
}
5164
} catch (ParseException& p) {
5265
p.dump(std::cerr);
5366
Fatal() << "error in parsing wasm binary";

src/wasm-binary.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -615,15 +615,17 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
615615

616616
void recurse(Expression*& curr);
617617
std::vector<Name> breakStack;
618+
Function::DebugLocation lastDebugLocation;
618619

619620
void visit(Expression* curr) {
620621
if (binaryMap && currFunction) {
621622
// Dump the binaryMap debug info
622623
auto& debugLocations = currFunction->debugLocations;
623624
auto iter = debugLocations.find(curr);
624-
if (iter != debugLocations.end()) {
625+
if (iter != debugLocations.end() && iter->second != lastDebugLocation) {
626+
lastDebugLocation = iter->second;
625627
auto fileName = wasm->debugInfoFileNames[iter->second.fileIndex];
626-
*binaryMap << o.size() << ":" << fileName << ":" <<iter->second.lineNumber << '\n';
628+
*binaryMap << o.size() << ":" << fileName << ":" << iter->second.lineNumber << ":" << iter->second.columnNumber << '\n';
627629
}
628630
}
629631
Visitor<WasmBinaryWriter>::visit(curr);
@@ -663,14 +665,16 @@ class WasmBinaryBuilder {
663665
MixedArena& allocator;
664666
std::vector<char>& input;
665667
bool debug;
668+
std::istream* binaryMap;
669+
std::pair<uint32_t, Function::DebugLocation> nextDebugLocation;
666670

667671
size_t pos = 0;
668672
Index startIndex = -1;
669673

670674
std::set<BinaryConsts::Section> seenSections;
671675

672676
public:
673-
WasmBinaryBuilder(Module& wasm, std::vector<char>& input, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), debug(debug) {}
677+
WasmBinaryBuilder(Module& wasm, std::vector<char>& input, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), debug(debug), binaryMap(nullptr), nextDebugLocation(0, {0,0,0}) {}
674678

675679
void read();
676680
void readUserSection(size_t payloadLen);
@@ -759,6 +763,16 @@ class WasmBinaryBuilder {
759763
void readTableElements();
760764
void readNames(size_t);
761765

766+
// Debug information reading helpers
767+
void setDebugLocations(std::istream* binaryMap_) {
768+
binaryMap = binaryMap_;
769+
readNextDebugLocation();
770+
}
771+
bool useDebugLocation;
772+
Function::DebugLocation debugLocation;
773+
std::unordered_map<std::string, Index> debugInfoFileIndices;
774+
void readNextDebugLocation();
775+
762776
// AST reading
763777
int depth = 0; // only for debugging
764778

src/wasm-s-parser.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@
2828

2929
namespace wasm {
3030

31+
class SourceLocation
32+
{
33+
public:
34+
std::string filename;
35+
uint32_t line;
36+
uint32_t column;
37+
SourceLocation(const std::string& filename_, uint32_t line_, uint32_t column_ = 0)
38+
: filename(filename_), line(line_), column(column_) {}
39+
};
40+
3141
//
3242
// An element in an S-Expression: a list or a string
3343
//
@@ -41,14 +51,15 @@ class Element {
4151
bool quoted_;
4252

4353
public:
44-
Element(MixedArena& allocator) : isList_(true), list_(allocator), line(-1), col(-1) {}
54+
Element(MixedArena& allocator) : isList_(true), list_(allocator), line(-1), col(-1), loc(nullptr) {}
4555

4656
bool isList() { return isList_; }
4757
bool isStr() { return !isList_; }
4858
bool dollared() { return isStr() && dollared_; }
4959
bool quoted() { return isStr() && quoted_; }
5060

5161
size_t line, col;
62+
SourceLocation* loc;
5263

5364
// list methods
5465
List& list();
@@ -61,21 +72,21 @@ class Element {
6172
cashew::IString str();
6273
const char* c_str();
6374
Element* setString(cashew::IString str__, bool dollared__, bool quoted__);
64-
Element* setMetadata(size_t line_, size_t col_);
75+
Element* setMetadata(size_t line_, size_t col_, SourceLocation* loc_);
6576

6677
// printing
6778
friend std::ostream& operator<<(std::ostream& o, Element& e);
6879
void dump();
6980
};
7081

71-
7282
//
7383
// Generic S-Expression parsing into lists
7484
//
7585
class SExpressionParser {
7686
char* input;
7787
size_t line;
7888
char* lineStart;
89+
SourceLocation* loc;
7990

8091
MixedArena allocator;
8192

@@ -87,6 +98,7 @@ class SExpressionParser {
8798
private:
8899
Element* parse();
89100
void skipWhitespace();
101+
void parseDebugLocation();
90102
Element* parseString();
91103
};
92104

@@ -102,6 +114,7 @@ class SExpressionWasmBuilder {
102114
int functionCounter;
103115
int globalCounter;
104116
std::map<Name, WasmType> functionTypes; // we need to know function return types before we parse their contents
117+
std::unordered_map<std::string, Index> debugInfoFileIndices;
105118

106119
public:
107120
// Assumes control of and modifies the input.
@@ -147,6 +160,7 @@ class SExpressionWasmBuilder {
147160
Expression* parseExpression(Element& s);
148161

149162
private:
163+
Expression* makeExpression(Element& s);
150164
Expression* makeBinary(Element& s, BinaryOp op, WasmType type);
151165
Expression* makeUnary(Element& s, UnaryOp op, WasmType type);
152166
Expression* makeSelect(Element& s);

src/wasm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,9 @@ class Function {
527527
std::map<Name, Index> localIndices;
528528

529529
struct DebugLocation {
530-
uint32_t fileIndex, lineNumber;
530+
uint32_t fileIndex, lineNumber, columnNumber;
531+
bool operator==(const DebugLocation& other) const { return fileIndex == other.fileIndex && lineNumber == other.lineNumber && columnNumber == other.columnNumber; }
532+
bool operator!=(const DebugLocation& other) const { return !(*this == other); }
531533
};
532534
std::unordered_map<Expression*, DebugLocation> debugLocations;
533535

0 commit comments

Comments
 (0)