DebugReportSection DebugReporter::getDotGraphSection( const std::string& id, std::string title, const std::string& dotSpec) { std::stringstream cmd; cmd << "dot -Tsvg <<END_DOT_FILE\n"; cmd << dotSpec << "\n"; cmd << "END_DOT_FILE\n"; FILE* in = popen(cmd.str().c_str(), "r"); std::stringstream data; while (true) { char c = fgetc(in); if (feof(in)) { break; } data << c; } pclose(in); std::stringstream graphHTML; if (data.str().find("<svg") != std::string::npos) { graphHTML << "<img alt='graph image' src='data:image/svg+xml;base64," << toBase64(data.str()) << "'><br/>\n"; } else { graphHTML << "<p>(error: unable to generate dot graph image)</p>"; } graphHTML << "<a href=\"javascript:toggleVisibility('" << id << "-source" << "')\">(show dot source)</a>\n"; graphHTML << "<div id='" << id << "-source" << "' style='display:none'>\n"; graphHTML << "<pre>" << dotSpec << "</pre>\n"; graphHTML << "</div>\n"; return DebugReportSection(id, std::move(title), {}, graphHTML.str()); }
void DebugReporter::generateDebugReport( AstTranslationUnit& translationUnit, std::string id, std::string title) { std::stringstream datalogSpec; translationUnit.getProgram()->print(datalogSpec); DebugReportSection datalogSection = getCodeSection(id + "-dl", "Datalog", datalogSpec.str()); std::stringstream precGraphDot; translationUnit.getAnalysis<PrecedenceGraph>()->outputPrecedenceGraph(precGraphDot); DebugReportSection precedenceGraphSection = getDotGraphSection(id + "-prec-graph", "Precedence Graph", precGraphDot.str()); std::stringstream sccGraphDot; translationUnit.getAnalysis<SCCGraph>()->outputSCCGraph(sccGraphDot); DebugReportSection sccGraphSection = getDotGraphSection(id + "-scc-graph", "SCC Graph", sccGraphDot.str()); std::stringstream topsortSCCGraph; translationUnit.getAnalysis<TopologicallySortedSCCGraph>()->outputTopologicallySortedSCCGraph( topsortSCCGraph); DebugReportSection topsortSCCGraphSection = getCodeSection(id + "-topsort-scc-graph", "SCC Topological Sort Order", topsortSCCGraph.str()); std::stringstream adornment; translationUnit.getAnalysis<Adornment>()->outputAdornment(adornment); DebugReportSection adornmentSection = getCodeSection(id + "-adornment-display", "Adornment", adornment.str()); translationUnit.getDebugReport().addSection( DebugReportSection(id, title, {datalogSection, precedenceGraphSection, sccGraphSection, topsortSCCGraphSection, adornmentSection}, "")); }
DebugReportSection DebugReporter::getCodeSection(const std::string& id, std::string title, std::string code) { std::stringstream codeHTML; std::string escapedCode = std::move(code); while (true) { size_t i = escapedCode.find("<"); if (i == std::string::npos) { break; } escapedCode.replace(i, 1, "<"); } codeHTML << "<pre>" << escapedCode << "</pre>\n"; return DebugReportSection(id, std::move(title), {}, codeHTML.str()); }
bool DebugReporter::transform(AstTranslationUnit& translationUnit) { auto start = std::chrono::high_resolution_clock::now(); bool changed = applySubtransformer(translationUnit, wrappedTransformer.get()); auto end = std::chrono::high_resolution_clock::now(); std::string runtimeStr = "(" + std::to_string(std::chrono::duration<double>(end - start).count()) + "s)"; if (changed) { generateDebugReport(translationUnit, wrappedTransformer->getName(), "After " + wrappedTransformer->getName() + " " + runtimeStr); } else { translationUnit.getDebugReport().addSection(DebugReportSection(wrappedTransformer->getName(), "After " + wrappedTransformer->getName() + " " + runtimeStr + " (unchanged)", {}, "")); } return changed; }
void DebugReporter::generateDebugReport( AstTranslationUnit& translationUnit, const std::string& id, std::string title) { std::stringstream datalogSpec; translationUnit.getProgram()->print(datalogSpec); DebugReportSection datalogSection = getCodeSection(id + "-dl", "Datalog", datalogSpec.str()); std::stringstream typeAnalysis; translationUnit.getAnalysis<TypeAnalysis>()->print(typeAnalysis); DebugReportSection typeAnalysisSection = getCodeSection(id + "-ta", "Type Analysis", typeAnalysis.str()); std::stringstream typeEnvironmentAnalysis; translationUnit.getAnalysis<TypeEnvironmentAnalysis>()->print(typeEnvironmentAnalysis); DebugReportSection typeEnvironmentAnalysisSection = getCodeSection(id + "-tea", "Type Environment Analysis", typeEnvironmentAnalysis.str()); std::stringstream precGraphDot; translationUnit.getAnalysis<PrecedenceGraph>()->print(precGraphDot); DebugReportSection precedenceGraphSection = getDotGraphSection(id + "-prec-graph", "Precedence Graph", precGraphDot.str()); std::stringstream sccGraphDot; translationUnit.getAnalysis<SCCGraph>()->print(sccGraphDot); DebugReportSection sccGraphSection = getDotGraphSection(id + "-scc-graph", "SCC Graph", sccGraphDot.str()); std::stringstream topsortSCCGraph; translationUnit.getAnalysis<TopologicallySortedSCCGraph>()->print(topsortSCCGraph); DebugReportSection topsortSCCGraphSection = getCodeSection(id + "-topsort-scc-graph", "SCC Topological Sort Order", topsortSCCGraph.str()); translationUnit.getDebugReport().addSection(DebugReportSection(id, std::move(title), {datalogSection, typeAnalysisSection, typeEnvironmentAnalysisSection, precedenceGraphSection, sccGraphSection, topsortSCCGraphSection}, "")); }