You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2020/09/23 17:13:12 UTC

[GitHub] [incubator-tvm] rkimball commented on a change in pull request #6274: [Diagnostics][Relay][InferType] Refactor InferType to work on whole module, and use new diagnostics.

rkimball commented on a change in pull request #6274:
URL: https://github.com/apache/incubator-tvm/pull/6274#discussion_r492254721



##########
File path: include/tvm/ir/diagnostic.h
##########
@@ -0,0 +1,262 @@
+/*
+ * 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/module.h>
+#include <tvm/ir/span.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;
+using tvm::runtime::TypedPackedFunc;
+
+extern const char* kTVM_INTERNAL_ERROR_MESSAGE;
+
+#define __INDENT "  "
+
+#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                  \
+      << __INDENT << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": "
+
+#define ICHECK(x)                                    \
+  if (!(x))                                          \
+  dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
+      << kTVM_INTERNAL_ERROR_MESSAGE << __INDENT << "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()                              \

Review comment:
       ```suggestion
     ((x) == nullptr ? dmlc::LogMessageFatal(__FILE__, __LINE__).stream()                              \
   ```

##########
File path: include/tvm/ir/diagnostic.h
##########
@@ -0,0 +1,262 @@
+/*
+ * 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/module.h>
+#include <tvm/ir/span.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;
+using tvm::runtime::TypedPackedFunc;
+
+extern const char* kTVM_INTERNAL_ERROR_MESSAGE;
+
+#define __INDENT "  "

Review comment:
       ```suggestion
   #define ICHECK_INDENT "  "
   ```
   Starting a name with underscore or containing double underscores is reserved in many instances so just avoid using it.

##########
File path: python/tvm/ir/diagnostic.py
##########
@@ -0,0 +1,67 @@
+# 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.
+# pylint: disable=invalid-name
+"""
+The diagnostic interface to TVM, uses for reporting and rendering

Review comment:
       ```suggestion
   The diagnostic interface to TVM, used for reporting and rendering
   ```

##########
File path: src/parser/parser.cc
##########
@@ -516,6 +582,33 @@ class Parser {
     return Bracket(TokenType::kLCurly, TokenType::kRCurly, parser);
   }
 
+  template <typename R>
+  R WithSpan(std::function<R()> parser) {
+    auto start_span = Peek()->span;
+    DLOG(INFO) << "WithSpan: start_span = " << start_span;
+    R ast = parser();
+    if (ast.defined()) {
+      // The token at the head of the stream is now 1 past where we parsed. So we find its start
+      // position as its start and end, so that when we merge we only grow the spanned region
+      // to the start of the current stream.
+      auto span_pos = pos - 1;
+      while ((tokens.at(span_pos)->token_type == TokenType::kWhitespace ||
+              tokens.at(span_pos)->token_type == TokenType::kNewline ||
+              tokens.at(span_pos)->token_type == TokenType::kLineComment ||
+              tokens.at(span_pos)->token_type == TokenType::kComment)) {
+        span_pos--;
+      }
+      auto end_token = tokens.at(span_pos);
+      DLOG(INFO) << "WithSpan: end_span = " << end_token->span;
+      ast->span = start_span.Merge(end_token->span);
+    }
+    return ast;
+  }
+
+  /*! \brief Parse a meta reference this is of the form `meta[type_key][node_index]`.
+   * For example `meta[relay.Constant][0]` references the first constant, `meta[relay.Constant][1]`
+   * and so on.

Review comment:
       ```suggestion
      * For example `meta[relay.Constant][0]` references the first constant, `meta[relay.Constant][1]`
      * the second, and so on.
   ```

##########
File path: python/tvm/ir/diagnostic.py
##########
@@ -0,0 +1,67 @@
+# 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.
+# pylint: disable=invalid-name
+"""
+The diagnostic interface to TVM, uses for reporting and rendering
+diagnostic information about the compiler. This module exposes
+three key abstractions a Diagnostic, the DiagnosticContext,

Review comment:
       ```suggestion
   three key abstractions: a Diagnostic, the DiagnosticContext,
   ```

##########
File path: src/relay/analysis/type_solver.cc
##########
@@ -57,13 +57,21 @@ class TypeSolver::Reporter : public TypeReporterNode {
     return true;
   }
 
-  TVM_DLL void SetLocation(const ObjectRef& ref) final { location = ref; }
+  TVM_DLL void SetLocation(const Span& span) final { this->span = span; }

Review comment:
       ```suggestion
     TVM_DLL void SetSpan(const Span& span) final { this->span = span; }
   ```
   I'm ok with fixing this later but they should be symmetric

##########
File path: tests/python/relay/test_diagnostic.py
##########
@@ -0,0 +1,51 @@
+# 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.
+import tvm
+
+from tvm import register_func, get_global_func, IRModule
+from tvm import relay
+from tvm.parser import SpanCheck
+from tvm.parser import AnnotateSpans
+from tvm.runtime import Object
+from tvm.ir.diagnostic import get_default_renderer, set_default_renderer
+
+# std_out = get_default_renderer()()

Review comment:
       Should this have a todo or jira or something?

##########
File path: include/tvm/ir/diagnostic.h
##########
@@ -0,0 +1,262 @@
+/*
+ * 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/module.h>
+#include <tvm/ir/span.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;
+using tvm::runtime::TypedPackedFunc;
+
+extern const char* kTVM_INTERNAL_ERROR_MESSAGE;
+
+#define __INDENT "  "
+
+#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                  \
+      << __INDENT << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": "
+
+#define ICHECK(x)                                    \
+  if (!(x))                                          \
+  dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
+      << kTVM_INTERNAL_ERROR_MESSAGE << __INDENT << "Check failed: " #x << ": "

Review comment:
       ```suggestion
         << kTVM_INTERNAL_ERROR_MESSAGE << __INDENT << "Check failed: " #x << " == false: "
   ```
   I'm not sure if this would make the message any more clear, whatever looks best

##########
File path: include/tvm/ir/diagnostic.h
##########
@@ -0,0 +1,262 @@
+/*
+ * 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/module.h>
+#include <tvm/ir/span.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;
+using tvm::runtime::TypedPackedFunc;
+
+extern const char* kTVM_INTERNAL_ERROR_MESSAGE;
+
+#define __INDENT "  "
+
+#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                  \
+      << __INDENT << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": "
+
+#define ICHECK(x)                                    \
+  if (!(x))                                          \
+  dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
+      << kTVM_INTERNAL_ERROR_MESSAGE << __INDENT << "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 << __INDENT << "Check not null: " #x << ' ', \
+   (x) : (x))  // NOLINT(*)
+
+/*! \brief The diagnostic level, controls the printing of the message. */
+enum class DiagnosticLevel {

Review comment:
       Do we want a way to get the level as a string for output later? 

##########
File path: src/relay/op/nn/convolution.h
##########
@@ -141,26 +142,43 @@ bool Conv2DRel(const Array<Type>& types, int num_inputs, const Attrs& attrs,
   const Layout kernel_layout(param->kernel_layout);
 
   const auto trans_in_layout = tir::BijectiveLayout(in_layout, kNCHW);
-  CHECK(trans_in_layout.defined())
-      << "Conv only support input layouts that are convertible from NCHW."
-      << " But got " << in_layout;
+  if (!trans_in_layout.defined()) {

Review comment:
       Can these be done via ICHECK macro instead of explicit code? Maybe add an ICHECK option to do the return false part?

##########
File path: src/parser/parser.cc
##########
@@ -516,6 +582,33 @@ class Parser {
     return Bracket(TokenType::kLCurly, TokenType::kRCurly, parser);
   }
 
+  template <typename R>
+  R WithSpan(std::function<R()> parser) {
+    auto start_span = Peek()->span;
+    DLOG(INFO) << "WithSpan: start_span = " << start_span;
+    R ast = parser();
+    if (ast.defined()) {
+      // The token at the head of the stream is now 1 past where we parsed. So we find its start
+      // position as its start and end, so that when we merge we only grow the spanned region
+      // to the start of the current stream.
+      auto span_pos = pos - 1;
+      while ((tokens.at(span_pos)->token_type == TokenType::kWhitespace ||
+              tokens.at(span_pos)->token_type == TokenType::kNewline ||
+              tokens.at(span_pos)->token_type == TokenType::kLineComment ||
+              tokens.at(span_pos)->token_type == TokenType::kComment)) {
+        span_pos--;
+      }
+      auto end_token = tokens.at(span_pos);
+      DLOG(INFO) << "WithSpan: end_span = " << end_token->span;
+      ast->span = start_span.Merge(end_token->span);
+    }
+    return ast;
+  }
+
+  /*! \brief Parse a meta reference this is of the form `meta[type_key][node_index]`.

Review comment:
       ```suggestion
     /*! \brief Parse a meta reference of the form `meta[type_key][node_index]`.
   ```

##########
File path: include/tvm/ir/diagnostic.h
##########
@@ -0,0 +1,262 @@
+/*
+ * 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/module.h>
+#include <tvm/ir/span.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;
+using tvm::runtime::TypedPackedFunc;
+
+extern const char* kTVM_INTERNAL_ERROR_MESSAGE;
+
+#define __INDENT "  "
+
+#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                  \
+      << __INDENT << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": "
+
+#define ICHECK(x)                                    \
+  if (!(x))                                          \
+  dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
+      << kTVM_INTERNAL_ERROR_MESSAGE << __INDENT << "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 << __INDENT << "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,

Review comment:
       What is the difference between Note and Help? The others I get but don't we only need one of these?

##########
File path: include/tvm/ir/diagnostic.h
##########
@@ -0,0 +1,262 @@
+/*
+ * 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/module.h>
+#include <tvm/ir/span.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;
+using tvm::runtime::TypedPackedFunc;
+
+extern const char* kTVM_INTERNAL_ERROR_MESSAGE;
+
+#define __INDENT "  "
+
+#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                  \
+      << __INDENT << "Check failed: " << #x " " #op " " #y << *(_check_err.str) << ": "
+
+#define ICHECK(x)                                    \
+  if (!(x))                                          \
+  dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
+      << kTVM_INTERNAL_ERROR_MESSAGE << __INDENT << "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 << __INDENT << "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_NOTNULLABLE_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;
+
+/*! \brief Display diagnostics in a given display format.
+ *
+ * A diagnostic renderer is responsible for converting the
+ * raw diagnostics into consumable output.
+ *
+ * For example the terminal renderer will render a sequence
+ * of compiler diagnostics to std::out and std::err in
+ * a human readable form.
+ */
+class DiagnosticRendererNode : public Object {
+ public:
+  TypedPackedFunc<void(DiagnosticContext ctx)> renderer;
+
+  // override attr visitor
+  void VisitAttrs(AttrVisitor* v) {}
+
+  static constexpr const char* _type_key = "DiagnosticRenderer";
+  TVM_DECLARE_FINAL_OBJECT_INFO(DiagnosticRendererNode, Object);
+};
+
+class DiagnosticRenderer : public ObjectRef {
+ public:
+  TVM_DLL DiagnosticRenderer(TypedPackedFunc<void(DiagnosticContext ctx)> render);
+  TVM_DLL DiagnosticRenderer()
+      : DiagnosticRenderer(TypedPackedFunc<void(DiagnosticContext ctx)>()) {}
+
+  void Render(const DiagnosticContext& ctx);
+
+  DiagnosticRendererNode* operator->() {
+    CHECK(get() != nullptr);
+    return static_cast<DiagnosticRendererNode*>(get_mutable());
+  }
+
+  TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(DiagnosticRenderer, ObjectRef, DiagnosticRendererNode);
+};
+
+class DiagnosticContextNode : public Object {
+ public:
+  /*! \brief The Module to report against. */
+  IRModule module;
+
+  /*! \brief The set of diagnostics to report. */
+  Array<Diagnostic> diagnostics;
+
+  /*! \brief The renderer set for the context. */
+  DiagnosticRenderer renderer;
+
+  void VisitAttrs(AttrVisitor* v) {
+    v->Visit("module", &module);
+    v->Visit("diagnostics", &diagnostics);
+  }
+
+  bool SEqualReduce(const DiagnosticContextNode* other, SEqualReducer equal) const {
+    return equal(module, other->module) && equal(diagnostics, other->diagnostics);
+  }
+
+  static constexpr const char* _type_key = "DiagnosticContext";
+  TVM_DECLARE_FINAL_OBJECT_INFO(DiagnosticContextNode, Object);
+};
+
+class DiagnosticContext : public ObjectRef {
+ public:
+  TVM_DLL DiagnosticContext(const IRModule& module, const DiagnosticRenderer& renderer);
+  TVM_DLL static DiagnosticContext Default(const IRModule& source_map);
+
+  /*! \brief Emit a diagnostic. */
+  void Emit(const Diagnostic& diagnostic);
+  /*! \brief Emit a diagnostic. */
+  void EmitFatal(const Diagnostic& diagnostic);

Review comment:
       Can you document the difference between Emit and EmitFatal here?




----------------------------------------------------------------
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:
users@infra.apache.org