tkonolige commented on a change in pull request #6274: URL: https://github.com/apache/incubator-tvm/pull/6274#discussion_r483722840
########## File path: src/ir/diagnostic.cc ########## @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * \file src/ir/transform.cc + * \brief Infrastructure for transformation passes. + */ +#include <tvm/ir/diagnostic.h> +#include <tvm/parser/source_map.h> + +#include <rang.hpp> + +namespace tvm { + +using tvm::parser::Source; + +const char* kTVM_INTERNAL_ERROR_MESSAGE = + "\n---------------------------------------------------------------\n" + "An internal invariant was violated during the execution of TVM " + "please read TVM's error reporting guidelines.\n" + "More details can be found here: https://discuss.tvm.ai/t/error-reporting/7793.\n" + "---------------------------------------------------------------\n"; + +/* Diagnostic */ +TVM_REGISTER_NODE_TYPE(DiagnosticNode); + +Diagnostic::Diagnostic(DiagnosticLevel level, Span span, const std::string& message) { + auto n = make_object<DiagnosticNode>(); + n->level = level; + n->span = span; + n->message = message; + data_ = std::move(n); +} + +DiagnosticBuilder Diagnostic::Bug(Span span) { + return DiagnosticBuilder(DiagnosticLevel::kBug, span); +} + +DiagnosticBuilder Diagnostic::Error(Span span) { + return DiagnosticBuilder(DiagnosticLevel::kError, span); +} + +DiagnosticBuilder Diagnostic::Warning(Span span) { + return DiagnosticBuilder(DiagnosticLevel::kWarning, span); +} + +DiagnosticBuilder Diagnostic::Note(Span span) { + return DiagnosticBuilder(DiagnosticLevel::kNote, span); +} + +DiagnosticBuilder Diagnostic::Help(Span span) { + return DiagnosticBuilder(DiagnosticLevel::kHelp, span); +} + +/* Diagnostic Renderer */ +TVM_REGISTER_NODE_TYPE(DiagnosticRendererNode); + +void DiagnosticRenderer::Render(const DiagnosticContext& ctx) { (*this)->renderer(ctx); } + +TVM_DLL DiagnosticRenderer::DiagnosticRenderer( + TypedPackedFunc<void(DiagnosticContext ctx)> renderer) { + auto n = make_object<DiagnosticRendererNode>(); + n->renderer = renderer; + data_ = std::move(n); +} + +TVM_REGISTER_GLOBAL("DiagnosticRenderer") + .set_body_typed([](TypedPackedFunc<void(DiagnosticContext ctx)> renderer) { + return DiagnosticRenderer(renderer); + }); + +/* Diagnostic Context */ +TVM_REGISTER_NODE_TYPE(DiagnosticContextNode); + +void DiagnosticContext::Render() { + (*this)->renderer.Render(*this); + + if ((*this)->diagnostics.size()) { + (*this)->renderer = DiagnosticRenderer(); + LOG(FATAL) << "DiagnosticError: one or more error diagnostics were " + << "emitted, please check diagnostic render for output."; + } +} + +TVM_REGISTER_GLOBAL("DiagnosticRendererRender") + .set_body_typed([](DiagnosticRenderer renderer, DiagnosticContext ctx) { + renderer.Render(ctx); + }); + +DiagnosticContext::DiagnosticContext(const IRModule& module, const DiagnosticRenderer& renderer) { + auto n = make_object<DiagnosticContextNode>(); + n->module = module; + n->renderer = renderer; + data_ = std::move(n); +} + +/*! \brief Emit a diagnostic. */ +void DiagnosticContext::Emit(const Diagnostic& diagnostic) { + (*this)->diagnostics.push_back(diagnostic); +} + +/*! \brief Emit a diagnostic. */ +void DiagnosticContext::EmitFatal(const Diagnostic& diagnostic) { + Emit(diagnostic); + Render(); +} + +/* Default Terminal Renderer. */ +static const char* DEFAULT_RENDERER = "diagnostics.DefaultRenderer"; + +DiagnosticContext DiagnosticContext::Default(const IRModule& module) { + auto pf = tvm::runtime::Registry::Get(DEFAULT_RENDERER); + ICHECK(pf != nullptr) + << "Can not find registered function for " << DEFAULT_RENDERER << "." << std::endl + << "Either this is an internal error or the default function was overloaded incorrectly."; + auto default_render = tvm::runtime::TypedPackedFunc<DiagnosticRenderer()>(*pf); + return DiagnosticContext(module, default_render()); +} + +std::ostream& EmitDiagnosticHeader(std::ostream& out, const Span& span, DiagnosticLevel level, + std::string msg) { + rang::fg diagnostic_color; + std::string diagnostic_type; + + switch (level) { + case DiagnosticLevel::kWarning: { + diagnostic_color = rang::fg::yellow; + diagnostic_type = "warning"; + break; + } + case DiagnosticLevel::kError: { + diagnostic_color = rang::fg::red; + diagnostic_type = "error"; + break; + } + case DiagnosticLevel::kBug: { + diagnostic_color = rang::fg::blue; + diagnostic_type = "bug"; + break; + } + case DiagnosticLevel::kNote: { + diagnostic_color = rang::fg::reset; + diagnostic_type = "note"; + break; + } + case DiagnosticLevel::kHelp: { + diagnostic_color = rang::fg::reset; + diagnostic_type = "help"; + break; + } + } + + out << rang::style::bold << diagnostic_color << diagnostic_type << ": " << rang::fg::reset << msg + << std::endl + << rang::fg::blue << " --> " << rang::fg::reset << rang::style::reset + << span->source_name->name << ":" << span->line << ":" << span->column << std::endl; + + return out; +} + +/*! \brief Generate an error message at a specific line and column with the + * annotated message. + * + * The error is written directly to the `out` std::ostream. + * + * \param out The output ostream. + * \param line The line at which to report a diagnostic. + * \param line The column at which to report a diagnostic. + * \param msg The message to attach. + */ +void ReportAt(const DiagnosticContext& context, std::ostream& out, const Span& span, + const Diagnostic& diagnostic) { + auto it = context->module->source_map->source_map.find(span->source_name); + + // If the source name is not in the current source map, sources were not annotated. + if (it == context->module->source_map->source_map.end()) { + LOG(FATAL) << "The source maps are not populated for this module." + << "Please use `tvm.relay.transform.AnnotateSpans` to attach source maps for error " + "reporting." Review comment: ```suggestion LOG(FATAL) << "The source maps are not populated for this module. " << "Please use `tvm.relay.transform.AnnotateSpans` to attach source maps for error " "reporting. " ``` ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected]
