self-hosted: build against zig_llvm and embedded LLD

Now the self-hosted compiler re-uses the same C++ code for interfacing
with LLVM as the C++ code.
It also links against the same LLD library files.
This commit is contained in:
Andrew Kelley
2017-12-26 19:44:08 -05:00
parent 2a25398c86
commit 6fece14cfb
22 changed files with 736 additions and 461 deletions

View File

@@ -13,7 +13,7 @@
* 3. Prevent C++ from infecting the rest of the project.
*/
#include "zig_llvm.hpp"
#include "zig_llvm.h"
#include <llvm/Analysis/TargetLibraryInfo.h>
#include <llvm/Analysis/TargetTransformInfo.h>
@@ -39,8 +39,35 @@
#include <lld/Driver/Driver.h>
#include <new>
#include <stdlib.h>
#if defined(_MSC_VER)
#define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
#else
#define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
#endif
using namespace llvm;
template<typename T, typename... Args>
ATTRIBUTE_RETURNS_NOALIAS static inline T * create(Args... args) {
T * ptr = reinterpret_cast<T*>(malloc(sizeof(T)));
if (ptr == nullptr)
return nullptr;
new (ptr) T(args...);
return ptr;
}
template<typename T>
static inline void destroy(T * ptr) {
if (ptr != nullptr) {
ptr[0].~T();
}
free(ptr);
}
void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R) {
initializeLoopStrengthReducePass(*unwrap(R));
}
@@ -50,8 +77,7 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R) {
}
char *ZigLLVMGetHostCPUName(void) {
std::string str = sys::getHostCPUName();
return strdup(str.c_str());
return strdup((const char *)sys::getHostCPUName().bytes_begin());
}
char *ZigLLVMGetNativeFeatures(void) {
@@ -63,11 +89,11 @@ char *ZigLLVMGetNativeFeatures(void) {
features.AddFeature(F.first(), F.second);
}
return strdup(features.getString().c_str());
return strdup((const char *)StringRef(features.getString()).bytes_begin());
}
static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
PM.add(createAddDiscriminatorsPass());
PM.add(createAddDiscriminatorsPass());
}
#ifndef NDEBUG
@@ -82,7 +108,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
std::error_code EC;
raw_fd_ostream dest(filename, EC, sys::fs::F_None);
if (EC) {
*error_message = strdup(EC.message().c_str());
*error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
return true;
}
TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
@@ -90,7 +116,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
Module* module = unwrap(module_ref);
PassManagerBuilder *PMBuilder = new PassManagerBuilder();
PassManagerBuilder *PMBuilder = create<PassManagerBuilder>();
PMBuilder->OptLevel = target_machine->getOptLevel();
PMBuilder->SizeLevel = 0;
@@ -123,7 +149,7 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
// Set up the per-function pass manager.
legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
FPM.add(new TargetLibraryInfoWrapperPass(tlii));
FPM.add(create<TargetLibraryInfoWrapperPass>(tlii));
FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
if (assertions_on) {
FPM.add(createVerifierPass());
@@ -415,7 +441,10 @@ unsigned ZigLLVMTag_DW_union_type(void) {
}
ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) {
DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved);
DIBuilder *di_builder = reinterpret_cast<DIBuilder*>(malloc(sizeof(DIBuilder)));
if (di_builder == nullptr)
return nullptr;
new (di_builder) DIBuilder(*unwrap(module), allow_unresolved);
return reinterpret_cast<ZigLLVMDIBuilder *>(di_builder);
}
@@ -617,7 +646,7 @@ void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn_ref) {
func->setAttributes(new_attr_set);
}
void ZigLLVMParseCommandLineOptions(int argc, const char *const *argv) {
void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
llvm::cl::ParseCommandLineOptions(argc, argv);
}
@@ -771,29 +800,35 @@ LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLV
}
#include "buffer.hpp"
class MyOStream: public raw_ostream {
public:
MyOStream(void (*_append_diagnostic)(void *, const char *, size_t), void *_context) :
raw_ostream(true), append_diagnostic(_append_diagnostic), context(_context), pos(0) {
bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, Buf *diag_buf) {
}
void write_impl(const char *ptr, size_t len) override {
append_diagnostic(context, ptr, len);
pos += len;
}
uint64_t current_pos() const override {
return pos;
}
void (*append_diagnostic)(void *, const char *, size_t);
void *context;
size_t pos;
};
bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
void (*append_diagnostic)(void *, const char *, size_t), void *context)
{
ArrayRef<const char *> array_ref_args(args, arg_count);
buf_resize(diag_buf, 0);
class MyOStream: public raw_ostream {
public:
MyOStream(Buf *_diag_buf) : raw_ostream(true), diag_buf(_diag_buf) {
}
void write_impl(const char *ptr, size_t len) override {
buf_append_mem(diag_buf, ptr, len);
}
uint64_t current_pos() const override {
return buf_len(diag_buf);
}
Buf *diag_buf;
} diag(diag_buf);
MyOStream diag(append_diagnostic, context);
switch (oformat) {
case ZigLLVM_UnknownObjectFormat:
zig_unreachable();
assert(false); // unreachable
case ZigLLVM_COFF:
return lld::coff::link(array_ref_args, false, diag);
@@ -805,7 +840,8 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_
return lld::mach_o::link(array_ref_args, diag);
case ZigLLVM_Wasm:
zig_panic("ZigLLDLink for Wasm");
assert(false); // TODO ZigLLDLink for Wasm
}
zig_unreachable();
assert(false); // unreachable
abort();
}