Clean up the halley files

This commit is contained in:
Sameer Rahmani 2022-03-29 19:55:42 +01:00
parent b9496b429e
commit 7050e7d53d
7 changed files with 46 additions and 58 deletions

View File

@ -925,7 +925,8 @@ CLOSED: [2022-02-26 Sat 12:50]
#+RESULTS: ep-16-jit-3
[[file:/tmp/ep16-3.svg]]
* Episode 17 - Custom ORC Layers
* DONE Episode 17 - Custom ORC Layers
CLOSED: [2022-03-28 Mon 14:00]
** Updates:
- Finished the basic compiler wiring
- Restructured the source tree
@ -952,3 +953,10 @@ Let's have a look at the =MaterializationUnit= class.
*** And the layer class itself
The layer classes are not special but conventionally the come with few functions
like: =add=, =emit= and =getInterface=.
* Episode 18 - JIT Engine Part 1
** =Halley= JIT Engine
- It's not the final implementation
- Wraps LLJIT and LLLazyJIT
- Uses object cache layer
- Supports ASTs and Namespaces

View File

@ -18,7 +18,15 @@
/**
* Commentary:
* The code is based on the MLIR's JIT and named after Edmond Halley.
This is the first working attempt on building a JIT engine for Serene
and named after Edmond Halley.
- It supports both ASTs and Namespaces
- Every Namespace might have one or more JITDylibs. Depends on the method
of the compilation.
- It operates in lazy (for REPL) and non-lazy mode and wraps LLJIT
and LLLazyJIT
- It uses an object cache layer to cache module (not NSs) objects.
*/
#ifndef SERENE_JIT_HALLEY_H
@ -51,13 +59,14 @@ class Namespace;
namespace exprs {
class Symbol;
}
} // namespace exprs
namespace jit {
class Halley;
using MaybeJIT = llvm::Expected<std::unique_ptr<Halley>>;
using MaybeJITPtr = llvm::Expected<void (*)(void **)>;
/// A simple object cache following Lang's LLJITWithObjectCache example and
/// MLIR's SimpelObjectCache.
class ObjectCache : public llvm::ObjectCache {
@ -100,14 +109,12 @@ public:
Halley(serene::SereneContext &ctx, llvm::orc::JITTargetMachineBuilder &&jtmb,
llvm::DataLayout &&dl);
// TODO: Read the sharedLibPaths via context
static MaybeJIT make(serene::SereneContext &ctx,
llvm::orc::JITTargetMachineBuilder &&jtmb);
void setEngine(std::unique_ptr<llvm::orc::LLJIT> e, bool isLazy);
/// Looks up a packed-argument function with the given name and returns a
/// pointer to it. Propagates errors in case of failure.
// llvm::Expected<void (*)(void **)> lookup(llvm::StringRef name) const;
/// Looks up a packed-argument function with the given sym name and returns a
/// pointer to it. Propagates errors in case of failure.
MaybeJITPtr lookup(exprs::Symbol &sym) const;
/// Invokes the function with the given name passing it the list of opaque
@ -174,11 +181,6 @@ public:
void dumpToObjectFile(llvm::StringRef filename);
/// Register symbols with this ExecutionEngine.
void registerSymbols(
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
symbolMap);
llvm::Error addNS(Namespace &ns, reader::LocationRange &loc);
llvm::Error addAST(exprs::Ast &ast);

View File

@ -57,15 +57,9 @@
namespace serene {
namespace jit {
// TODO: Remove this function and replace it by our own version of
// error handler
/// Wrap a string into an llvm::StringError.
// static llvm::Error make_string_error(const llvm::Twine &message) {
// return llvm::make_error<llvm::StringError>(message.str(),
// llvm::inconvertibleErrorCode());
// }
static std::string makePackedFunctionName(llvm::StringRef name) {
// TODO: move the "_serene_" constant to a macro or something
return "_serene_" + name.str();
}
@ -207,13 +201,13 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
auto expectedSymbol =
engine->lookup(*dylib, makePackedFunctionName(sym.name));
// auto expectedSymbol = engine->lookup(name);
// JIT lookup may return an Error referring to strings stored internally by
// the JIT. If the Error outlives the ExecutionEngine, it would want have a
// dangling reference, which is currently caught by an assertion inside JIT
// thanks to hand-rolled reference counting. Rewrap the error message into a
// string before returning. Alternatively, ORC JIT should consider copying
// the string into the error message.
// JIT lookup may return an Error referring to strings stored internally by
// the JIT. If the Error outlives the ExecutionEngine, it would want have a
// dangling reference, which is currently caught by an assertion inside JIT
// thanks to hand-rolled reference counting. Rewrap the error message into a
// string before returning. Alternatively, ORC JIT should consider copying
// the string into the error message.
if (!expectedSymbol) {
std::string errorMessage;
llvm::raw_string_ostream os(errorMessage);
@ -235,19 +229,6 @@ MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
return fptr;
};
void createObjectFile(SereneContext &ctx, llvm::StringRef name,
llvm::MemoryBufferRef objBuffer) {
std::string errorMessage;
auto file = mlir::openOutputFile(name, &errorMessage);
if (!file) {
panic(ctx, errorMessage);
}
file->os() << objBuffer.getBuffer();
file->keep();
}
// llvm::Error Halley::invokePacked(llvm::StringRef name,
// llvm::MutableArrayRef<void *> args) const {
// auto expectedFPtr = lookup(name);
@ -261,15 +242,6 @@ void createObjectFile(SereneContext &ctx, llvm::StringRef name,
// return llvm::Error::success();
// }
void Halley::registerSymbols(
llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)>
symbolMap) {
auto &mainJitDylib = engine->getMainJITDylib();
cantFail(mainJitDylib.define(
absoluteSymbols(symbolMap(llvm::orc::MangleAndInterner(
mainJitDylib.getExecutionSession(), engine->getDataLayout())))));
};
llvm::Error Halley::addNS(Namespace &ns, reader::LocationRange &loc) {
HALLEY_LOG(llvm::formatv("Creating Dylib {0}#{1}", ns.name,

View File

@ -57,8 +57,7 @@ TEST_CASE("getMessage function", "[errors]") {
llvm::Error err = makeError(*ctx, PassFailureError, *range, "test error");
CHECK(getMessage(err) == "test error");
CHECK_ERR(PassFailureError, std::move(err));
CHECK_SERENE_ERR(PassFailureError, std::move(err));
}
}; // namespace errors

View File

@ -88,19 +88,19 @@ TEST_CASE("List semantic analysis of 'def'", "[semantic,expression,list]") {
auto afterAst = semantics::analyze(state, ast);
REQUIRE_FALSE(afterAst);
CHECK_ERR(llvm::ErrorList, afterAst.takeError());
{
auto err = afterAst.takeError();
CHECK(err.isA<llvm::ErrorList>());
}
ast = llvm::cantFail(READ("(def a)"));
afterAst = semantics::analyze(state, ast);
REQUIRE_FALSE(afterAst);
CHECK(errors::getMessage(afterAst.takeError()) ==
"<Error E2: Expected 3 got 2>");
CHECK(errors::getMessage(afterAst.takeError()) == "Expected 3 got 2");
ast = llvm::cantFail(READ("(def a b c)"));
afterAst = semantics::analyze(state, ast);
REQUIRE_FALSE(afterAst);
CHECK(errors::getMessage(afterAst.takeError()) ==
"<Error E2: Expected 3 got 4>");
CHECK(errors::getMessage(afterAst.takeError()) == "Expected 3 got 4");
ast = llvm::cantFail(READ("(def a b)"));
afterAst = semantics::analyze(state, ast);

View File

@ -21,7 +21,7 @@
#include "./environment_tests.cpp.inc"
#include "./errors/error_tests.cpp.inc"
#include "./exprs/expression_tests.cpp.inc"
//#include "./exprs/list_tests.cpp.inc"
#include "./exprs/list_tests.cpp.inc"
#include "./exprs/number_tests.cpp.inc"
#include "./exprs/symbol_tests.cpp.inc"
#include "./setup.cpp.inc"

View File

@ -30,11 +30,18 @@
// `llvm::Error`s has to be checked in the same scope. This macro makes
// the check easy while were testing the other aspects of the error.
// `t` is the concrete error type and `e` is the error instance.
#define CHECK_ERR(t, e) \
#define CHECK_SERENE_ERR(t, e) \
auto unhandled = llvm::handleErrors( \
e, [&](const SereneError &x) { CHECK(x.errorType == t); }); \
CHECK(!unhandled);
#define CHECK_ERR(t, e) \
auto unhandled = llvm::handleErrors(e, [&](const t &x) { \
(void)x; \
CHECK(true); \
}); \
CHECK(!unhandled);
namespace serene {
reader::LocationRange *dummyLocation() {