Setup the CLI options around the JIT and make it the context owner
This commit is contained in:
parent
c2fb6bf8cb
commit
b71701a640
|
@ -247,13 +247,13 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
|||
# Create the tools we use to compile Serene
|
||||
add_subdirectory(serene-tblgen)
|
||||
|
||||
# Binary tools of the compiler
|
||||
# add_subdirectory(serenec)
|
||||
# add_subdirectory(serene-repl)
|
||||
# The compiled library code is here
|
||||
add_subdirectory(libserene)
|
||||
# The static library containing builtin special forms and functions
|
||||
add_subdirectory(core)
|
||||
# Binary tools of the compiler
|
||||
add_subdirectory(serenec)
|
||||
# add_subdirectory(serene-repl)
|
||||
|
||||
# add_subdirectory(devtools)
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define SERENE_CONTEXT_H
|
||||
|
||||
#include "serene/export.h" // for SERENE_EXPORT
|
||||
#include "serene/options.h"
|
||||
|
||||
#include <llvm/ADT/Triple.h> // for Triple
|
||||
#include <llvm/ADT/Twine.h> // for Twine
|
||||
|
@ -56,24 +57,6 @@ enum class CompilationPhase {
|
|||
/// via the JIT use an appropriate function in the `serene.core` ns.
|
||||
SERENE_EXPORT void terminate(SereneContext &ctx, int exitCode);
|
||||
|
||||
/// Options describes the compiler options that can be passed to the
|
||||
/// compiler via command line. Anything that user should be able to
|
||||
/// tweak about the compiler has to end up here regardless of the
|
||||
/// different subsystem that might use it.
|
||||
struct SERENE_EXPORT Options {
|
||||
|
||||
/// Whether to use colors for the output or not
|
||||
bool withColors = true;
|
||||
|
||||
// JIT related flags
|
||||
bool JITenableObjectCache = true;
|
||||
bool JITenableGDBNotificationListener = true;
|
||||
bool JITenablePerfNotificationListener = true;
|
||||
bool JITLazy = false;
|
||||
|
||||
Options() = default;
|
||||
};
|
||||
|
||||
class SERENE_EXPORT SereneContext {
|
||||
|
||||
public:
|
||||
|
@ -100,6 +83,9 @@ public:
|
|||
return std::make_unique<llvm::LLVMContext>();
|
||||
};
|
||||
|
||||
/// Setup the load path for namespace lookups
|
||||
void setLoadPaths(std::vector<std::string> &dirs) { loadPaths.swap(dirs); };
|
||||
|
||||
// JIT JITDylib related functions ---
|
||||
|
||||
// TODO: For Dylib related functions, make sure that the namespace in questoin
|
||||
|
@ -117,7 +103,7 @@ public:
|
|||
|
||||
private:
|
||||
CompilationPhase targetPhase;
|
||||
|
||||
std::vector<std::string> loadPaths;
|
||||
/// A vector of pointers to all the jitDylibs for namespaces. Usually
|
||||
/// There will be only one pre NS but in case of forceful reloads of a
|
||||
/// namespace there will be more.
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
#ifndef SERENE_JIT_HALLEY_H
|
||||
#define SERENE_JIT_HALLEY_H
|
||||
|
||||
#include "serene/export.h" // for SERENE...
|
||||
#include "serene/context.h" // for Serene...
|
||||
#include "serene/export.h" // for SERENE...
|
||||
|
||||
#include <llvm/ADT/SmallVector.h> // for SmallV...
|
||||
#include <llvm/ADT/StringMap.h> // for StringMap
|
||||
|
@ -59,12 +60,15 @@ class Module;
|
|||
} // namespace llvm
|
||||
|
||||
namespace serene {
|
||||
class SereneContext;
|
||||
|
||||
namespace jit {
|
||||
class Halley;
|
||||
|
||||
using MaybeEngine = llvm::Expected<std::unique_ptr<Halley>>;
|
||||
// Why? This is the lazy man's way to make it easier to replace
|
||||
// the class under the hood later on to test different implementaion
|
||||
// with the same interface
|
||||
using Engine = Halley;
|
||||
using EnginePtr = std::unique_ptr<Engine>;
|
||||
using MaybeEngine = llvm::Expected<EnginePtr>;
|
||||
using MaybeEnginePtr = llvm::Expected<void (*)(void **)>;
|
||||
|
||||
/// A simple object cache following Lang's LLJITWithObjectCache example and
|
||||
|
@ -99,17 +103,20 @@ class SERENE_EXPORT Halley {
|
|||
|
||||
llvm::orc::JITTargetMachineBuilder jtmb;
|
||||
llvm::DataLayout &dl;
|
||||
SereneContext &ctx;
|
||||
|
||||
std::unique_ptr<SereneContext> ctx;
|
||||
|
||||
bool isLazy = false;
|
||||
|
||||
public:
|
||||
Halley(serene::SereneContext &ctx, llvm::orc::JITTargetMachineBuilder &&jtmb,
|
||||
llvm::DataLayout &&dl);
|
||||
Halley(std::unique_ptr<SereneContext> ctx,
|
||||
llvm::orc::JITTargetMachineBuilder &&jtmb, llvm::DataLayout &&dl);
|
||||
|
||||
static MaybeEngine make(serene::SereneContext &ctx,
|
||||
static MaybeEngine make(std::unique_ptr<SereneContext> sereneCtxPtr,
|
||||
llvm::orc::JITTargetMachineBuilder &&jtmb);
|
||||
|
||||
SereneContext &getContext() { return *ctx; };
|
||||
|
||||
void setEngine(std::unique_ptr<llvm::orc::LLJIT> e, bool isLazy);
|
||||
/// Looks up a packed-argument function with the given sym name and returns a
|
||||
/// pointer to it. Propagates errors in case of failure.
|
||||
|
@ -156,7 +163,7 @@ public:
|
|||
void dumpToObjectFile(llvm::StringRef filename);
|
||||
};
|
||||
|
||||
MaybeEngine makeHalleyJIT(SereneContext &ctx);
|
||||
MaybeEngine makeHalleyJIT(std::unique_ptr<SereneContext> ctx);
|
||||
|
||||
} // namespace jit
|
||||
} // namespace serene
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- C++ -*-
|
||||
* Serene Programming Language
|
||||
*
|
||||
* Copyright (c) 2019-2022 Sameer Rahmani <lxsameer@gnu.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SERENE_OPTIONS_H
|
||||
#define SERENE_OPTIONS_H
|
||||
|
||||
#include "serene/export.h"
|
||||
|
||||
namespace serene {
|
||||
/// Options describes the compiler options that can be passed to the
|
||||
/// compiler via command line. Anything that user should be able to
|
||||
/// tweak about the compiler has to end up here regardless of the
|
||||
/// different subsystem that might use it.
|
||||
struct SERENE_EXPORT Options {
|
||||
|
||||
/// Whether to use colors for the output or not
|
||||
bool withColors = true;
|
||||
|
||||
// JIT related flags
|
||||
bool JITenableObjectCache = true;
|
||||
bool JITenableGDBNotificationListener = true;
|
||||
bool JITenablePerfNotificationListener = true;
|
||||
bool JITLazy = false;
|
||||
|
||||
// namespace serene Options() = default;
|
||||
};
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
|
@ -20,11 +20,25 @@
|
|||
#define SERENE_SERENE_H
|
||||
|
||||
#include "serene/export.h" // for SERENE_EXPORT
|
||||
#include "serene/jit/halley.h" // for MaybeEngine
|
||||
#include "serene/jit/halley.h" // for Engine, MaybeEngine
|
||||
#include "serene/options.h" // for Options
|
||||
|
||||
namespace serene {
|
||||
|
||||
serene::jit::MaybeEngine SERENE_EXPORT makeEngine();
|
||||
/// Clinet applications have to call this function before any interaction
|
||||
/// with the Serene's compiler API.
|
||||
void SERENE_EXPORT initSerene();
|
||||
|
||||
/// Register the global CLI options of the serene compiler. If the client
|
||||
/// application needs to setup the compilers options automatically use this
|
||||
/// function in conjunction with `applySereneCLOptions`.
|
||||
void SERENE_EXPORT registerSereneCLOptions();
|
||||
|
||||
/// Applies the global compiler options on the give \p SereneContext. This
|
||||
/// function has to be called after `llvm::cl::ParseCommandLineOptions`.
|
||||
void SERENE_EXPORT applySereneCLOptions(serene::jit::Engine &engine);
|
||||
|
||||
serene::jit::MaybeEngine SERENE_EXPORT makeEngine(Options opts = Options());
|
||||
|
||||
} // namespace serene
|
||||
#endif
|
||||
|
|
|
@ -89,4 +89,7 @@ target_compile_definitions(
|
|||
|
||||
target_link_libraries(serene PRIVATE
|
||||
LLVMOrcJIT
|
||||
LLVMX86CodeGen
|
||||
LLVMX86AsmParser
|
||||
|
||||
${llvm_libs})
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "serene/jit/halley.h"
|
||||
|
||||
#include "serene/context.h" // for Seren...
|
||||
#include "serene/options.h" // for Options
|
||||
|
||||
#include <system_error> // for error...
|
||||
|
||||
|
@ -97,17 +99,17 @@ void ObjectCache::dumpToObjectFile(llvm::StringRef outputFilename) {
|
|||
file->keep();
|
||||
}
|
||||
|
||||
Halley::Halley(serene::SereneContext &ctx,
|
||||
Halley::Halley(std::unique_ptr<SereneContext> ctx,
|
||||
llvm::orc::JITTargetMachineBuilder &&jtmb, llvm::DataLayout &&dl)
|
||||
: cache(ctx.opts.JITenableObjectCache ? new ObjectCache() : nullptr),
|
||||
gdbListener(ctx.opts.JITenableGDBNotificationListener
|
||||
: cache(ctx->opts.JITenableObjectCache ? new ObjectCache() : nullptr),
|
||||
gdbListener(ctx->opts.JITenableGDBNotificationListener
|
||||
|
||||
? llvm::JITEventListener::createGDBRegistrationListener()
|
||||
: nullptr),
|
||||
perfListener(ctx.opts.JITenablePerfNotificationListener
|
||||
perfListener(ctx->opts.JITenablePerfNotificationListener
|
||||
? llvm::JITEventListener::createPerfJITEventListener()
|
||||
: nullptr),
|
||||
jtmb(jtmb), dl(dl), ctx(ctx){};
|
||||
jtmb(jtmb), dl(dl), ctx(std::move(ctx)){};
|
||||
|
||||
// MaybeJITPtr Halley::lookup(exprs::Symbol &sym) const {
|
||||
// HALLEY_LOG("Looking up: " << sym.toString());
|
||||
|
@ -170,16 +172,15 @@ void Halley::dumpToObjectFile(llvm::StringRef filename) {
|
|||
cache->dumpToObjectFile(filename);
|
||||
};
|
||||
|
||||
MaybeEngine Halley::make(SereneContext &serene_ctx,
|
||||
MaybeEngine Halley::make(std::unique_ptr<SereneContext> sereneCtxPtr,
|
||||
llvm::orc::JITTargetMachineBuilder &&jtmb) {
|
||||
|
||||
auto dl = jtmb.getDefaultDataLayoutForTarget();
|
||||
if (!dl) {
|
||||
return dl.takeError();
|
||||
}
|
||||
|
||||
auto jitEngine =
|
||||
std::make_unique<Halley>(serene_ctx, std::move(jtmb), std::move(*dl));
|
||||
auto jitEngine = std::make_unique<Halley>(std::move(sereneCtxPtr),
|
||||
std::move(jtmb), std::move(*dl));
|
||||
|
||||
// Why not the llvmcontext from the SereneContext??
|
||||
// Sice we're going to pass the ownership of this context to a thread
|
||||
|
@ -193,6 +194,9 @@ MaybeEngine Halley::make(SereneContext &serene_ctx,
|
|||
// run it.
|
||||
std::unique_ptr<llvm::LLVMContext> ctx(new llvm::LLVMContext);
|
||||
|
||||
// Since we moved the original sereneCtxPtr into the engine.
|
||||
auto &sereneCtx = jitEngine->getContext();
|
||||
|
||||
// Callback to create the object layer with symbol resolution to current
|
||||
// process and dynamically linked libraries.
|
||||
auto objectLinkingLayerCreator = [&](llvm::orc::ExecutionSession &session,
|
||||
|
@ -217,7 +221,7 @@ MaybeEngine Halley::make(SereneContext &serene_ctx,
|
|||
// cf llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
|
||||
// LLJIT::createObjectLinkingLayer
|
||||
|
||||
if (serene_ctx.triple.isOSBinFormatCOFF()) {
|
||||
if (sereneCtx.triple.isOSBinFormatCOFF()) {
|
||||
objectLayer->setOverrideObjectFlagsWithResponsibilityFlags(true);
|
||||
objectLayer->setAutoClaimResponsibilityForObjectSymbols(true);
|
||||
}
|
||||
|
@ -252,7 +256,7 @@ MaybeEngine Halley::make(SereneContext &serene_ctx,
|
|||
-> llvm::Expected<
|
||||
std::unique_ptr<llvm::orc::IRCompileLayer::IRCompiler>> {
|
||||
llvm::CodeGenOpt::Level jitCodeGenOptLevel =
|
||||
static_cast<llvm::CodeGenOpt::Level>(serene_ctx.getOptimizatioLevel());
|
||||
static_cast<llvm::CodeGenOpt::Level>(sereneCtx.getOptimizatioLevel());
|
||||
|
||||
JTMB.setCodeGenOptLevel(jitCodeGenOptLevel);
|
||||
|
||||
|
@ -265,7 +269,7 @@ MaybeEngine Halley::make(SereneContext &serene_ctx,
|
|||
std::move(*targetMachine), jitEngine->cache.get());
|
||||
};
|
||||
|
||||
if (serene_ctx.opts.JITLazy) {
|
||||
if (sereneCtx.opts.JITLazy) {
|
||||
// Setup a LLLazyJIT instance to the times that latency is important
|
||||
// for example in a REPL. This way
|
||||
|
||||
|
@ -308,10 +312,10 @@ MaybeEngine Halley::make(SereneContext &serene_ctx,
|
|||
return MaybeEngine(std::move(jitEngine));
|
||||
};
|
||||
|
||||
MaybeEngine makeHalleyJIT(SereneContext &ctx) {
|
||||
MaybeEngine makeHalleyJIT(std::unique_ptr<SereneContext> ctx) {
|
||||
|
||||
llvm::orc::JITTargetMachineBuilder jtmb(ctx.triple);
|
||||
auto maybeJIT = Halley::make(ctx, std::move(jtmb));
|
||||
llvm::orc::JITTargetMachineBuilder jtmb(ctx->triple);
|
||||
auto maybeJIT = Halley::make(std::move(ctx), std::move(jtmb));
|
||||
if (!maybeJIT) {
|
||||
return maybeJIT.takeError();
|
||||
}
|
||||
|
|
|
@ -18,13 +18,75 @@
|
|||
|
||||
#include "serene/serene.h"
|
||||
|
||||
#include "serene/jit/halley.h" // for makeHalleyJIT, MaybeEngine
|
||||
#include "serene/context.h" // for SereneContext, makeSereneCon...
|
||||
#include "serene/jit/halley.h" // for makeHalleyJIT, Engine, Maybe...
|
||||
|
||||
#include <llvm/ADT/StringRef.h> // for StringRef
|
||||
#include <llvm/Support/CommandLine.h> // for list, cat, desc, MiscFlags
|
||||
#include <llvm/Support/ManagedStatic.h> // for ManagedStatic
|
||||
#include <llvm/Support/TargetSelect.h> // for InitializeAllAsmParsers, Ini...
|
||||
|
||||
#include <string> // for string
|
||||
#include <utility> // for move
|
||||
|
||||
namespace serene {
|
||||
class SereneContext;
|
||||
// CLI Option ----------------
|
||||
|
||||
serene::jit::MaybeEngine makeEngine(SereneContext &ctx) {
|
||||
return serene::jit::makeHalleyJIT(ctx);
|
||||
/// All the global CLI option ar defined here. If you need to add a new global
|
||||
/// option
|
||||
/// make sure that you are handling it in `applySereneCLOptions` too.
|
||||
struct SereneOptions {
|
||||
|
||||
llvm::cl::OptionCategory clOptionsCategory{"Discovery options"};
|
||||
|
||||
llvm::cl::list<std::string> loadPaths{
|
||||
"l", llvm::cl::desc("The load path to use for compilation."),
|
||||
llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::PositionalEatsArgs,
|
||||
llvm::cl::cat(clOptionsCategory)};
|
||||
|
||||
llvm::cl::list<std::string> sharedLibraryPaths{
|
||||
"sl", llvm::cl::desc("Where to find shared libraries"),
|
||||
llvm::cl::ZeroOrMore, llvm::cl::MiscFlags::PositionalEatsArgs,
|
||||
llvm::cl::cat(clOptionsCategory)};
|
||||
};
|
||||
|
||||
static llvm::ManagedStatic<SereneOptions> options;
|
||||
|
||||
void registerSereneCLOptions() {
|
||||
// Make sure that the options struct has been constructed.
|
||||
*options;
|
||||
|
||||
// #ifdef SERENE_WITH_MLIR_CL_OPTION
|
||||
// // mlir::registerAsmPrinterCLOptions();
|
||||
// mlir::registerMLIRContextCLOptions();
|
||||
// mlir::registerPassManagerCLOptions();
|
||||
// #endif
|
||||
}
|
||||
|
||||
void applySereneCLOptions(serene::jit::Engine &engine) {
|
||||
if (!options.isConstructed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &ctx = engine.getContext();
|
||||
ctx.setLoadPaths(options->loadPaths);
|
||||
|
||||
// #ifdef SERENE_WITH_MLIR_CL_OPTION
|
||||
// mlir::applyPassManagerCLOptions(ctx.pm);
|
||||
// #endif
|
||||
}
|
||||
|
||||
void initSerene() {
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargets();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllAsmParsers();
|
||||
llvm::InitializeAllAsmPrinters();
|
||||
};
|
||||
|
||||
serene::jit::MaybeEngine makeEngine(Options opts) {
|
||||
auto ctx = makeSereneContext(opts);
|
||||
return serene::jit::makeHalleyJIT(std::move(ctx));
|
||||
};
|
||||
|
||||
} // namespace serene
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "serene/config.h"
|
||||
#include "serene/context.h"
|
||||
#include "serene/serene.h"
|
||||
// #include "serene/jit/halley.h"
|
||||
// #include "serene/namespace.h"
|
||||
// #include "serene/reader/location.h"
|
||||
|
@ -36,9 +39,11 @@
|
|||
// #include <llvm/ADT/StringRef.h>
|
||||
// #include <llvm/IR/LegacyPassManager.h>
|
||||
// //#include <llvm/MC/TargetRegistry.h>
|
||||
// #include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
// #include <llvm/Support/FileSystem.h>
|
||||
// #include <llvm/Support/FormatVariadic.h>
|
||||
#include <llvm/Support/FormatVariadic.h>
|
||||
|
||||
#include <iostream>
|
||||
// #include <llvm/Support/Host.h>
|
||||
// #include <llvm/Support/Path.h>
|
||||
// #include <llvm/Support/raw_ostream.h>
|
||||
|
@ -48,9 +53,9 @@
|
|||
// #include <memory>
|
||||
|
||||
// using namespace std;
|
||||
// using namespace serene;
|
||||
using namespace serene;
|
||||
|
||||
// namespace cl = llvm::cl;
|
||||
namespace cl = llvm::cl;
|
||||
|
||||
// namespace {
|
||||
// enum Action {
|
||||
|
@ -68,15 +73,15 @@
|
|||
// };
|
||||
// } // namespace
|
||||
|
||||
// static std::string banner =
|
||||
// llvm::formatv("\n\nSerene Compiler Version {0}"
|
||||
// "\nCopyright (C) 2019-2022 "
|
||||
// "Sameer Rahmani <lxsameer@gnu.org>\n"
|
||||
// "Serene comes with ABSOLUTELY NO WARRANTY;\n"
|
||||
// "This is free software, and you are welcome\n"
|
||||
// "to redistribute it under certain conditions; \n"
|
||||
// "for details take a look at the LICENSE file.\n",
|
||||
// SERENE_VERSION);
|
||||
static std::string banner =
|
||||
llvm::formatv("\n\nSerene Compiler Version {0}"
|
||||
"\nCopyright (C) 2019-2022 "
|
||||
"Sameer Rahmani <lxsameer@gnu.org>\n"
|
||||
"Serene comes with ABSOLUTELY NO WARRANTY;\n"
|
||||
"This is free software, and you are welcome\n"
|
||||
"to redistribute it under certain conditions; \n"
|
||||
"for details take a look at the LICENSE file.\n",
|
||||
SERENE_VERSION);
|
||||
|
||||
// static cl::opt<std::string> inputNS(cl::Positional, cl::desc("<namespace>"),
|
||||
// cl::Required);
|
||||
|
@ -256,15 +261,21 @@
|
|||
// return 0;
|
||||
// };
|
||||
|
||||
int main() {
|
||||
// initCompiler();
|
||||
// registerSereneCLOptions();
|
||||
int main(int argc, char *argv[]) {
|
||||
initSerene();
|
||||
registerSereneCLOptions();
|
||||
|
||||
// cl::ParseCommandLineOptions(argc, argv, banner);
|
||||
cl::ParseCommandLineOptions(argc, argv, banner);
|
||||
|
||||
// auto ctx = makeSereneContext();
|
||||
auto engine = makeEngine();
|
||||
|
||||
// applySereneCLOptions(*ctx);
|
||||
if (!engine) {
|
||||
llvm::errs() << "Error: Couldn't create the engine due to '"
|
||||
<< engine.takeError() << "'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
applySereneCLOptions(*(*engine));
|
||||
|
||||
// // TODO: handle the outputDir by not forcing it. it should be
|
||||
// // default to the current working dir
|
||||
|
|
Loading…
Reference in New Issue