jroesch commented on a change in pull request #6274: URL: https://github.com/apache/incubator-tvm/pull/6274#discussion_r483345164
########## File path: include/tvm/ir/diagnostic.h ########## @@ -0,0 +1,254 @@ +/* + * 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 diagnostic.h + * \brief A new diagnostic interface for TVM error reporting. + * + * A prototype of the new diagnostic reporting interface for TVM. + * + * Eventually we hope to promote this file to the top-level and + * replace the existing errors.h. + */ + +#ifndef TVM_IR_DIAGNOSTIC_H_ +#define TVM_IR_DIAGNOSTIC_H_ + +#include <tvm/ir/span.h> +#include <tvm/ir/module.h> +#include <tvm/parser/source_map.h> +#include <tvm/runtime/container.h> +#include <tvm/runtime/object.h> +#include <tvm/support/logging.h> + +#include <fstream> +#include <string> +#include <utility> +#include <vector> + +namespace tvm { + +using tvm::parser::SourceMap; + +static const char* kTVM_INTERNAL_ERROR_MESSAGE = "An internal invariant was violated during the execution of TVM" \ + "please read TVM's error reporting guidelines at discuss.tvm.ai/thread"; + +static const char* kINDENT = " "; + +#define ICHECK_BINARY_OP(name, op, x, y) \ + if (dmlc::LogCheckError _check_err = dmlc::LogCheck##name(x, y)) \ + dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << kTVM_INTERNAL_ERROR_MESSAGE << std::endl \ + << kIndent << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": " + +#define ICHECK(x) \ + if (!(x)) \ + dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << kTVM_INTERNAL_ERROR_MESSAGE \ + << kINDENT << "Check failed: " #x << ": " + +#define ICHECK_LT(x, y) ICHECK_BINARY_OP(_LT, <, x, y) +#define ICHECK_GT(x, y) ICHECK_BINARY_OP(_GT, >, x, y) +#define ICHECK_LE(x, y) ICHECK_BINARY_OP(_LE, <=, x, y) +#define ICHECK_GE(x, y) ICHECK_BINARY_OP(_GE, >=, x, y) +#define ICHECK_EQ(x, y) ICHECK_BINARY_OP(_EQ, ==, x, y) +#define ICHECK_NE(x, y) ICHECK_BINARY_OP(_NE, !=, x, y) +#define ICHECK_NOTNULL(x) \ + ((x) == NULL ? dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << kTVM_INTERNAL_ERROR_MESSAGE \ + << kINDENT << "Check not null: " #x << ' ', (x) : (x)) // NOLINT(*) + +/*! \brief The diagnostic level, controls the printing of the message. */ +enum class DiagnosticLevel { + kBug, + kError, + kWarning, + kNote, + kHelp, +}; + +class DiagnosticBuilder; + +/*! \brief A compiler diagnostic. */ +class Diagnostic; + + /*! \brief A compiler diagnostic message. */ +class DiagnosticNode : public Object { + public: + /*! \brief The level. */ + DiagnosticLevel level; + /*! \brief The span at which to report an error. */ + Span span; + /*! \brief The diagnostic message. */ + std::string message; + + // override attr visitor + void VisitAttrs(AttrVisitor* v) { + v->Visit("level", &level); + v->Visit("span", &span); + v->Visit("message", &message); + } + + bool SEqualReduce(const DiagnosticNode* other, SEqualReducer equal) const { + return equal(this->level, other->level) && + equal(this->span, other->span) && + equal(this->message, other->message); + } + + static constexpr const char* _type_key = "Diagnostic"; + TVM_DECLARE_FINAL_OBJECT_INFO(DiagnosticNode, Object); +}; + +class Diagnostic : public ObjectRef { + public: + TVM_DLL Diagnostic(DiagnosticLevel level, Span span, const std::string& message); + + static DiagnosticBuilder Bug(Span span); + static DiagnosticBuilder Error(Span span); + static DiagnosticBuilder Warning(Span span); + static DiagnosticBuilder Note(Span span); + static DiagnosticBuilder Help(Span span); + + TVM_DEFINE_OBJECT_REF_METHODS(Diagnostic, ObjectRef, DiagnosticNode); +}; + +/*! + * \brief A wrapper around std::stringstream to build a diagnostic. + * + * \code + * + * void ReportError(const Error& err); + * + * void Test(int number) { + * // Use error reporter to construct an error. + * ReportError(ErrorBuilder() << "This is an error number=" << number); + * } + * + * \endcode + */ +class DiagnosticBuilder { + public: + /*! \brief The level. */ + DiagnosticLevel level; + + /*! \brief The source name. */ + SourceName source_name; + + /*! \brief The span of the diagnostic. */ + Span span; + + template <typename T> + DiagnosticBuilder& operator<<(const T& val) { // NOLINT(*) + stream_ << val; + return *this; + } + + DiagnosticBuilder() : level(DiagnosticLevel::kError), source_name(), span(Span()) {} + + DiagnosticBuilder(const DiagnosticBuilder& builder) + : level(builder.level), source_name(builder.source_name), span(builder.span) {} + + DiagnosticBuilder(DiagnosticLevel level, Span span) : level(level), span(span) {} + + operator Diagnostic() { return Diagnostic(this->level, this->span, this->stream_.str()); } + + private: + std::stringstream stream_; + friend class Diagnostic; +}; + +/*! + * \brief A diagnostic context for recording errors against a source file. + */ +class DiagnosticContext; + +class DiagnosticContextNode : public Object { + public: + /*! \brief The source to report against. */ + SourceMap source_map; + + /*! \brief The set of diagnostics to report. */ + Array<Diagnostic> diagnostics; + + void VisitAttrs(AttrVisitor* v) { + v->Visit("source_map", &source_map); + v->Visit("diagnostics", &diagnostics); + } + + bool SEqualReduce(const DiagnosticContextNode* other, SEqualReducer equal) const { + return equal(source_map, other->source_map); + } + + static constexpr const char* _type_key = "DiagnosticContext"; + TVM_DECLARE_FINAL_OBJECT_INFO(DiagnosticContextNode, Object); +}; + +class DiagnosticRenderer; + +class DiagnosticContext : public ObjectRef { + public: + TVM_DLL DiagnosticContext(const SourceMap& source_map); + + /*! \brief Emit a diagnostic. */ + void Emit(const Diagnostic& diagnostic); + /*! \brief Emit a diagnostic. */ + void EmitFatal(const Diagnostic& diagnostic); + /*! \brief Render the errors and raise a DiagnosticError exception. */ + void Render(const DiagnosticRenderer& renderer); + + DiagnosticContextNode* operator->() { + CHECK(get() != nullptr); + return static_cast<DiagnosticContextNode*>(get_mutable()); + } + + TVM_DEFINE_OBJECT_REF_METHODS(DiagnosticContext, ObjectRef, DiagnosticContextNode); Review comment: Did this ########## File path: include/tvm/ir/diagnostic.h ########## @@ -0,0 +1,254 @@ +/* + * 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 diagnostic.h + * \brief A new diagnostic interface for TVM error reporting. + * + * A prototype of the new diagnostic reporting interface for TVM. + * + * Eventually we hope to promote this file to the top-level and + * replace the existing errors.h. + */ + +#ifndef TVM_IR_DIAGNOSTIC_H_ +#define TVM_IR_DIAGNOSTIC_H_ + +#include <tvm/ir/span.h> +#include <tvm/ir/module.h> +#include <tvm/parser/source_map.h> +#include <tvm/runtime/container.h> +#include <tvm/runtime/object.h> +#include <tvm/support/logging.h> + +#include <fstream> +#include <string> +#include <utility> +#include <vector> + +namespace tvm { + +using tvm::parser::SourceMap; + +static const char* kTVM_INTERNAL_ERROR_MESSAGE = "An internal invariant was violated during the execution of TVM" \ + "please read TVM's error reporting guidelines at discuss.tvm.ai/thread"; + +static const char* kINDENT = " "; + +#define ICHECK_BINARY_OP(name, op, x, y) \ + if (dmlc::LogCheckError _check_err = dmlc::LogCheck##name(x, y)) \ + dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << kTVM_INTERNAL_ERROR_MESSAGE << std::endl \ + << kIndent << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": " + +#define ICHECK(x) \ + if (!(x)) \ + dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << kTVM_INTERNAL_ERROR_MESSAGE \ + << kINDENT << "Check failed: " #x << ": " + +#define ICHECK_LT(x, y) ICHECK_BINARY_OP(_LT, <, x, y) +#define ICHECK_GT(x, y) ICHECK_BINARY_OP(_GT, >, x, y) +#define ICHECK_LE(x, y) ICHECK_BINARY_OP(_LE, <=, x, y) +#define ICHECK_GE(x, y) ICHECK_BINARY_OP(_GE, >=, x, y) +#define ICHECK_EQ(x, y) ICHECK_BINARY_OP(_EQ, ==, x, y) +#define ICHECK_NE(x, y) ICHECK_BINARY_OP(_NE, !=, x, y) +#define ICHECK_NOTNULL(x) \ + ((x) == NULL ? dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \ + << kTVM_INTERNAL_ERROR_MESSAGE \ + << kINDENT << "Check not null: " #x << ' ', (x) : (x)) // NOLINT(*) + +/*! \brief The diagnostic level, controls the printing of the message. */ +enum class DiagnosticLevel { + kBug, + kError, + kWarning, + kNote, + kHelp, +}; + +class DiagnosticBuilder; + +/*! \brief A compiler diagnostic. */ +class Diagnostic; + + /*! \brief A compiler diagnostic message. */ +class DiagnosticNode : public Object { + public: + /*! \brief The level. */ + DiagnosticLevel level; + /*! \brief The span at which to report an error. */ + Span span; + /*! \brief The diagnostic message. */ + std::string message; + + // override attr visitor + void VisitAttrs(AttrVisitor* v) { + v->Visit("level", &level); + v->Visit("span", &span); + v->Visit("message", &message); + } + + bool SEqualReduce(const DiagnosticNode* other, SEqualReducer equal) const { + return equal(this->level, other->level) && + equal(this->span, other->span) && + equal(this->message, other->message); + } + + static constexpr const char* _type_key = "Diagnostic"; + TVM_DECLARE_FINAL_OBJECT_INFO(DiagnosticNode, Object); +}; + +class Diagnostic : public ObjectRef { + public: + TVM_DLL Diagnostic(DiagnosticLevel level, Span span, const std::string& message); + + static DiagnosticBuilder Bug(Span span); + static DiagnosticBuilder Error(Span span); + static DiagnosticBuilder Warning(Span span); + static DiagnosticBuilder Note(Span span); + static DiagnosticBuilder Help(Span span); + + TVM_DEFINE_OBJECT_REF_METHODS(Diagnostic, ObjectRef, DiagnosticNode); +}; + +/*! + * \brief A wrapper around std::stringstream to build a diagnostic. + * + * \code + * + * void ReportError(const Error& err); + * + * void Test(int number) { + * // Use error reporter to construct an error. + * ReportError(ErrorBuilder() << "This is an error number=" << number); + * } + * + * \endcode + */ +class DiagnosticBuilder { + public: + /*! \brief The level. */ + DiagnosticLevel level; + + /*! \brief The source name. */ + SourceName source_name; + + /*! \brief The span of the diagnostic. */ + Span span; + + template <typename T> + DiagnosticBuilder& operator<<(const T& val) { // NOLINT(*) + stream_ << val; + return *this; + } + + DiagnosticBuilder() : level(DiagnosticLevel::kError), source_name(), span(Span()) {} + + DiagnosticBuilder(const DiagnosticBuilder& builder) + : level(builder.level), source_name(builder.source_name), span(builder.span) {} + + DiagnosticBuilder(DiagnosticLevel level, Span span) : level(level), span(span) {} + + operator Diagnostic() { return Diagnostic(this->level, this->span, this->stream_.str()); } + + private: + std::stringstream stream_; + friend class Diagnostic; +}; + +/*! + * \brief A diagnostic context for recording errors against a source file. + */ +class DiagnosticContext; + +class DiagnosticContextNode : public Object { + public: + /*! \brief The source to report against. */ + SourceMap source_map; + + /*! \brief The set of diagnostics to report. */ + Array<Diagnostic> diagnostics; + + void VisitAttrs(AttrVisitor* v) { + v->Visit("source_map", &source_map); + v->Visit("diagnostics", &diagnostics); + } + + bool SEqualReduce(const DiagnosticContextNode* other, SEqualReducer equal) const { + return equal(source_map, other->source_map); + } + + static constexpr const char* _type_key = "DiagnosticContext"; + TVM_DECLARE_FINAL_OBJECT_INFO(DiagnosticContextNode, Object); +}; + +class DiagnosticRenderer; + +class DiagnosticContext : public ObjectRef { + public: + TVM_DLL DiagnosticContext(const SourceMap& source_map); + + /*! \brief Emit a diagnostic. */ + void Emit(const Diagnostic& diagnostic); + /*! \brief Emit a diagnostic. */ + void EmitFatal(const Diagnostic& diagnostic); + /*! \brief Render the errors and raise a DiagnosticError exception. */ + void Render(const DiagnosticRenderer& renderer); + + DiagnosticContextNode* operator->() { + CHECK(get() != nullptr); Review comment: Did this. ---------------------------------------------------------------- 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]
