Clean up the halley files
This commit is contained in:
parent
b9496b429e
commit
7050e7d53d
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue