Skip to content

Commit

Permalink
Extends wasm-as, wasm-dis and s2wasm to consume debug locations.
Browse files Browse the repository at this point in the history
  • Loading branch information
yurydelendik committed May 19, 2017
1 parent 55e312d commit 3f94250
Show file tree
Hide file tree
Showing 23 changed files with 363 additions and 135 deletions.
4 changes: 2 additions & 2 deletions src/asm2wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1382,13 +1382,13 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
while (i < expressionStack.size()) {
exp = expressionStack[i];
if (debugLocations.count(exp) == 0) {
debugLocations[exp] = { fileIndex, lineNumber };
debugLocations[exp] = { fileIndex, lineNumber, 0 };
break;
}
i++;
}
} else {
debugLocations[exp] = { fileIndex, lineNumber };
debugLocations[exp] = { fileIndex, lineNumber, 0 };
}
break;
}
Expand Down
9 changes: 7 additions & 2 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {

Module* currModule = nullptr;
Function* currFunction = nullptr;
Function::DebugLocation lastPrintedLocation;

PrintSExpression(std::ostream& o) : o(o) {
setMinify(false);
Expand All @@ -58,8 +59,11 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
auto iter = debugLocations.find(curr);
if (iter != debugLocations.end()) {
auto fileName = currModule->debugInfoFileNames[iter->second.fileIndex];
o << ";; " << fileName << ":" << iter->second.lineNumber << '\n';
doIndent(o, indent);
if (lastPrintedLocation != iter->second) {
lastPrintedLocation = iter->second;
o << ";;@ " << fileName << ":" << iter->second.lineNumber << ":" << iter->second.columnNumber << '\n';
doIndent(o, indent);
}
}
}
Visitor<PrintSExpression>::visit(curr);
Expand Down Expand Up @@ -599,6 +603,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
void visitFunction(Function *curr) {
currFunction = curr;
lastPrintedLocation = {0, 0, 0};
printOpening(o, "func ", true);
printName(curr->name);
if (curr->type.is()) {
Expand Down
27 changes: 21 additions & 6 deletions src/s2wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class S2WasmBuilder {
MixedArena* allocator;
LinkerObject* linkerObj;
std::unique_ptr<LinkerObject::SymbolInfo> symbolInfo;
std::unordered_map<uint32_t, uint32_t> fileIndexMap;

public:
S2WasmBuilder(const char* input, bool debug)
Expand Down Expand Up @@ -601,7 +602,9 @@ class S2WasmBuilder {
size_t fileId = getInt();
skipWhitespace();
auto quoted = getQuoted();
WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted
uint32_t index = wasm->debugInfoFileNames.size();
fileIndexMap[fileId] = index;
wasm->debugInfoFileNames.push_back(std::string(quoted.begin(), quoted.end()));
s = strchr(s, '\n');
return;
}
Expand Down Expand Up @@ -665,22 +668,31 @@ class S2WasmBuilder {

mustMatch(":");

Function::DebugLocation debugLocation = {0,0,0};
bool useDebugLocation = false;
auto recordFile = [&]() {
if (debug) dump("file");
size_t fileId = getInt();
skipWhitespace();
auto quoted = getQuoted();
WASM_UNUSED(fileId); WASM_UNUSED(quoted); // TODO: use the fileId and quoted
uint32_t index = wasm->debugInfoFileNames.size();
fileIndexMap[fileId] = index;
wasm->debugInfoFileNames.push_back(std::string(quoted.begin(), quoted.end()));
s = strchr(s, '\n');
};
auto recordLoc = [&]() {
if (debug) dump("loc");
size_t fileId = getInt();
skipWhitespace();
size_t row = getInt();
uint32_t row = getInt();
skipWhitespace();
size_t column = getInt();
WASM_UNUSED(fileId); WASM_UNUSED(row); WASM_UNUSED(column); // TODO: use the fileId, row and column
uint32_t column = getInt();
auto iter = fileIndexMap.find(fileId);
if (iter == fileIndexMap.end()) {
abort_on("idx");
}
useDebugLocation = true;
debugLocation = {iter->second, row, column};
s = strchr(s, '\n');
};
auto recordLabel = [&]() {
Expand Down Expand Up @@ -746,7 +758,10 @@ class S2WasmBuilder {
// parse body
func->body = allocator->alloc<Block>();
std::vector<Expression*> bstack;
auto addToBlock = [&bstack](Expression* curr) {
auto addToBlock = [&](Expression* curr) {
if (useDebugLocation) {
func->debugLocations[curr] = debugLocation;
}
Expression* last = bstack.back();
if (last->is<Loop>()) {
last = last->cast<Loop>()->body;
Expand Down
19 changes: 19 additions & 0 deletions src/tools/wasm-as.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ using namespace wasm;
int main(int argc, const char *argv[]) {
bool debugInfo = false;
std::string symbolMap;
std::string binaryMapFilename;
std::string binaryMapUrl;
Options options("wasm-as", "Assemble a .wast (WebAssembly text format) into a .wasm (WebAssembly binary format)");
options.extra["validate"] = "wasm";
options
Expand All @@ -51,6 +53,12 @@ int main(int argc, const char *argv[]) {
.add("--debuginfo", "-g", "Emit names section and debug info",
Options::Arguments::Zero,
[&](Options *o, const std::string &arguments) { debugInfo = true; })
.add("--binarymap-file", "-bm", "Emit binary map to the specified file",
Options::Arguments::One,
[&binaryMapFilename](Options *o, const std::string &argument) { binaryMapFilename = argument; })
.add("--binarymap-url", "-bu", "Use specified string as binary map URL",
Options::Arguments::One,
[&binaryMapUrl](Options *o, const std::string &argument) { binaryMapUrl = argument; })
.add("--symbolmap", "-s", "Emit a symbol map (indexes => names)",
Options::Arguments::One,
[&](Options *o, const std::string &argument) { symbolMap = argument; })
Expand Down Expand Up @@ -87,12 +95,23 @@ int main(int argc, const char *argv[]) {
BufferWithRandomAccess buffer(options.debug);
WasmBinaryWriter writer(&wasm, buffer, options.debug);
writer.setNamesSection(debugInfo);
std::ofstream* binaryMapStream = nullptr;
if (binaryMapFilename.size()) {
binaryMapStream = new std::ofstream;
binaryMapStream->open(binaryMapFilename);
writer.setBinaryMap(binaryMapStream, binaryMapUrl);
}
writer.setBinaryMap(binaryMapStream, binaryMapUrl);
if (symbolMap.size() > 0) writer.setSymbolMap(symbolMap);
writer.write();

if (options.debug) std::cerr << "writing to output..." << std::endl;
Output output(options.extra["output"], Flags::Binary, options.debug ? Flags::Debug : Flags::Release);
buffer.writeTo(output);
if (binaryMapStream) {
binaryMapStream->close();
delete binaryMapStream;
}

if (options.debug) std::cerr << "Done." << std::endl;
}
14 changes: 14 additions & 0 deletions src/tools/wasm-dis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@ using namespace cashew;
using namespace wasm;

int main(int argc, const char *argv[]) {
std::string binaryMapFilename;
Options options("wasm-dis", "Un-assemble a .wasm (WebAssembly binary format) into a .wast (WebAssembly text format)");
options.add("--output", "-o", "Output file (stdout if not specified)",
Options::Arguments::One,
[](Options *o, const std::string &argument) {
o->extra["output"] = argument;
Colors::disable();
})
.add("--binarymap-file", "-bm", "Consume binary map from the specified file to add location information",
Options::Arguments::One,
[&binaryMapFilename](Options *o, const std::string &argument) { binaryMapFilename = argument; })
.add_positional("INFILE", Options::Arguments::One,
[](Options *o, const std::string &argument) {
o->extra["infile"] = argument;
Expand All @@ -46,8 +50,18 @@ int main(int argc, const char *argv[]) {
if (options.debug) std::cerr << "parsing binary..." << std::endl;
Module wasm;
try {
std::ifstream* binaryMapStream = nullptr;
WasmBinaryBuilder parser(wasm, input, options.debug);
if (binaryMapFilename.size()) {
binaryMapStream = new std::ifstream;
binaryMapStream->open(binaryMapFilename);
parser.setDebugLocations(binaryMapStream);
}
parser.read();
if (binaryMapStream) {
binaryMapStream->close();
delete binaryMapStream;
}
} catch (ParseException& p) {
p.dump(std::cerr);
Fatal() << "error in parsing wasm binary";
Expand Down
20 changes: 17 additions & 3 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -615,15 +615,17 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {

void recurse(Expression*& curr);
std::vector<Name> breakStack;
Function::DebugLocation lastDebugLocation;

void visit(Expression* curr) {
if (binaryMap && currFunction) {
// Dump the binaryMap debug info
auto& debugLocations = currFunction->debugLocations;
auto iter = debugLocations.find(curr);
if (iter != debugLocations.end()) {
if (iter != debugLocations.end() && iter->second != lastDebugLocation) {
lastDebugLocation = iter->second;
auto fileName = wasm->debugInfoFileNames[iter->second.fileIndex];
*binaryMap << o.size() << ":" << fileName << ":" <<iter->second.lineNumber << '\n';
*binaryMap << o.size() << ":" << fileName << ":" <<iter->second.lineNumber << ":" <<iter->second.columnNumber << '\n';
}
}
Visitor<WasmBinaryWriter>::visit(curr);
Expand Down Expand Up @@ -663,14 +665,16 @@ class WasmBinaryBuilder {
MixedArena& allocator;
std::vector<char>& input;
bool debug;
std::istream* binaryMap;
std::pair<uint32_t, Function::DebugLocation> nextDebugLocation;

size_t pos = 0;
Index startIndex = -1;

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

public:
WasmBinaryBuilder(Module& wasm, std::vector<char>& input, bool debug) : wasm(wasm), allocator(wasm.allocator), input(input), debug(debug) {}
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}) {}

void read();
void readUserSection(size_t payloadLen);
Expand Down Expand Up @@ -759,6 +763,16 @@ class WasmBinaryBuilder {
void readTableElements();
void readNames(size_t);

// Debug information reading helpers
void setDebugLocations(std::istream* binaryMap_) {
binaryMap = binaryMap_;
readNextDebugLocation();
}
bool useDebugLocation;
Function::DebugLocation debugLocation;
std::unordered_map<std::string, Index> debugInfoFileIndices;
void readNextDebugLocation();

// AST reading
int depth = 0; // only for debugging

Expand Down
20 changes: 17 additions & 3 deletions src/wasm-s-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@

namespace wasm {

class SourceLocation
{
public:
std::string filename;
uint32_t line;
uint32_t column;
SourceLocation(const std::string& filename_, uint32_t line_, uint32_t column_ = 0)
: filename(filename_), line(line_), column(column_) {}
};

//
// An element in an S-Expression: a list or a string
//
Expand All @@ -41,14 +51,15 @@ class Element {
bool quoted_;

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

bool isList() { return isList_; }
bool isStr() { return !isList_; }
bool dollared() { return isStr() && dollared_; }
bool quoted() { return isStr() && quoted_; }

size_t line, col;
SourceLocation* loc;

// list methods
List& list();
Expand All @@ -61,21 +72,21 @@ class Element {
cashew::IString str();
const char* c_str();
Element* setString(cashew::IString str__, bool dollared__, bool quoted__);
Element* setMetadata(size_t line_, size_t col_);
Element* setMetadata(size_t line_, size_t col_, SourceLocation* loc_);

// printing
friend std::ostream& operator<<(std::ostream& o, Element& e);
void dump();
};


//
// Generic S-Expression parsing into lists
//
class SExpressionParser {
char* input;
size_t line;
char* lineStart;
SourceLocation* loc;

MixedArena allocator;

Expand All @@ -87,6 +98,7 @@ class SExpressionParser {
private:
Element* parse();
void skipWhitespace();
void parseDebugLocation();
Element* parseString();
};

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

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

private:
Expression* makeExpression(Element& s);
Expression* makeBinary(Element& s, BinaryOp op, WasmType type);
Expression* makeUnary(Element& s, UnaryOp op, WasmType type);
Expression* makeSelect(Element& s);
Expand Down
4 changes: 3 additions & 1 deletion src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,9 @@ class Function {
std::map<Name, Index> localIndices;

struct DebugLocation {
uint32_t fileIndex, lineNumber;
uint32_t fileIndex, lineNumber, columnNumber;
bool operator==(const DebugLocation& other) { return fileIndex == other.fileIndex && lineNumber == other.lineNumber && columnNumber == other.columnNumber; }
bool operator!=(const DebugLocation& other) { return !this->operator==(other); }
};
std::unordered_map<Expression*, DebugLocation> debugLocations;

Expand Down
Loading

0 comments on commit 3f94250

Please sign in to comment.