From b23a9af95c65c01d949153fc49e5091aaa7c3d30 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 17 Nov 2021 22:27:08 +0200 Subject: [PATCH] Colorize the debug output of the GLSL compiler --- source/glsl/compiler.cpp | 4 +- source/glsl/compiler.h | 2 +- source/glsl/debug.cpp | 111 ++++++++++++++++++++++++++------------- source/glsl/debug.h | 21 +++++++- tools/glslcompiler.cpp | 2 +- 5 files changed, 99 insertions(+), 41 deletions(-) diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 0e26a163..16ac375c 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -209,11 +209,11 @@ const SourceMap &Compiler::get_source_map() const return module->source_map; } -string Compiler::get_stage_debug(Stage::Type stage_type) const +string Compiler::get_stage_debug(Stage::Type stage_type, bool use_colors) const { auto i = find_member(module->stages, stage_type, &Stage::type); if(i!=module->stages.end()) - return DumpTree().apply(*i); + return DumpTree(use_colors).apply(*i); throw key_error(Stage::get_stage_name(stage_type)); } diff --git a/source/glsl/compiler.h b/source/glsl/compiler.h index 52076e69..0db1ca40 100644 --- a/source/glsl/compiler.h +++ b/source/glsl/compiler.h @@ -117,7 +117,7 @@ public: /** Returns a textual representation of the syntax tree for a shader stage. Intended for debugging purposes. */ - std::string get_stage_debug(Stage::Type) const; + std::string get_stage_debug(Stage::Type, bool = false) const; /** Returns diagnostics from compilation. The output is intended to be viewed by humans. */ diff --git a/source/glsl/debug.cpp b/source/glsl/debug.cpp index 60ac76f2..5ee30e09 100644 --- a/source/glsl/debug.cpp +++ b/source/glsl/debug.cpp @@ -8,6 +8,24 @@ namespace Msp { namespace GL { namespace SL { +const DumpTree::Colors DumpTree::no_colors = +{ "", "", "", "", "", "", "" }; + +const DumpTree::Colors DumpTree::default_colors = +{ + "\033[0m", // default + "\033[38;5;250m", // tree + "\033[38;5;244m", // location + "\033[38;5;146m", // label + "\033[38;5;194m", // type + "\033[38;5;230m", // name + "\033[38;5;210m" // error +}; + +DumpTree::DumpTree(bool use_colors): + colors(use_colors ? default_colors : no_colors) +{ } + string DumpTree::apply(Stage &stage) { formatted = format("Stage: %s\n", Stage::get_stage_name(stage.type)); @@ -15,13 +33,13 @@ string DumpTree::apply(Stage &stage) append(format("Version: %d.%02d", stage.required_features.glsl_version.major, stage.required_features.glsl_version.minor)); for(const auto &kvp: stage.types) - append(format("Type: %%%d %s", get_label(*kvp.second), kvp.first)); + append(format("Type: %s %s%s%s", get_label(*kvp.second), colors.type_color, kvp.first, colors.default_color)); for(const auto &kvp: stage.interface_blocks) - append(format("Interface block: %%%d %s", get_label(*kvp.second), kvp.first)); + append(format("Interface block: %s %s", get_label(*kvp.second), format_name(kvp.first))); for(const auto &kvp: stage.functions) - append(format("Function: %%%d %s", get_label(*kvp.second), kvp.first)); + append(format("Function: %s %s", get_label(*kvp.second), format_name(kvp.first))); last_branch(); stage.content.visit(*this); @@ -30,19 +48,30 @@ string DumpTree::apply(Stage &stage) void DumpTree::append(const string &line) { + formatted += colors.tree_color; StringCodec::Utf8::Encoder enc; for(auto i=tree.begin(); i!=tree.end(); ) { enc.encode_char(*i++, formatted); enc.encode_char((i==tree.end() ? REACH : EMPTY), formatted); } + formatted += colors.default_color; formatted += line; formatted += '\n'; } void DumpTree::append(const Node &node, const string &line) { - append(format("<%d:%d> %s", node.source, node.line, line)); + string location; + if(node.source==BUILTIN_SOURCE) + location = "builtin"; + else if(node.source==INTERNAL_SOURCE) + location = "internal"; + else if(node.source==GENERATED_SOURCE) + location = "generated"; + else + location = format("%s:%s", node.source, node.line); + append(format("%s<%s>%s %s", colors.location_color, location, colors.default_color, line)); } void DumpTree::append_subtree(const vector &branches) @@ -95,17 +124,27 @@ void DumpTree::end_sub() tree.back() = BRANCH; } -unsigned DumpTree::get_label(const Node &node) +std::string DumpTree::get_label(const Node &node) { unsigned &label = node_labels[&node]; if(!label) label = node_labels.size(); - return label; + return format("%s%%%d%s", colors.label_color, label, colors.default_color); } string DumpTree::format_type(TypeDeclaration *type) { - return (type ? type->name : "?"); + return type ? format_type(type->name) : format("%s?%s", colors.error_color, colors.default_color); +} + +string DumpTree::format_type(const string &type) +{ + return format("%s%s%s", colors.type_color, type, colors.default_color); +} + +string DumpTree::format_name(const string &name) +{ + return format("%s%s%s", colors.name_color, name, colors.default_color); } template @@ -123,7 +162,7 @@ void DumpTree::visit(Block &block) begin_sub(); for(const auto &kvp: block.variables) - append(format("Variable: %%%d %s %s", get_label(*kvp.second), kvp.second->type, kvp.first)); + append(format("Variable: %s %s %s", get_label(*kvp.second), format_type(kvp.second->type), format_name(kvp.first))); for(auto i=block.body.cbegin(); i!=block.body.cend(); ) { @@ -143,8 +182,8 @@ void DumpTree::visit(VariableReference &var) { string text; if(var.declaration) - text += format("%%%d ", get_label(*var.declaration)); - text += format("%s (var) -> %s", var.name, format_type(var.type)); + text += format("%s ", get_label(*var.declaration)); + text += format("%s (var) -> %s", format_name(var.name), format_type(var.type)); append(var, text); } @@ -152,8 +191,8 @@ void DumpTree::visit(InterfaceBlockReference &iface) { string text; if(iface.declaration) - text += format("%%%d ", get_label(*iface.declaration)); - text += format("%s (iface) -> %s", iface.name, format_type(iface.type)); + text += format("%s ", get_label(*iface.declaration)); + text += format("%s (iface) -> %s", format_name(iface.name), format_type(iface.type)); append(iface, text); } @@ -161,8 +200,8 @@ void DumpTree::visit(MemberAccess &memacc) { string text = "Member access:"; if(memacc.declaration) - text += format(" %%%d", get_label(*memacc.declaration)); - text += format(" .%s (%d) -> %s", memacc.member, memacc.index, format_type(memacc.type)); + text += format(" %s", get_label(*memacc.declaration)); + text += format(" .%s (%d) -> %s", format_name(memacc.member), memacc.index, format_type(memacc.type)); append(memacc, text); append_subtree(*memacc.left); } @@ -201,7 +240,7 @@ void DumpTree::visit(Assignment &assign) begin_sub(); if(assign.target.declaration) { - string text = format("Target: %%%d", get_label(*assign.target.declaration)); + string text = format("Target: %s", get_label(*assign.target.declaration)); static const char swizzle[4] = { 'x', 'y', 'z', 'w' }; for(unsigned i=0; i %s", format_type(call.type)); @@ -301,11 +340,11 @@ void DumpTree::visit(InterfaceLayout &layout) void DumpTree::visit(BasicTypeDeclaration &type) { - append(type, format("%%%d typedef %s", get_label(type), type.name)); + append(type, format("%s typedef %s", get_label(type), format_type(type.name))); vector branches; if(type.base_type) - branches.emplace_back(format("%s: %%%d %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), type.base_type->name)); + branches.emplace_back(format("%s: %s %s", (type.kind==BasicTypeDeclaration::ALIAS ? "Alias of" : "Base"), get_label(*type.base_type), format_type(type.base_type->name))); if(type.kind==BasicTypeDeclaration::VECTOR) branches.emplace_back(format("Vector: %d", type.size)); else if(type.kind==BasicTypeDeclaration::MATRIX) @@ -317,12 +356,12 @@ void DumpTree::visit(ImageTypeDeclaration &type) { static const char *const dims[] = { "1D", "2D", "3D", "Cube" }; - append(type, format("%%%d typedef %s", get_label(type), type.name)); + append(type, format("%s typedef %s", get_label(type), format_type(type.name))); vector branches; branches.emplace_back(format("Dimensions: %s%s", dims[type.dimensions-1], (type.array ? " array" : ""))); if(type.base_type) - branches.emplace_back(format("Element type: %%%d %s", get_label(*type.base_type), type.base_type->name)); + branches.emplace_back(format("Element type: %s %s", get_label(*type.base_type), format_type(type.base_type->name))); if(type.shadow) branches.emplace_back("Shadow"); append_subtree(branches); @@ -330,13 +369,13 @@ void DumpTree::visit(ImageTypeDeclaration &type) void DumpTree::visit(StructDeclaration &strct) { - append(strct, format("%%%d struct %s", get_label(strct), strct.name)); + append(strct, format("%s struct %s", get_label(strct), strct.name)); append_subtree(strct.members); } void DumpTree::visit(VariableDeclaration &var) { - string decl = format("%%%d ", get_label(var)); + string decl = format("%s ", get_label(var)); if(var.constant) decl += "const "; if(!var.interpolation.empty()) @@ -347,7 +386,7 @@ void DumpTree::visit(VariableDeclaration &var) decl += format("%s ", var.interface); if(!var.precision.empty()) decl += format("%s ", var.precision); - decl += format("%s %s", var.type, var.name); + decl += format("%s %s", format_type(var.type), format_name(var.name)); if(var.source==BUILTIN_SOURCE) decl += " (builtin)"; else if(var.linked_declaration) @@ -356,26 +395,26 @@ void DumpTree::visit(VariableDeclaration &var) vector branches; if(var.type_declaration) - branches.push_back(format("Type: %%%d %s", get_label(*var.type_declaration), var.type_declaration->name)); + branches.emplace_back(format("Type: %s %s", get_label(*var.type_declaration), format_type(var.type_declaration->name))); if(var.layout) - branches.push_back(var.layout.get()); + branches.emplace_back(var.layout.get()); if(var.array) { if(var.array_size) branches.emplace_back("Array []", var.array_size.get()); else - branches.push_back("Array []"); + branches.emplace_back("Array []"); } if(var.init_expression) - branches.push_back(var.init_expression.get()); + branches.emplace_back(var.init_expression.get()); append_subtree(branches); } void DumpTree::visit(InterfaceBlock &iface) { - string head = format("%%%d %s %s", get_label(iface), iface.interface, iface.block_name); + string head = format("%s %s %s", get_label(iface), iface.interface, format_name(iface.block_name)); if(!iface.instance_name.empty()) - head += format(" %s", iface.instance_name); + head += format(" %s", format_name(iface.instance_name)); if(iface.array) head += "[]"; if(iface.source==BUILTIN_SOURCE) @@ -386,17 +425,17 @@ void DumpTree::visit(InterfaceBlock &iface) vector branches; if(iface.type_declaration) - branches.push_back(format("Type: %%%d %s", get_label(*iface.type_declaration), iface.type_declaration->name)); + branches.emplace_back(format("Type: %s %s", get_label(*iface.type_declaration), format_type(iface.type_declaration->name))); if(iface.layout) - branches.push_back(iface.layout.get()); + branches.emplace_back(iface.layout.get()); if(iface.members) - branches.push_back(iface.members.get()); + branches.emplace_back(iface.members.get()); append_subtree(branches); } void DumpTree::visit(FunctionDeclaration &func) { - string text = format("%%%d %s %s%s", get_label(func), func.return_type, func.name, (func.signature.empty() ? "(?)" : func.signature)); + string text = format("%s %s %s%s", get_label(func), format_type(func.return_type), format_name(func.name), (func.signature.empty() ? "(?)" : func.signature)); if(func.source==BUILTIN_SOURCE) text += " (builtin)"; else if(!func.definition) @@ -405,14 +444,14 @@ void DumpTree::visit(FunctionDeclaration &func) begin_sub(); if(func.return_type_declaration) - append(format("Return type: %%%d %s", get_label(*func.return_type_declaration), func.return_type_declaration->name)); + append(format("Return type: %s %s", get_label(*func.return_type_declaration), format_type(func.return_type_declaration))); for(const RefPtr &p: func.parameters) p->visit(*this); last_branch(); if(func.definition==&func) func.body.visit(*this); else if(func.definition) - append(format("Definition: %%%d", get_label(*func.definition))); + append(format("Definition: %s", get_label(*func.definition))); end_sub(); } diff --git a/source/glsl/debug.h b/source/glsl/debug.h index c3e9c701..5b2a3d96 100644 --- a/source/glsl/debug.h +++ b/source/glsl/debug.h @@ -32,11 +32,28 @@ private: Branch(Node *n): node(n) { } }; + struct Colors + { + const char *default_color; + const char *tree_color; + const char *location_color; + const char *label_color; + const char *type_color; + const char *name_color; + const char *error_color; + }; + std::map node_labels; std::string formatted; std::vector tree; + const Colors &colors; + + static const Colors no_colors; + static const Colors default_colors; public: + DumpTree(bool = false); + std::string apply(Stage &); std::string apply(Node &n) { n.visit(*this); return formatted; } @@ -48,8 +65,10 @@ private: void begin_sub(); void last_branch(); void end_sub(); - unsigned get_label(const Node &); + std::string get_label(const Node &); std::string format_type(TypeDeclaration *); + std::string format_type(const std::string &); + std::string format_name(const std::string &); template typename T::const_iterator increment(typename T::const_iterator &, const T &); diff --git a/tools/glslcompiler.cpp b/tools/glslcompiler.cpp index ee9c2d3c..f7bb2de9 100644 --- a/tools/glslcompiler.cpp +++ b/tools/glslcompiler.cpp @@ -168,7 +168,7 @@ int GlslCompiler::main() { vector stages = compiler.get_stages(); for(vector::const_iterator i=stages.begin(); i!=stages.end(); ++i) - IO::print("%s\n", compiler.get_stage_debug(*i)); + IO::print("%s\n", compiler.get_stage_debug(*i, true)); } IO::Base *out = &IO::cout; -- 2.43.0