2021-11-01 15:09:11 +00:00
|
|
|
/* -*- C++ -*-
|
|
|
|
* Serene Programming Language
|
|
|
|
*
|
|
|
|
* Copyright (c) 2019-2021 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "serene/jit/layers.h"
|
|
|
|
|
|
|
|
#include "serene/context.h"
|
2021-11-12 11:49:45 +00:00
|
|
|
#include "serene/exprs/fn.h"
|
|
|
|
#include "serene/exprs/traits.h"
|
2021-11-01 15:09:11 +00:00
|
|
|
|
|
|
|
#include <llvm/ExecutionEngine/Orc/ThreadSafeModule.h>
|
|
|
|
#include <llvm/Support/Error.h> // for report_fatal_error
|
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
2021-11-01 15:09:11 +00:00
|
|
|
namespace serene::jit {
|
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
llvm::orc::ThreadSafeModule compileAst(Namespace &ns, exprs::Ast &ast) {
|
2021-11-01 15:09:11 +00:00
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
assert(ns.getTree().size() < ast.size() && "Did you add the ast to the NS?");
|
2021-11-01 15:09:11 +00:00
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
LAYER_LOG("Compile in context of namespace: " + ns.name);
|
|
|
|
unsigned offset = ns.getTree().size() - ast.size();
|
2021-11-01 15:09:11 +00:00
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
auto maybeModule = ns.compileToLLVMFromOffset(offset);
|
2021-11-01 15:09:11 +00:00
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
if (!maybeModule) {
|
|
|
|
// TODO: Handle failure
|
|
|
|
llvm::report_fatal_error("Couldn't compile lazily JIT'd function");
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::move(maybeModule.getValue());
|
|
|
|
};
|
|
|
|
|
|
|
|
AstMaterializationUnit::AstMaterializationUnit(Namespace &ns, AstLayer &l,
|
|
|
|
exprs::Ast &ast)
|
2021-12-15 17:26:08 +00:00
|
|
|
: orc::MaterializationUnit(l.getInterface(ns, ast)), ns(ns), astLayer(l),
|
|
|
|
ast(ast){};
|
2021-11-19 00:41:28 +00:00
|
|
|
|
|
|
|
void AstMaterializationUnit::materialize(
|
|
|
|
std::unique_ptr<orc::MaterializationResponsibility> r) {
|
|
|
|
astLayer.emit(std::move(r), ns, ast);
|
|
|
|
}
|
|
|
|
|
2021-12-15 17:26:08 +00:00
|
|
|
orc::MaterializationUnit::Interface AstLayer::getInterface(Namespace &ns,
|
|
|
|
exprs::Ast &e) {
|
2021-11-19 00:41:28 +00:00
|
|
|
orc::SymbolFlagsMap Symbols;
|
|
|
|
auto symList = ns.getSymList();
|
|
|
|
unsigned index = symList.size();
|
|
|
|
|
|
|
|
// This probably will change symList
|
|
|
|
auto err = ns.addTree(e);
|
2021-11-01 15:09:11 +00:00
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
if (err) {
|
|
|
|
// TODO: Fix this by a call to diag engine or return the err
|
|
|
|
llvm::outs() << "Fixme: semantic err\n";
|
2021-12-15 17:26:08 +00:00
|
|
|
return orc::MaterializationUnit::Interface(std::move(Symbols), nullptr);
|
2021-11-19 00:41:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto &env = ns.getRootEnv();
|
|
|
|
auto populateTableFn = [&env, this, &Symbols](auto name) {
|
|
|
|
auto flags = llvm::JITSymbolFlags::Exported;
|
|
|
|
auto maybeExpr = env.lookup(name.str());
|
|
|
|
|
|
|
|
if (!maybeExpr) {
|
|
|
|
LAYER_LOG("Skiping '" + name + "' symbol");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto expr = maybeExpr.getValue();
|
|
|
|
|
|
|
|
if (expr->getType() == exprs::ExprType::Fn) {
|
|
|
|
flags = flags | llvm::JITSymbolFlags::Callable;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto mangledSym = this->mangler(name);
|
|
|
|
LAYER_LOG("Mangle symbol for: " + name + " = " << mangledSym);
|
|
|
|
Symbols[mangledSym] = llvm::JITSymbolFlags(flags);
|
|
|
|
};
|
|
|
|
|
|
|
|
std::for_each(symList.begin() + index, symList.end(), populateTableFn);
|
2021-12-15 17:26:08 +00:00
|
|
|
return orc::MaterializationUnit::Interface(std::move(Symbols), nullptr);
|
2021-11-19 00:41:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// NS Layer ==================================================================
|
2021-11-06 21:23:37 +00:00
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
llvm::orc::ThreadSafeModule compileNS(Namespace &ns) {
|
2021-11-06 21:23:37 +00:00
|
|
|
LAYER_LOG("Compile namespace: " + ns.name);
|
|
|
|
|
2021-11-01 15:09:11 +00:00
|
|
|
auto maybeModule = ns.compileToLLVM();
|
|
|
|
|
|
|
|
if (!maybeModule) {
|
|
|
|
// TODO: Handle failure
|
|
|
|
llvm::report_fatal_error("Couldn't compile lazily JIT'd function");
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::move(maybeModule.getValue());
|
|
|
|
};
|
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
NSMaterializationUnit::NSMaterializationUnit(NSLayer &l, Namespace &ns)
|
2021-12-15 17:26:08 +00:00
|
|
|
: MaterializationUnit(l.getInterface(ns)), nsLayer(l), ns(ns){};
|
2021-11-01 15:09:11 +00:00
|
|
|
|
|
|
|
void NSMaterializationUnit::materialize(
|
|
|
|
std::unique_ptr<orc::MaterializationResponsibility> r) {
|
|
|
|
nsLayer.emit(std::move(r), ns);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Error NSLayer::add(orc::ResourceTrackerSP &rt, llvm::StringRef nsname,
|
|
|
|
reader::LocationRange &loc) {
|
|
|
|
|
2021-11-06 21:23:37 +00:00
|
|
|
LAYER_LOG("Add namespace: " + nsname);
|
2022-01-01 22:15:30 +00:00
|
|
|
auto maybeNS = ctx.readNamespace(nsname.str(), loc);
|
2021-11-01 15:09:11 +00:00
|
|
|
|
|
|
|
if (!maybeNS) {
|
|
|
|
// TODO: Fix this by making Serene errors compatible with llvm::Error
|
|
|
|
auto err = maybeNS.getError();
|
|
|
|
return llvm::make_error<llvm::StringError>(
|
|
|
|
llvm::Twine(err.front()->getMessage()),
|
|
|
|
std::make_error_code(std::errc::io_error));
|
|
|
|
}
|
|
|
|
|
|
|
|
auto ns = maybeNS.getValue();
|
|
|
|
|
2021-11-06 21:23:37 +00:00
|
|
|
LAYER_LOG("Add the materialize unit for: " + nsname);
|
2021-11-01 15:09:11 +00:00
|
|
|
return rt->getJITDylib().define(
|
2021-11-19 00:41:28 +00:00
|
|
|
std::make_unique<NSMaterializationUnit>(*this, *ns), rt);
|
2021-11-01 15:09:11 +00:00
|
|
|
}
|
|
|
|
|
2021-12-15 17:26:08 +00:00
|
|
|
orc::MaterializationUnit::Interface
|
|
|
|
NSLayer::getInterface(serene::Namespace &ns) {
|
2021-11-01 15:09:11 +00:00
|
|
|
orc::SymbolFlagsMap Symbols;
|
|
|
|
|
2021-11-17 17:37:45 +00:00
|
|
|
for (auto &k : ns.getRootEnv()) {
|
2021-11-12 11:49:45 +00:00
|
|
|
auto flags = llvm::JITSymbolFlags::Exported;
|
|
|
|
auto name = k.getFirst();
|
|
|
|
auto expr = k.getSecond();
|
|
|
|
|
|
|
|
if (expr->getType() == exprs::ExprType::Fn) {
|
|
|
|
flags = flags | llvm::JITSymbolFlags::Callable;
|
|
|
|
}
|
|
|
|
|
2021-11-19 00:41:28 +00:00
|
|
|
auto mangledSym = mangler(name);
|
|
|
|
LAYER_LOG("Mangle symbol for: " + name + " = " << mangledSym);
|
2021-11-12 11:49:45 +00:00
|
|
|
Symbols[mangledSym] = llvm::JITSymbolFlags(flags);
|
2021-11-01 15:09:11 +00:00
|
|
|
}
|
|
|
|
|
2021-12-15 17:26:08 +00:00
|
|
|
return orc::MaterializationUnit::Interface(std::move(Symbols), nullptr);
|
2021-11-01 15:09:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace serene::jit
|