diff --git a/dev.org b/dev.org
index dd23eb5..8333031 100644
--- a/dev.org
+++ b/dev.org
@@ -127,6 +127,10 @@ and recompile those functions with more optimization passes
* TODOs
+** TODO Investigate possible implementanion for Internal Errors
+- An option is to use llvm registry functionality like the one used in =clang-doc= instead of
+ =errorVariants= var.
+
** TODO In =SereneContext::getLatestJITDylib= function, make sure that the JITDylib is still valid
Make sure that the returning Dylib still exists in the JIT
by calling =jit->engine->getJITDylibByName(dylib_name);=
diff --git a/libserene/include/serene/environment.h b/libserene/include/serene/environment.h
index 144354d..70baa81 100644
--- a/libserene/include/serene/environment.h
+++ b/libserene/include/serene/environment.h
@@ -16,10 +16,9 @@
* along with this program. If not, see .
*/
-#ifndef SERENE_ENVIRONMENT_H
-#define SERENE_ENVIRONMENT_H
+#ifndef SERENE_TEST_ENVIRONMENT_H
+#define SERENE_TEST_ENVIRONMENT_H
-#include "serene/llvm/patches.h"
#include "serene/utils.h"
#include
diff --git a/libserene/include/serene/errors.h b/libserene/include/serene/errors.h
index ce93741..1afb07e 100644
--- a/libserene/include/serene/errors.h
+++ b/libserene/include/serene/errors.h
@@ -22,6 +22,8 @@
#include "serene/errors/base.h"
#include "serene/errors/errc.h"
+#include
+
#define GET_CLASS_DEFS
#include "serene/errors/errs.h.inc"
@@ -29,8 +31,12 @@
namespace serene::errors {
+/// Create and return a Serene flavored `llvm::Error` by passing the parameters
+/// directly to the constructor of type `E`.
+///
+/// This is the official way of creating error objects in Serene.
template
-llvm::Error makeError(Args &&...args) {
+SERENE_EXPORT llvm::Error makeError(Args &&...args) {
return llvm::make_error(std::forward(args)...);
};
diff --git a/libserene/include/serene/errors/base.h b/libserene/include/serene/errors/base.h
index 8ed7f6e..2358152 100644
--- a/libserene/include/serene/errors/base.h
+++ b/libserene/include/serene/errors/base.h
@@ -28,19 +28,20 @@
namespace serene::errors {
+// This class is used in the generated code
struct ErrorVariant {
- int id;
+ const int id;
const std::string title;
const std::string desc;
const std::string help;
- static ErrorVariant make(int id, const char *t, const char *d,
+ static ErrorVariant make(const int id, const char *t, const char *d,
const char *h) {
return ErrorVariant(id, t, d, h);
};
private:
- ErrorVariant(int id, const char *t, const char *d, const char *h)
+ ErrorVariant(const int id, const char *t, const char *d, const char *h)
: id(id), title(t), desc(d), help(h){};
};
diff --git a/libserene/lib/errors.cpp b/libserene/lib/errors.cpp
index 7bfb922..70f0c93 100644
--- a/libserene/lib/errors.cpp
+++ b/libserene/lib/errors.cpp
@@ -17,6 +17,3 @@
*/
#include "serene/errors.h"
-
-#define GET_ERRS_ARRAY
-#include "serene/errors/errs.h.inc"
diff --git a/libserene/tests/context_tests.cpp.inc b/libserene/tests/context_tests.cpp.inc
index 6a10925..0e4ba8f 100644
--- a/libserene/tests/context_tests.cpp.inc
+++ b/libserene/tests/context_tests.cpp.inc
@@ -21,6 +21,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+#ifndef SERENE_TEST_CONTEXT_H
+#define SERENE_TEST_CONTEXT_H
#include "serene/context.h"
#include "serene/namespace.h"
@@ -162,3 +164,4 @@ TEST_CASE("context and jit", "[context]") {
};
} // namespace serene
+#endif
diff --git a/libserene/tests/errors/error_tests.cpp.inc b/libserene/tests/errors/error_tests.cpp.inc
index bbb2828..47c4bb3 100644
--- a/libserene/tests/errors/error_tests.cpp.inc
+++ b/libserene/tests/errors/error_tests.cpp.inc
@@ -22,25 +22,37 @@
* SOFTWARE.
*/
+#ifndef SERENE_TEST_ERRORS_H
+#define SERENE_TEST_ERRORS_H
+
#include "serene/errors.h"
-#include "serene/exprs/symbol.h"
-#include "../test_helpers.cpp.inc"
-#include
+#include
-#include
+#include
+#include
+#include
namespace serene {
namespace errors {
-TEST_CASE("Error Expression", "[expression]") {
- std::unique_ptr range(dummyLocation());
- auto err = exprs::makeAndCast(*range.get(), &DefExpectSymbol,
- "Something Failed");
+TEST_CASE("Serene Error construction", "[errors]") {
+ {
+ std::unique_ptr range(dummyLocation());
+ llvm::Error err = llvm::make_error(*range, "test error");
- CHECK(err->getVariant()->id == E0001);
- CHECK(err->toString() == "");
-};
+ auto unhandled =
+ llvm::handleErrors(std::move(err), [&](const PassFailureError &e) {
+ REQUIRE(e.message() == "test error");
+ CHECK(errorVariants[e.ID].title == "PassFailureError");
+ CHECK(errorVariants[e.ID].desc == "Pass Failure.");
+ CHECK(errorVariants[e.ID].help.empty());
+ });
+ CHECK(!unhandled);
+ };
} // namespace errors
+}; // namespace errors
} // namespace serene
+
+#endif
diff --git a/libserene/tests/serenetests.cpp b/libserene/tests/serenetests.cpp
index cf4265e..8b61e95 100644
--- a/libserene/tests/serenetests.cpp
+++ b/libserene/tests/serenetests.cpp
@@ -19,8 +19,8 @@
#define CATCH_CONFIG_MAIN
#include "./context_tests.cpp.inc"
#include "./environment_tests.cpp.inc"
+#include "./errors/error_tests.cpp.inc"
#include "./setup.cpp.inc"
-// #include "./errors/error_tests.cpp.inc"
// #include "./exprs/expression_tests.cpp.inc"
// #include "./exprs/list_tests.cpp.inc"
// #include "./exprs/number_tests.cpp.inc"
diff --git a/serene-tblgen/serene/errors-backend.cpp b/serene-tblgen/serene/errors-backend.cpp
index 129e03e..ac7496d 100644
--- a/serene-tblgen/serene/errors-backend.cpp
+++ b/serene-tblgen/serene/errors-backend.cpp
@@ -16,6 +16,14 @@
* along with this program. If not, see .
*/
+/**
+ * Commentary:
+ * This is a `tablegen` backend to read from generate error definitions
+ * from the given tablegen records defined in a `.td` file. It relies on
+ * Two main classes to be available in the target source code. `SereneError`
+ * and `ErrorVariant`. Checkout `libserene/include/serene/errors/base.h`.
+ */
+
// The "serene/" part is due to a convention that we use in the project
#include "serene/errors-backend.h"
@@ -65,48 +73,7 @@ void ErrorsBackend::createErrorClass(const int id, llvm::Record &defRec,
<< "public:\n"
<< " using llvm::ErrorInfo<" << recName << ", "
<< "SereneError>::ErrorInfo;\n"
- << " constexpr static const int ID = " << id << ";\n};\n\n"
- << "static const ErrorVariant " << recName << INSTANCE_SUFFIX
- << " = ErrorVariant::make(\n"
- << " " << id << ",\n"
- << " \"" << recName << "\",\n";
-
- auto desc = defRec.getValueAsString("desc");
-
- if (desc.empty()) {
- llvm::PrintError("'desc' field is empty for " + recName);
- }
-
- os << " \"" << desc << "\",\n";
-
- auto help = defRec.getValueAsString("help");
-
- if (!help.empty()) {
-
- const llvm::MemoryBufferRef value(help, "help");
-
- llvm::line_iterator lines(value, false);
- while (!lines.is_at_end()) {
- if (lines.line_number() != 1) {
- os << '\t';
- }
- auto prevLine = *lines;
- lines++;
- os << '"' << prevLine << '"';
-
- if (lines.is_at_end()) {
- os << ";\n";
- } else {
- os << '\n';
- }
- }
- } else {
- os << " \"\"";
- }
-
- os << ");\n";
- // os << " " << help << ");\n";
- // auto *stringVal = llvm::dyn_cast(val.getValue());
+ << " constexpr static const int ID = " << id << ";\n};\n\n";
};
void ErrorsBackend::createNSBody(llvm::raw_ostream &os) {
@@ -135,41 +102,72 @@ void ErrorsBackend::createNSBody(llvm::raw_ostream &os) {
createErrorClass(i, *defRec, os);
}
- });
- os << "#undef GET_CLASS_DEFS\n#endif\n\n";
+ os << "static const ErrorVariant errorVariants[" << indexList->size()
+ << "] = {\n";
- os << "#ifdef GET_ERRS_ARRAY\n\n";
- inNamespace("serene::errors", os, [&](llvm::raw_ostream &os) {
- os << "SereneError::ID = -1;\n";
- for (size_t i = 0; i < indexList->size(); i++) {
- llvm::Record *defRec = indexList->getElementAsRecord(i);
- os << defRec->getName() << "::ID = " << i << ";\n";
- }
-
- os << "static const std::array "
- "variants{\n";
for (size_t i = 0; i < indexList->size(); i++) {
llvm::Record *defRec = indexList->getElementAsRecord(i);
+ auto recName = defRec->getName();
if (!defRec->isSubClassOf("Error")) {
continue;
}
- os << " &" << defRec->getName() << INSTANCE_SUFFIX << ",\n";
+
+ os << " ErrorVariant::make(" << i << ", \n";
+ os << " \"" << recName << "\",\n";
+
+ auto desc = defRec->getValueAsString("desc");
+
+ if (desc.empty()) {
+ llvm::PrintError("'desc' field is empty for " + recName);
+ }
+
+ os << " \"" << desc << "\",\n";
+
+ auto help = defRec->getValueAsString("help");
+
+ if (!help.empty()) {
+
+ const llvm::MemoryBufferRef value(help, "help");
+
+ llvm::line_iterator lines(value, false);
+ while (!lines.is_at_end()) {
+ if (lines.line_number() != 1) {
+ os << '\t';
+ }
+ auto prevLine = *lines;
+ lines++;
+ os << '"' << prevLine << '"';
+
+ if (lines.is_at_end()) {
+ os << ";\n";
+ } else {
+ os << '\n';
+ }
+ }
+ } else {
+ os << " \"\"";
+ }
+
+ os << "),\n";
}
+
+ os << "};\n";
});
- os << "\n};\n#undef GET_ERRS_ARRAY\n#endif\n";
+
+ os << "#undef GET_CLASS_DEFS\n#endif\n\n";
}
void ErrorsBackend::run(llvm::raw_ostream &os) {
(void)records;
llvm::emitSourceFileHeader("Serene's Errors collection", os);
+ // DO NOT GUARD THE HEADER WITH #ifndef ...
os << "#include \"serene/errors/base.h\"\n\n#include "
"\n\n";
- os << "#ifndef SERENE_ERRORS_ERRORS_H\n#define SERENE_ERRORS_ERRORS_H\n\n";
+
createNSBody(os);
- os << "#endif\n";
}
void emitErrors(llvm::RecordKeeper &rk, llvm::raw_ostream &os) {