nac3/nac3core/irrt/irrt/exception.hpp

80 lines
2.3 KiB
C++

#pragma once
#include <irrt/cslice.hpp>
#include <irrt/cstr_util.hpp>
#include <irrt/int_types.hpp>
/**
* @brief The int type of ARTIQ exception IDs.
*/
typedef int32_t ExceptionId;
/*
* Set of exceptions C++ IRRT can use.
* Must be synchronized with `setup_irrt_exceptions` in `nac3core/src/codegen/irrt/mod.rs`.
*/
extern "C"
{
ExceptionId EXN_INDEX_ERROR;
ExceptionId EXN_VALUE_ERROR;
ExceptionId EXN_ASSERTION_ERROR;
ExceptionId EXN_TYPE_ERROR;
}
/**
* @brief Extern function to `__nac3_raise`
*
* The parameter `err` could be `Exception<int32_t>` or `Exception<int64_t>`. The caller
* must make sure to pass `Exception`s with the correct `SizeT` depending on the `size_t` of the runtime.
*/
extern "C" void __nac3_raise(void *err);
namespace
{
/**
* @brief NAC3's Exception struct
*/
template <typename SizeT> struct Exception
{
ExceptionId id;
CSlice<SizeT> filename;
int32_t line;
int32_t column;
CSlice<SizeT> function;
CSlice<SizeT> msg;
int64_t params[3];
};
const int64_t NO_PARAM = 0;
template <typename SizeT>
void _raise_exception_helper(ExceptionId id, const char *filename, int32_t line, const char *function, const char *msg,
int64_t param0, int64_t param1, int64_t param2)
{
Exception<SizeT> e = {
.id = id,
.filename = {.base = (uint8_t *)filename, .len = (int32_t)cstr::length(filename)},
.line = line,
.column = 0,
.function = {.base = (uint8_t *)function, .len = (int32_t)cstr::length(function)},
.msg = {.base = (uint8_t *)msg, .len = (int32_t)cstr::length(msg)},
};
e.params[0] = param0;
e.params[1] = param1;
e.params[2] = param2;
__nac3_raise((void *)&e);
__builtin_unreachable();
}
/**
* @brief Raise an exception with location details (location in the IRRT source files).
* @param SizeT The runtime `size_t` type.
* @param id The ID of the exception to raise.
* @param msg A global constant C-string of the error message.
*
* `param0` to `param2` are optional format arguments of `msg`. They should be set to
* `NO_PARAM` to indicate they are unused.
*/
#define raise_exception(SizeT, id, msg, param0, param1, param2) \
_raise_exception_helper<SizeT>(id, __FILE__, __LINE__, __FUNCTION__, msg, param0, param1, param2)
} // namespace