Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse debug information such as files and locations from .s files. #347

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,26 @@ class NameManager : public WalkerPass<PostWalker<NameManager, Visitor<NameManage
size_t counter = 0;
};

struct PrinterArgs {
std::ostream& o;
bool minify;
bool fullAST;
bool debugInfo;

PrinterArgs(): o(std::cout), minify(false), fullAST(false), debugInfo(false) {}
PrinterArgs(std::ostream& o): o(o), minify(false), fullAST(false), debugInfo(false) {}
PrinterArgs(std::ostream& o, bool minify, bool fullAST, bool debugInfo): o(o), minify(minify), fullAST(fullAST), debugInfo(debugInfo) {}
};

// Prints out a module
class Printer : public Pass {
protected:
std::ostream& o;
PrinterArgs args;

public:
Printer() : o(std::cout) {}
Printer(std::ostream& o) : o(o) {}
Printer() : args(PrinterArgs()) {}
Printer(std::ostream& o) : args(PrinterArgs(o)) {}
Printer(const PrinterArgs& args) : args(args) {}

void run(PassRunner* runner, Module* module) override;
};
Expand Down
118 changes: 101 additions & 17 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
std::ostream& o;
unsigned indent = 0;

bool debugInfoComments = false;
size_t lastDebugLocationId = 0;
std::vector<DebugLocation>* functionDebugLocations = nullptr;
size_t lastLabelId = 0;
std::vector<Name>* functionLabels = nullptr;

bool minify;
const char *maybeSpace;
const char *maybeNewLine;
Expand All @@ -49,6 +55,8 @@ struct PrintSExpression : public Visitor<PrintSExpression> {

void setFullAST(bool fullAST_) { fullAST = fullAST_; }

void setDebugInfoComments(bool debugInfoComments_) { debugInfoComments = debugInfoComments_; }

void incIndent() {
if (minify) return;
o << '\n';
Expand Down Expand Up @@ -78,6 +86,32 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
return name;
}

void visit(Expression *curr) {
if (debugInfoComments && curr->debugInfo.labelIndex != lastLabelId) {
lastLabelId = curr->debugInfo.labelIndex;
if (functionLabels) { // no labels -- skipping
const Name& labelName = (*functionLabels)[lastLabelId];
o << "(;!bookmark " << labelName.str << ";)";
o << maybeNewLine;
!minify && doIndent(o, indent);
}
}
if (debugInfoComments && curr->debugInfo.locationIndex != lastDebugLocationId) {
lastDebugLocationId = curr->debugInfo.locationIndex;
// skipping location id 0 or debug information is absent
if (functionDebugLocations && lastDebugLocationId) {
const DebugLocation& debugLocation = (*functionDebugLocations)[lastDebugLocationId];
o << "(;!loc " << debugLocation.fileId << ' ' << debugLocation.row << ' ' << debugLocation.column << ";)";
o << maybeNewLine;
!minify && doIndent(o, indent);
}
}
Visitor<PrintSExpression>::visit(curr);
// keeping previously set location for next siblings
lastDebugLocationId = curr->debugInfo.locationIndex;
lastLabelId = curr->debugInfo.labelIndex;
}

void visitBlock(Block *curr) {
// special-case Block, because Block nesting (in their first element) can be incredibly deep
std::vector<Block*> stack;
Expand Down Expand Up @@ -506,6 +540,11 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
void visitFunction(Function *curr) {
currFunction = curr;
printOpening(o, "func ", true) << curr->name;
functionDebugLocations = &(curr->debugLocations);
lastDebugLocationId = 0;
functionLabels = &(curr->labels);
lastLabelId = 0;

if (curr->type.is()) {
o << maybeSpace << "(type " << curr->type << ')';
}
Expand All @@ -525,6 +564,12 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
printMinorOpening(o, "local ") << printableLocal(i) << ' ' << printWasmType(curr->getLocalType(i)) << ")";
o << maybeNewLine;
}
if (debugInfoComments && functionLabels) { // no labels -- skipping
const Name& labelName = (*functionLabels)[0]; // first label is normally a function name
doIndent(o, indent);
o << "(;!bookmark " << labelName.str << ";)";
o << maybeNewLine;
}
// It is ok to emit a block here, as a function can directly contain a list, even if our
// ast avoids that for simplicity. We can just do that optimization here..
if (!fullAST && curr->body->is<Block>() && curr->body->cast<Block>()->name.isNull()) {
Expand All @@ -544,6 +589,35 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
o << ')';
}
void printDebugSections(Module *curr) {
if (!debugInfoComments)
return;

bool hasSequences = false;
for (auto& child : curr->functions) {
if (child->labels.size() > 0) {
hasSequences = true;
}
}
if (hasSequences) {
doIndent(o, indent);
o << "(;!dbg_section .label_sequences\n";
for (auto& child : curr->functions) {
o << "\t.function";
for (auto item : child->labels) {
o << " " << item.str;
}
o << '\n';
}
o << ";)";
o << maybeNewLine;
}
for (auto& child : curr->debugSections) {
doIndent(o, indent);
o << "(;!dbg_section " << child.c_str() << ";)";
o << maybeNewLine;
}
}
void visitModule(Module *curr) {
printOpening(o, "module", true);
incIndent();
Expand Down Expand Up @@ -608,18 +682,31 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
visitTable(&curr->table);
o << maybeNewLine;
}
if (debugInfoComments) {
for(auto const &item : curr->debugFileMap) {
doIndent(o, indent);
o << "(;!file " << item.first << " ";
printText(o, item.second.str);
o << ";)";
o << maybeNewLine;
}
}
for (auto& child : curr->functions) {
doIndent(o, indent);
visitFunction(child.get());
o << maybeNewLine;
}
printDebugSections(curr);
decIndent();
o << maybeNewLine;
}
};

