* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file error.h
* \brief
*/
#pragma once
#include <cstddef>
#include <exception>
#include <sstream>
#include <string>
#include <memory>
#include <vector>
#include <cstring>
#include <cassert>
#include <iomanip>
#include "error_code.h"
#include "lazy.h"
namespace npu::tile_fwk {
using Backtrace = std::shared_ptr<LazyValue<std::string>>;
Backtrace GetBacktrace(size_t skipFrames, size_t maxFrames);
struct ErrorMessage {
public:
std::string Message() { return ss.str(); }
template <typename T>
ErrorMessage& operator<<(const T& value)
{
ss << value;
return *this;
}
template <typename T>
ErrorMessage& operator<<(const std::vector<T>& vec)
{
ss << "[";
for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
if (iter != vec.begin()) {
ss << ", ";
}
ss << *iter;
}
ss << "]";
return *this;
}
ErrorMessage& operator<<(std::ostream& (*manipulator)(std::ostream&))
{
ss << manipulator;
return *this;
}
std::stringstream ss;
};
class Error : public std::exception {
public:
Error(const char* func, const char* file, size_t line, const std::string& msg, Backtrace backtrace)
: func_(func), file_(file), line_(line), msg_(msg), backtrace_(backtrace)
{}
Error(const char* func, const char* file, size_t line, Backtrace backtrace = nullptr)
: func_(func), file_(file), line_(line), backtrace_(backtrace)
{}
const char* what() const noexcept override;
[[nodiscard]] std::string DiagnosticWithBacktrace() const;
int operator=(ErrorMessage& msg);
private:
const char* func_;
const char* file_;
size_t line_;
std::string msg_;
Backtrace backtrace_;
mutable LazyShared<std::string> what_;
};
class AssertInfo {
public:
[[noreturn]] int operator=(ErrorMessage& msg)
{
(void)fprintf(stderr, "%s\n", msg.Message().c_str());
abort();
}
};
#ifndef __DEVICE__
#define ASSERT_WITH_CODE(errcode, cond) \
(cond) ? \
0 : \
npu::tile_fwk::Error(__func__, __FILE__, __LINE__, npu::tile_fwk::GetBacktrace(0, 64)) = \
npu::tile_fwk::ErrorMessage() << "ASSERT FAILED: " \
<< "ErrCode: F" << std::uppercase << std::hex << std::setw(5) << std::setfill('0') \
<< (static_cast<unsigned>(errcode) & 0xFFFFF) << std::dec << "! Enum: " << #errcode << "\n"
#define CHECK_WITH_CODE(errcode, cond) \
(cond) ? \
0 : \
npu::tile_fwk::Error(__func__, __FILE__, __LINE__, npu::tile_fwk::GetBacktrace(0, 64)) = \
npu::tile_fwk::ErrorMessage() << "CHECK FAILED: " \
<< "ErrCode: F" << std::uppercase << std::hex << std::setw(5) << std::setfill('0') \
<< (static_cast<unsigned>(errcode) & 0xFFFFF) << std::dec << "! Enum: " << #errcode << "\n"
#define TILEFWK_ERROR() \
npu::tile_fwk::Error(__func__, __FILE__, __LINE__, npu::tile_fwk::GetBacktrace(0, 64)) = \
npu::tile_fwk::ErrorMessage()
#else
#define ASSERT_WITH_CODE(errcode, cond) \
(cond) ? 0 : \
AssertInfo() = npu::tile_fwk::ErrorMessage() << "ASSERT FAILED: " \
<< "ErrCode: F" << std::uppercase << std::hex << std::setw(5) << std::setfill('0') \
<< (static_cast<unsigned>(errcode) & 0xFFFFF) << std::dec << "! Enum: " << #errcode << "\n"
#define CHECK_WITH_CODE(errcode, cond) \
(cond) ? 0 : \
AssertInfo() = npu::tile_fwk::ErrorMessage() << "CHECK FAILED: " \
<< "ErrCode: F" << std::uppercase << std::hex << std::setw(5) << std::setfill('0') \
<< (static_cast<unsigned>(errcode) & 0xFFFFF) << std::dec << "! Enum: " << #errcode << "\n"
#endif
#define ASSERT_DEFAULT_SELECT(_1, _2, NAME, ...) NAME
#define ASSERT_DEFAULT_WITHOUT_ERR_CODE(default_errcode, cond) ASSERT_WITH_CODE(default_errcode, cond)
#define ASSERT_DEFAULT_WITH_ERR_CODE(default_errcode, errcode, cond) ASSERT_WITH_CODE(errcode, cond)
#define ASSERT_DEFAULT(default_errcode, ...) \
ASSERT_DEFAULT_SELECT(__VA_ARGS__, ASSERT_DEFAULT_WITH_ERR_CODE, ASSERT_DEFAULT_WITHOUT_ERR_CODE)( \
default_errcode, __VA_ARGS__)
#define CHECK_DEFAULT_SELECT(_1, _2, NAME, ...) NAME
#define CHECK_DEFAULT_WITHOUT_ERR_CODE(default_errcode, cond) CHECK_WITH_CODE(default_errcode, cond)
#define CHECK_DEFAULT_WITH_ERR_CODE(default_errcode, errcode, cond) CHECK_WITH_CODE(errcode, cond)
#define CHECK_DEFAULT(default_errcode, ...) \
CHECK_DEFAULT_SELECT(__VA_ARGS__, CHECK_DEFAULT_WITH_ERR_CODE, CHECK_DEFAULT_WITHOUT_ERR_CODE)( \
default_errcode, __VA_ARGS__)
#define ASSERT(...) ASSERT_DEFAULT(npu::tile_fwk::InternalError::COMMON_INNER_ERROR, __VA_ARGS__)
#define CHECK(...) CHECK_DEFAULT(npu::tile_fwk::ExternalError::COMMON_EXTERNAL_ERROR, __VA_ARGS__)
#ifndef FE_ASSERT
#define FE_ASSERT(...) ASSERT_DEFAULT(npu::tile_fwk::InternalError::FE_INNER_ERROR, __VA_ARGS__)
#endif
#ifndef PASS_ASSERT
#define PASS_ASSERT(...) ASSERT_DEFAULT(npu::tile_fwk::InternalError::PASS_INNER_ERROR, __VA_ARGS__)
#endif
#ifndef MACHINE_ASSERT
#define MACHINE_ASSERT(...) ASSERT_DEFAULT(npu::tile_fwk::InternalError::MACHINE_INNER_ERROR, __VA_ARGS__)
#endif
#ifndef SIM_ASSERT
#define SIM_ASSERT(...) ASSERT_DEFAULT(npu::tile_fwk::InternalError::SIM_INNER_ERROR, __VA_ARGS__)
#endif
}