feat: publish Dever core with project scaffolding and versioned AI skills
This commit is contained in:
1 parent
70fa73cdc2
commit
ac458ffa7f
960 files changed
+221319
-1163
No files matched your search
@@ -0,0 +1,154 @@
|
||||
// Private LLVM 18 / LLD bridge. Inputs are borrowed only for the call; outputs
|
||||
// use malloc/free through one ABI and never expose LLVM ownership to Rust.
|
||||
#include "lld/Common/Driver.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/IRReader/IRReader.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Passes/PassBuilder.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
|
||||
LLD_HAS_DRIVER(elf)
|
||||
LLD_HAS_DRIVER(coff)
|
||||
LLD_HAS_DRIVER(macho)
|
||||
|
||||
struct Reply {
|
||||
unsigned char *bytes;
|
||||
size_t len;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
struct Resource {
|
||||
const unsigned char *symbol;
|
||||
size_t symbol_len;
|
||||
const unsigned char *bytes;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static void answer(Reply *reply, llvm::StringRef bytes, uint32_t status) {
|
||||
constexpr size_t limit = 320 * 1024 * 1024;
|
||||
if (bytes.size() > limit) {
|
||||
bytes = "compiler bridge output exceeds 320 MiB";
|
||||
status = 1;
|
||||
}
|
||||
reply->status = status;
|
||||
reply->len = bytes.size();
|
||||
reply->bytes = static_cast<unsigned char *>(std::malloc(bytes.size()));
|
||||
if (!reply->bytes && !bytes.empty()) {
|
||||
reply->len = 0;
|
||||
reply->status = 1;
|
||||
return;
|
||||
}
|
||||
if (!bytes.empty()) std::memcpy(reply->bytes, bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
extern "C" void dever_backend_free(unsigned char *bytes) { std::free(bytes); }
|
||||
|
||||
extern "C" void dever_backend_object(const unsigned char *ir, size_t len,
|
||||
const char *triple, const Resource *resources,
|
||||
size_t resource_count, Reply *reply) {
|
||||
try {
|
||||
static std::once_flag initialized;
|
||||
std::call_once(initialized, [] {
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargets();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllAsmPrinters();
|
||||
llvm::InitializeAllAsmParsers();
|
||||
});
|
||||
llvm::LLVMContext context;
|
||||
llvm::SMDiagnostic diagnostic;
|
||||
auto input = llvm::MemoryBuffer::getMemBufferCopy(
|
||||
llvm::StringRef(reinterpret_cast<const char *>(ir), len), "dever.ir");
|
||||
auto module = llvm::parseIR(input->getMemBufferRef(), diagnostic, context);
|
||||
std::string error;
|
||||
llvm::raw_string_ostream errors(error);
|
||||
if (!module) {
|
||||
diagnostic.print("dever", errors);
|
||||
return answer(reply, error, 1);
|
||||
}
|
||||
// Do not silently compile a module for a target different from its ABI.
|
||||
if (!module->getTargetTriple().empty() && module->getTargetTriple() != triple)
|
||||
return answer(reply, "LLVM module target disagrees with selected target", 1);
|
||||
for (size_t index = 0; index < resource_count; ++index) {
|
||||
const auto &resource = resources[index];
|
||||
auto *global = module->getNamedGlobal(llvm::StringRef(
|
||||
reinterpret_cast<const char *>(resource.symbol), resource.symbol_len));
|
||||
auto *array = global ? llvm::dyn_cast<llvm::ArrayType>(global->getValueType()) : nullptr;
|
||||
if (!global || !global->isDeclaration() || !global->isConstant() ||
|
||||
!global->hasExternalLinkage() || global->isThreadLocal() ||
|
||||
global->getAddressSpace() != 0 || !array ||
|
||||
!array->getElementType()->isIntegerTy(8) ||
|
||||
array->getNumElements() != resource.len || global->use_empty())
|
||||
return answer(reply, "LLVM resource must match a used external constant byte-array declaration", 1);
|
||||
global->setInitializer(llvm::ConstantDataArray::get(
|
||||
context, llvm::ArrayRef<uint8_t>(resource.bytes, resource.len)));
|
||||
global->setLinkage(llvm::GlobalValue::PrivateLinkage);
|
||||
}
|
||||
if (llvm::verifyModule(*module, &errors)) return answer(reply, error, 1);
|
||||
auto target = llvm::TargetRegistry::lookupTarget(triple, error);
|
||||
if (!target) return answer(reply, error, 1);
|
||||
llvm::TargetOptions options;
|
||||
std::unique_ptr<llvm::TargetMachine> machine(target->createTargetMachine(
|
||||
triple, "generic", "", options, llvm::Reloc::PIC_, std::nullopt,
|
||||
llvm::CodeGenOptLevel::Default));
|
||||
if (!machine) return answer(reply, "LLVM target machine is unavailable", 1);
|
||||
auto layout = machine->createDataLayout();
|
||||
if (!module->getDataLayoutStr().empty() && module->getDataLayout() != layout)
|
||||
return answer(reply, "LLVM module layout disagrees with selected target", 1);
|
||||
module->setTargetTriple(triple);
|
||||
module->setDataLayout(layout);
|
||||
llvm::PassBuilder passes(machine.get());
|
||||
llvm::LoopAnalysisManager loops;
|
||||
llvm::FunctionAnalysisManager functions;
|
||||
llvm::CGSCCAnalysisManager calls;
|
||||
llvm::ModuleAnalysisManager modules;
|
||||
passes.registerModuleAnalyses(modules);
|
||||
passes.registerCGSCCAnalyses(calls);
|
||||
passes.registerFunctionAnalyses(functions);
|
||||
passes.registerLoopAnalyses(loops);
|
||||
passes.crossRegisterProxies(loops, functions, calls, modules);
|
||||
auto pipeline = passes.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O2);
|
||||
pipeline.run(*module, modules);
|
||||
if (llvm::verifyModule(*module, &errors)) return answer(reply, error, 1);
|
||||
llvm::SmallVector<char, 0> output;
|
||||
llvm::raw_svector_ostream stream(output);
|
||||
llvm::legacy::PassManager emission;
|
||||
if (machine->addPassesToEmitFile(emission, stream, nullptr,
|
||||
llvm::CodeGenFileType::ObjectFile))
|
||||
return answer(reply, "LLVM target cannot emit native objects", 1);
|
||||
emission.run(*module);
|
||||
answer(reply, llvm::StringRef(output.data(), output.size()), 0);
|
||||
} catch (const std::exception &error) {
|
||||
answer(reply, error.what(), 1);
|
||||
} catch (...) {
|
||||
answer(reply, "LLVM bridge failed", 1);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void dever_backend_link(const char *const *args, size_t count,
|
||||
Reply *reply) {
|
||||
try {
|
||||
std::string output, error;
|
||||
llvm::raw_string_ostream out(output), err(error);
|
||||
const lld::DriverDef drivers[] = {{lld::Gnu, lld::elf::link},
|
||||
{lld::WinLink, lld::coff::link},
|
||||
{lld::Darwin, lld::macho::link}};
|
||||
auto result = lld::lldMain(llvm::ArrayRef(args, count), out, err, drivers);
|
||||
// LLD explicitly forbids cleanup/re-entry after failed crash recovery.
|
||||
// This bridge belongs to a compiler worker, never an application process.
|
||||
if (!result.canRunAgain) lld::exitLld(result.retCode ? result.retCode : 1);
|
||||
answer(reply, error, result.retCode == 0 ? 0 : 1);
|
||||
} catch (const std::exception &) {
|
||||
lld::exitLld(1);
|
||||
} catch (...) {
|
||||
lld::exitLld(1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user