void Printer::run(PassRunner* runner, Module* module) {
PrintSExpression print(o);
PrintSExpression print(args.o);
print.setMinify(args.minify);
print.setFullAST(args.fullAST);
print.setDebugInfoComments(args.debugInfo);
print.visitModule(module);
}

Expand All @@ -629,14 +716,8 @@ static RegisterPass<Printer> registerPass("print", "print in s-expression format

class MinifiedPrinter : public Printer {
public:
MinifiedPrinter() : Printer() {}
MinifiedPrinter(std::ostream& o) : Printer(o) {}

void run(PassRunner* runner, Module* module) override {
PrintSExpression print(o);
print.setMinify(true);
print.visitModule(module);
}
MinifiedPrinter() : Printer(PrinterArgs(std::cout, true, false, false)) {}
MinifiedPrinter(std::ostream& o) : Printer(PrinterArgs(o, true, false, false)) {}
};

static RegisterPass<MinifiedPrinter> registerMinifyPass("print-minified", "print in minified s-expression format");
Expand All @@ -645,18 +726,21 @@ static RegisterPass<MinifiedPrinter> registerMinifyPass("print-minified", "print

class FullPrinter : public Printer {
public:
FullPrinter() : Printer() {}
FullPrinter(std::ostream& o) : Printer(o) {}

void run(PassRunner* runner, Module* module) override {
PrintSExpression print(o);
print.setFullAST(true);
print.visitModule(module);
}
FullPrinter() : Printer(PrinterArgs(std::cout, false, true, false)) {}
FullPrinter(std::ostream& o) : Printer(PrinterArgs(o, false, true, false)) {}
};

static RegisterPass<FullPrinter> registerFullASTPass("print-full", "print in full s-expression format");

// Prints out full ast module with additional debug info comments
class DebugInfoCommentsPrinter : public Printer {
public:
DebugInfoCommentsPrinter() : Printer(PrinterArgs(std::cout, false, true, true)) {}
DebugInfoCommentsPrinter(std::ostream& o) : Printer(PrinterArgs(o, false, true, true)) {}
};

static RegisterPass<DebugInfoCommentsPrinter> registerDebugInfoCommentsPass("print-debug-info", "print in full s-expression format with debug info comments");

// Print individual expressions

std::ostream& WasmPrinter::printExpression(Expression* expression, std::ostream& o, bool minify) {
Expand Down
Loading