Commit 6fece14cfb

Andrew Kelley <superjoe30@gmail.com>
2017-12-27 01:44:08
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.
1 parent 2a25398
src/all_types.hpp
@@ -10,7 +10,7 @@
 
 #include "list.hpp"
 #include "buffer.hpp"
-#include "zig_llvm.hpp"
+#include "zig_llvm.h"
 #include "hash_map.hpp"
 #include "errmsg.hpp"
 #include "bigint.hpp"
src/analyze.cpp
@@ -14,7 +14,7 @@
 #include "os.hpp"
 #include "parser.hpp"
 #include "softfloat.hpp"
-#include "zig_llvm.hpp"
+#include "zig_llvm.h"
 
 
 static const size_t default_backward_branch_quota = 1000;
src/codegen.cpp
@@ -17,7 +17,7 @@
 #include "os.hpp"
 #include "translate_c.hpp"
 #include "target.hpp"
-#include "zig_llvm.hpp"
+#include "zig_llvm.h"
 
 #include <stdio.h>
 #include <errno.h>
src/config.h.in
@@ -24,4 +24,8 @@
 // Only used for running tests before installing.
 #define ZIG_TEST_DIR "@CMAKE_SOURCE_DIR@/test"
 
+// Used for communicating build information to self hosted build.
+#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@"
+#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@"
+
 #endif
src/link.cpp
@@ -351,6 +351,16 @@ static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
     }
 }
 
+static void link_diag_callback(void *context, const char *ptr, size_t len) {
+    Buf *diag = reinterpret_cast<Buf *>(context);
+    buf_append_mem(diag, ptr, len);
+}
+
+static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, Buf *diag) {
+    buf_resize(diag, 0);
+    return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag);
+}
+
 static void construct_linker_job_coff(LinkJob *lj) {
     CodeGen *g = lj->codegen;
 
@@ -515,7 +525,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
             gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
             gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
             Buf diag = BUF_INIT;
-            if (!ZigLLDLink(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) {
+            if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) {
                 fprintf(stderr, "%s\n", buf_ptr(&diag));
                 exit(1);
             }
@@ -930,7 +940,7 @@ void codegen_link(CodeGen *g, const char *out_file) {
     Buf diag = BUF_INIT;
 
     codegen_add_time_event(g, "LLVM Link");
-    if (!ZigLLDLink(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
+    if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
         fprintf(stderr, "%s\n", buf_ptr(&diag));
         exit(1);
     }
src/main.cpp
@@ -266,6 +266,11 @@ static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) {
 }
 
 int main(int argc, char **argv) {
+    if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
+        printf("%s\n%s\n", ZIG_CMAKE_BINARY_DIR, ZIG_CXX_COMPILER);
+        return 0;
+    }
+
     os_init();
 
     char *arg0 = argv[0];
src/os.hpp
@@ -11,7 +11,7 @@
 #include "list.hpp"
 #include "buffer.hpp"
 #include "error.hpp"
-#include "zig_llvm.hpp"
+#include "zig_llvm.h"
 
 #include <stdio.h>
 #include <inttypes.h>
src/target.hpp
@@ -8,7 +8,7 @@
 #ifndef ZIG_TARGET_HPP
 #define ZIG_TARGET_HPP
 
-#include <zig_llvm.hpp>
+#include <zig_llvm.h>
 
 struct Buf;
 
src/util.hpp
@@ -13,8 +13,6 @@
 #include <string.h>
 #include <assert.h>
 
-#include <new>
-
 #if defined(_MSC_VER)
 
 #include <intrin.h>  
src/zig_llvm.cpp
@@ -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) {
+
+        }
+        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, Buf *diag_buf) {
+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();
 }
src/zig_llvm.h
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2015 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_ZIG_LLVM_HPP
+#define ZIG_ZIG_LLVM_HPP
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <llvm-c/Core.h>
+#include <llvm-c/Analysis.h>
+#include <llvm-c/Target.h>
+#include <llvm-c/Initialization.h>
+#include <llvm-c/TargetMachine.h>
+
+#ifdef __cplusplus
+#define ZIG_EXTERN_C extern "C"
+#else
+#define ZIG_EXTERN_C
+#endif
+
+struct ZigLLVMDIType;
+struct ZigLLVMDIBuilder;
+struct ZigLLVMDICompileUnit;
+struct ZigLLVMDIScope;
+struct ZigLLVMDIFile;
+struct ZigLLVMDILexicalBlock;
+struct ZigLLVMDISubprogram;
+struct ZigLLVMDISubroutineType;
+struct ZigLLVMDILocalVariable;
+struct ZigLLVMDIGlobalVariable;
+struct ZigLLVMDILocation;
+struct ZigLLVMDIEnumerator;
+struct ZigLLVMInsertionPoint;
+
+ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
+ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
+
+/// Caller must free memory.
+ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void);
+ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void);
+
+// We use a custom enum here since LLVM does not expose LLVMIr as an emit
+// output through the same mechanism as assembly/binary.
+enum ZigLLVM_EmitOutputType {
+    ZigLLVM_EmitAssembly,
+    ZigLLVM_EmitBinary,
+    ZigLLVM_EmitLLVMIr,
+};
+
+ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
+        const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug);
+
+enum ZigLLVM_FnInline {
+    ZigLLVM_FnInlineAuto,
+    ZigLLVM_FnInlineAlways,
+    ZigLLVM_FnInlineNever,
+};
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
+        unsigned NumArgs, unsigned CC, enum ZigLLVM_FnInline fn_inline, const char *Name);
+
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp,
+        LLVMValueRef new_val, LLVMAtomicOrdering success_ordering,
+        LLVMAtomicOrdering failure_ordering);
+
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
+        const char *name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
+        const char *name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
+        const char *name);
+ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
+        const char *name);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugPointerType(struct ZigLLVMDIBuilder *dibuilder,
+        struct ZigLLVMDIType *pointee_type, uint64_t size_in_bits, uint64_t align_in_bits, const char *name);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugBasicType(struct ZigLLVMDIBuilder *dibuilder, const char *name,
+        uint64_t size_in_bits, unsigned encoding);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugArrayType(struct ZigLLVMDIBuilder *dibuilder,
+        uint64_t size_in_bits, uint64_t align_in_bits, struct ZigLLVMDIType *elem_type,
+        int elem_count);
+
+ZIG_EXTERN_C struct ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(struct ZigLLVMDIBuilder *dibuilder,
+        const char *name, int64_t val);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(struct ZigLLVMDIBuilder *dibuilder,
+        struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,
+        uint64_t size_in_bits, uint64_t align_in_bits, struct ZigLLVMDIEnumerator **enumerator_array,
+        int enumerator_array_len, struct ZigLLVMDIType *underlying_type, const char *unique_id);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugStructType(struct ZigLLVMDIBuilder *dibuilder,
+        struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,
+        uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, struct ZigLLVMDIType *derived_from,
+        struct ZigLLVMDIType **types_array, int types_array_len, unsigned run_time_lang,
+        struct ZigLLVMDIType *vtable_holder, const char *unique_id);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugUnionType(struct ZigLLVMDIBuilder *dibuilder,
+        struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_number,
+        uint64_t size_in_bits, uint64_t align_in_bits, unsigned flags, struct ZigLLVMDIType **types_array,
+        int types_array_len, unsigned run_time_lang, const char *unique_id);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugMemberType(struct ZigLLVMDIBuilder *dibuilder,
+        struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line,
+        uint64_t size_in_bits, uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags,
+        struct ZigLLVMDIType *type);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateReplaceableCompositeType(struct ZigLLVMDIBuilder *dibuilder,
+        unsigned tag, const char *name, struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateDebugForwardDeclType(struct ZigLLVMDIBuilder *dibuilder, unsigned tag,
+        const char *name, struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line);
+
+ZIG_EXTERN_C void ZigLLVMReplaceTemporary(struct ZigLLVMDIBuilder *dibuilder, struct ZigLLVMDIType *type,
+        struct ZigLLVMDIType *replacement);
+
+ZIG_EXTERN_C void ZigLLVMReplaceDebugArrays(struct ZigLLVMDIBuilder *dibuilder, struct ZigLLVMDIType *type,
+        struct ZigLLVMDIType **types_array, int types_array_len);
+
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMCreateSubroutineType(struct ZigLLVMDIBuilder *dibuilder_wrapped,
+        struct ZigLLVMDIType **types_array, int types_array_len, unsigned flags);
+
+ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_unsigned(void);
+ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed(void);
+ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_float(void);
+ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_boolean(void);
+ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_unsigned_char(void);
+ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed_char(void);
+ZIG_EXTERN_C unsigned ZigLLVMLang_DW_LANG_C99(void);
+ZIG_EXTERN_C unsigned ZigLLVMTag_DW_variable(void);
+ZIG_EXTERN_C unsigned ZigLLVMTag_DW_structure_type(void);
+ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void);
+
+ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
+ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
+ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
+
+ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column,
+        struct ZigLLVMDIScope *scope);
+ZIG_EXTERN_C void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder);
+
+ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(struct ZigLLVMDILexicalBlock *lexical_block);
+ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMCompileUnitToScope(struct ZigLLVMDICompileUnit *compile_unit);
+ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *difile);
+ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);
+ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type);
+
+ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder,
+        struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
+        struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);
+
+ZIG_EXTERN_C struct ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(struct ZigLLVMDIBuilder *dbuilder,
+    struct ZigLLVMDIScope *scope, const char *name, const char *linkage_name, struct ZigLLVMDIFile *file,
+    unsigned line_no, struct ZigLLVMDIType *di_type, bool is_local_to_unit);
+
+ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(struct ZigLLVMDIBuilder *dbuilder,
+        struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
+        struct ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no);
+
+ZIG_EXTERN_C struct ZigLLVMDILexicalBlock *ZigLLVMCreateLexicalBlock(struct ZigLLVMDIBuilder *dbuilder,
+        struct ZigLLVMDIScope *scope, struct ZigLLVMDIFile *file, unsigned line, unsigned col);
+
+ZIG_EXTERN_C struct ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(struct ZigLLVMDIBuilder *dibuilder,
+        unsigned lang, struct ZigLLVMDIFile *difile, const char *producer,
+        bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
+        uint64_t dwo_id, bool emit_debug_info);
+
+ZIG_EXTERN_C struct ZigLLVMDIFile *ZigLLVMCreateFile(struct ZigLLVMDIBuilder *dibuilder, const char *filename,
+        const char *directory);
+
+ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIBuilder *dibuilder,
+        struct ZigLLVMDIScope *scope, const char *name, const char *linkage_name, struct ZigLLVMDIFile *file,
+        unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
+        unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);
+
+ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
+
+ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);
+
+ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclareAtEnd(struct ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
+        struct ZigLLVMDILocalVariable *var_info, struct ZigLLVMDILocation *debug_loc,
+        LLVMBasicBlockRef basic_block_ref);
+
+ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDeclare(struct ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
+        struct ZigLLVMDILocalVariable *var_info, struct ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr);
+ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, struct ZigLLVMDIScope *scope);
+
+ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
+
+ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
+ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
+
+ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);
+
+
+// copied from include/llvm/ADT/Triple.h
+
+enum ZigLLVM_ArchType {
+    ZigLLVM_UnknownArch,
+
+    ZigLLVM_arm,            // ARM (little endian): arm, armv.*, xscale
+    ZigLLVM_armeb,          // ARM (big endian): armeb
+    ZigLLVM_aarch64,        // AArch64 (little endian): aarch64
+    ZigLLVM_aarch64_be,     // AArch64 (big endian): aarch64_be
+    ZigLLVM_avr,            // AVR: Atmel AVR microcontroller
+    ZigLLVM_bpfel,          // eBPF or extended BPF or 64-bit BPF (little endian)
+    ZigLLVM_bpfeb,          // eBPF or extended BPF or 64-bit BPF (big endian)
+    ZigLLVM_hexagon,        // Hexagon: hexagon
+    ZigLLVM_mips,           // MIPS: mips, mipsallegrex
+    ZigLLVM_mipsel,         // MIPSEL: mipsel, mipsallegrexel
+    ZigLLVM_mips64,         // MIPS64: mips64
+    ZigLLVM_mips64el,       // MIPS64EL: mips64el
+    ZigLLVM_msp430,         // MSP430: msp430
+    ZigLLVM_nios2,          // NIOSII: nios2
+    ZigLLVM_ppc,            // PPC: powerpc
+    ZigLLVM_ppc64,          // PPC64: powerpc64, ppu
+    ZigLLVM_ppc64le,        // PPC64LE: powerpc64le
+    ZigLLVM_r600,           // R600: AMD GPUs HD2XXX - HD6XXX
+    ZigLLVM_amdgcn,         // AMDGCN: AMD GCN GPUs
+    ZigLLVM_riscv32,        // RISC-V (32-bit): riscv32
+    ZigLLVM_riscv64,        // RISC-V (64-bit): riscv64
+    ZigLLVM_sparc,          // Sparc: sparc
+    ZigLLVM_sparcv9,        // Sparcv9: Sparcv9
+    ZigLLVM_sparcel,        // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
+    ZigLLVM_systemz,        // SystemZ: s390x
+    ZigLLVM_tce,            // TCE (http://tce.cs.tut.fi/): tce
+    ZigLLVM_tcele,          // TCE little endian (http://tce.cs.tut.fi/): tcele
+    ZigLLVM_thumb,          // Thumb (little endian): thumb, thumbv.*
+    ZigLLVM_thumbeb,        // Thumb (big endian): thumbeb
+    ZigLLVM_x86,            // X86: i[3-9]86
+    ZigLLVM_x86_64,         // X86-64: amd64, x86_64
+    ZigLLVM_xcore,          // XCore: xcore
+    ZigLLVM_nvptx,          // NVPTX: 32-bit
+    ZigLLVM_nvptx64,        // NVPTX: 64-bit
+    ZigLLVM_le32,           // le32: generic little-endian 32-bit CPU (PNaCl)
+    ZigLLVM_le64,           // le64: generic little-endian 64-bit CPU (PNaCl)
+    ZigLLVM_amdil,          // AMDIL
+    ZigLLVM_amdil64,        // AMDIL with 64-bit pointers
+    ZigLLVM_hsail,          // AMD HSAIL
+    ZigLLVM_hsail64,        // AMD HSAIL with 64-bit pointers
+    ZigLLVM_spir,           // SPIR: standard portable IR for OpenCL 32-bit version
+    ZigLLVM_spir64,         // SPIR: standard portable IR for OpenCL 64-bit version
+    ZigLLVM_kalimba,        // Kalimba: generic kalimba
+    ZigLLVM_shave,          // SHAVE: Movidius vector VLIW processors
+    ZigLLVM_lanai,          // Lanai: Lanai 32-bit
+    ZigLLVM_wasm32,         // WebAssembly with 32-bit pointers
+    ZigLLVM_wasm64,         // WebAssembly with 64-bit pointers
+    ZigLLVM_renderscript32, // 32-bit RenderScript
+    ZigLLVM_renderscript64, // 64-bit RenderScript
+
+    ZigLLVM_LastArchType = ZigLLVM_renderscript64
+};
+
+enum ZigLLVM_SubArchType {
+    ZigLLVM_NoSubArch,
+
+    ZigLLVM_ARMSubArch_v8_2a,
+    ZigLLVM_ARMSubArch_v8_1a,
+    ZigLLVM_ARMSubArch_v8,
+    ZigLLVM_ARMSubArch_v8r,
+    ZigLLVM_ARMSubArch_v8m_baseline,
+    ZigLLVM_ARMSubArch_v8m_mainline,
+    ZigLLVM_ARMSubArch_v7,
+    ZigLLVM_ARMSubArch_v7em,
+    ZigLLVM_ARMSubArch_v7m,
+    ZigLLVM_ARMSubArch_v7s,
+    ZigLLVM_ARMSubArch_v7k,
+    ZigLLVM_ARMSubArch_v7ve,
+    ZigLLVM_ARMSubArch_v6,
+    ZigLLVM_ARMSubArch_v6m,
+    ZigLLVM_ARMSubArch_v6k,
+    ZigLLVM_ARMSubArch_v6t2,
+    ZigLLVM_ARMSubArch_v5,
+    ZigLLVM_ARMSubArch_v5te,
+    ZigLLVM_ARMSubArch_v4t,
+
+    ZigLLVM_KalimbaSubArch_v3,
+    ZigLLVM_KalimbaSubArch_v4,
+    ZigLLVM_KalimbaSubArch_v5,
+};
+
+enum ZigLLVM_VendorType {
+    ZigLLVM_UnknownVendor,
+
+    ZigLLVM_Apple,
+    ZigLLVM_PC,
+    ZigLLVM_SCEI,
+    ZigLLVM_BGP,
+    ZigLLVM_BGQ,
+    ZigLLVM_Freescale,
+    ZigLLVM_IBM,
+    ZigLLVM_ImaginationTechnologies,
+    ZigLLVM_MipsTechnologies,
+    ZigLLVM_NVIDIA,
+    ZigLLVM_CSR,
+    ZigLLVM_Myriad,
+    ZigLLVM_AMD,
+    ZigLLVM_Mesa,
+    ZigLLVM_SUSE,
+
+    ZigLLVM_LastVendorType = ZigLLVM_SUSE
+};
+
+enum ZigLLVM_OSType {
+    ZigLLVM_UnknownOS,
+
+    ZigLLVM_Ananas,
+    ZigLLVM_CloudABI,
+    ZigLLVM_Darwin,
+    ZigLLVM_DragonFly,
+    ZigLLVM_FreeBSD,
+    ZigLLVM_Fuchsia,
+    ZigLLVM_IOS,
+    ZigLLVM_KFreeBSD,
+    ZigLLVM_Linux,
+    ZigLLVM_Lv2,        // PS3
+    ZigLLVM_MacOSX,
+    ZigLLVM_NetBSD,
+    ZigLLVM_OpenBSD,
+    ZigLLVM_Solaris,
+    ZigLLVM_Win32,
+    ZigLLVM_Haiku,
+    ZigLLVM_Minix,
+    ZigLLVM_RTEMS,
+    ZigLLVM_NaCl,       // Native Client
+    ZigLLVM_CNK,        // BG/P Compute-Node Kernel
+    ZigLLVM_Bitrig,
+    ZigLLVM_AIX,
+    ZigLLVM_CUDA,       // NVIDIA CUDA
+    ZigLLVM_NVCL,       // NVIDIA OpenCL
+    ZigLLVM_AMDHSA,     // AMD HSA Runtime
+    ZigLLVM_PS4,
+    ZigLLVM_ELFIAMCU,
+    ZigLLVM_TvOS,       // Apple tvOS
+    ZigLLVM_WatchOS,    // Apple watchOS
+    ZigLLVM_Mesa3D,
+    ZigLLVM_Contiki,
+
+    ZigLLVM_LastOSType = ZigLLVM_Contiki
+};
+
+enum ZigLLVM_EnvironmentType {
+    ZigLLVM_UnknownEnvironment,
+
+    ZigLLVM_GNU,
+    ZigLLVM_GNUABI64,
+    ZigLLVM_GNUEABI,
+    ZigLLVM_GNUEABIHF,
+    ZigLLVM_GNUX32,
+    ZigLLVM_CODE16,
+    ZigLLVM_EABI,
+    ZigLLVM_EABIHF,
+    ZigLLVM_Android,
+    ZigLLVM_Musl,
+    ZigLLVM_MuslEABI,
+    ZigLLVM_MuslEABIHF,
+
+    ZigLLVM_MSVC,
+    ZigLLVM_Itanium,
+    ZigLLVM_Cygnus,
+    ZigLLVM_AMDOpenCL,
+    ZigLLVM_CoreCLR,
+    ZigLLVM_OpenCL,
+
+    ZigLLVM_LastEnvironmentType = ZigLLVM_OpenCL
+};
+
+enum ZigLLVM_ObjectFormatType {
+    ZigLLVM_UnknownObjectFormat,
+
+    ZigLLVM_COFF,
+    ZigLLVM_ELF,
+    ZigLLVM_MachO,
+    ZigLLVM_Wasm,
+};
+
+ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
+ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);
+ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
+ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os);
+ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType env_type);
+
+ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
+        void (*append_diagnostic)(void *, const char *, size_t), void *context);
+
+ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,
+        enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
+        enum ZigLLVM_ObjectFormatType *oformat);
+
+#endif
src/zig_llvm.hpp
@@ -1,383 +0,0 @@
-/*
- * Copyright (c) 2015 Andrew Kelley
- *
- * This file is part of zig, which is MIT licensed.
- * See http://opensource.org/licenses/MIT
- */
-
-#ifndef ZIG_ZIG_LLVM_HPP
-#define ZIG_ZIG_LLVM_HPP
-
-#include <llvm-c/Core.h>
-#include <llvm-c/Analysis.h>
-#include <llvm-c/Target.h>
-#include <llvm-c/Initialization.h>
-#include <llvm-c/TargetMachine.h>
-
-struct ZigLLVMDIType;
-struct ZigLLVMDIBuilder;
-struct ZigLLVMDICompileUnit;
-struct ZigLLVMDIScope;
-struct ZigLLVMDIFile;
-struct ZigLLVMDILexicalBlock;
-struct ZigLLVMDISubprogram;
-struct ZigLLVMDISubroutineType;
-struct ZigLLVMDILocalVariable;
-struct ZigLLVMDIGlobalVariable;
-struct ZigLLVMDILocation;
-struct ZigLLVMDIEnumerator;
-struct ZigLLVMInsertionPoint;
-
-void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
-void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
-
-char *ZigLLVMGetHostCPUName(void);
-char *ZigLLVMGetNativeFeatures(void);
-
-// We use a custom enum here since LLVM does not expose LLVMIr as an emit
-// output through the same mechanism as assembly/binary.
-enum ZigLLVM_EmitOutputType {
-    ZigLLVM_EmitAssembly,
-    ZigLLVM_EmitBinary,
-    ZigLLVM_EmitLLVMIr,
-};
-
-bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
-        const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug);
-
-enum ZigLLVM_FnInline {
-    ZigLLVM_FnInlineAuto,
-    ZigLLVM_FnInlineAlways,
-    ZigLLVM_FnInlineNever,
-};
-LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
-        unsigned NumArgs, unsigned CC, ZigLLVM_FnInline fn_inline, const char *Name);
-
-LLVMValueRef ZigLLVMBuildCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp,
-        LLVMValueRef new_val, LLVMAtomicOrdering success_ordering,
-        LLVMAtomicOrdering failure_ordering);
-
-LLVMValueRef ZigLLVMBuildNSWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
-        const char *name);
-LLVMValueRef ZigLLVMBuildNUWShl(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
-        const char *name);
-LLVMValueRef ZigLLVMBuildLShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
-        const char *name);
-LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLVMValueRef RHS,
-        const char *name);
-
-ZigLLVMDIType *ZigLLVMCreateDebugPointerType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *pointee_type,
-        uint64_t size_in_bits, uint64_t align_in_bits, const char *name);
-
-ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const char *name,
-        uint64_t size_in_bits, unsigned encoding);
-
-ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder,
-        uint64_t size_in_bits, uint64_t align_in_bits, ZigLLVMDIType *elem_type,
-        int elem_count);
-
-ZigLLVMDIEnumerator *ZigLLVMCreateDebugEnumerator(ZigLLVMDIBuilder *dibuilder, const char *name, int64_t val);
-
-ZigLLVMDIType *ZigLLVMCreateDebugEnumerationType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
-        const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits,
-        uint64_t align_in_bits, ZigLLVMDIEnumerator **enumerator_array, int enumerator_array_len,
-        ZigLLVMDIType *underlying_type, const char *unique_id);
-
-ZigLLVMDIType *ZigLLVMCreateDebugStructType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
-        const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits,
-        uint64_t align_in_bits, unsigned flags, ZigLLVMDIType *derived_from,
-        ZigLLVMDIType **types_array, int types_array_len, unsigned run_time_lang, ZigLLVMDIType *vtable_holder,
-        const char *unique_id);
-
-ZigLLVMDIType *ZigLLVMCreateDebugUnionType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
-        const char *name, ZigLLVMDIFile *file, unsigned line_number, uint64_t size_in_bits,
-        uint64_t align_in_bits, unsigned flags, ZigLLVMDIType **types_array, int types_array_len,
-        unsigned run_time_lang, const char *unique_id);
-
-ZigLLVMDIType *ZigLLVMCreateDebugMemberType(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
-        const char *name, ZigLLVMDIFile *file, unsigned line, uint64_t size_in_bits,
-        uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, ZigLLVMDIType *type);
-
-ZigLLVMDIType *ZigLLVMCreateReplaceableCompositeType(ZigLLVMDIBuilder *dibuilder, unsigned tag,
-        const char *name, ZigLLVMDIScope *scope, ZigLLVMDIFile *file, unsigned line);
-
-ZigLLVMDIType *ZigLLVMCreateDebugForwardDeclType(ZigLLVMDIBuilder *dibuilder, unsigned tag,
-        const char *name, ZigLLVMDIScope *scope, ZigLLVMDIFile *file, unsigned line);
-
-void ZigLLVMReplaceTemporary(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *type,
-        ZigLLVMDIType *replacement);
-
-void ZigLLVMReplaceDebugArrays(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIType *type,
-        ZigLLVMDIType **types_array, int types_array_len);
-
-ZigLLVMDIType *ZigLLVMCreateSubroutineType(ZigLLVMDIBuilder *dibuilder_wrapped,
-        ZigLLVMDIType **types_array, int types_array_len, unsigned flags);
-
-unsigned ZigLLVMEncoding_DW_ATE_unsigned(void);
-unsigned ZigLLVMEncoding_DW_ATE_signed(void);
-unsigned ZigLLVMEncoding_DW_ATE_float(void);
-unsigned ZigLLVMEncoding_DW_ATE_boolean(void);
-unsigned ZigLLVMEncoding_DW_ATE_unsigned_char(void);
-unsigned ZigLLVMEncoding_DW_ATE_signed_char(void);
-unsigned ZigLLVMLang_DW_LANG_C99(void);
-unsigned ZigLLVMTag_DW_variable(void);
-unsigned ZigLLVMTag_DW_structure_type(void);
-unsigned ZigLLVMTag_DW_union_type(void);
-
-ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
-void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
-void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
-
-void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, ZigLLVMDIScope *scope);
-void ZigLLVMClearCurrentDebugLocation(LLVMBuilderRef builder);
-
-ZigLLVMDIScope *ZigLLVMLexicalBlockToScope(ZigLLVMDILexicalBlock *lexical_block);
-ZigLLVMDIScope *ZigLLVMCompileUnitToScope(ZigLLVMDICompileUnit *compile_unit);
-ZigLLVMDIScope *ZigLLVMFileToScope(ZigLLVMDIFile *difile);
-ZigLLVMDIScope *ZigLLVMSubprogramToScope(ZigLLVMDISubprogram *subprogram);
-ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type);
-
-ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(ZigLLVMDIBuilder *dbuilder,
-        ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no,
-        ZigLLVMDIType *type, bool always_preserve, unsigned flags);
-
-ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder,
-    ZigLLVMDIScope *scope, const char *name, const char *linkage_name, ZigLLVMDIFile *file,
-    unsigned line_no, ZigLLVMDIType *di_type, bool is_local_to_unit);
-
-ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,
-        ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no,
-        ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no);
-
-ZigLLVMDILexicalBlock *ZigLLVMCreateLexicalBlock(ZigLLVMDIBuilder *dbuilder, ZigLLVMDIScope *scope,
-        ZigLLVMDIFile *file, unsigned line, unsigned col);
-
-ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,
-        unsigned lang, ZigLLVMDIFile *difile, const char *producer,
-        bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
-        uint64_t dwo_id, bool emit_debug_info);
-
-ZigLLVMDIFile *ZigLLVMCreateFile(ZigLLVMDIBuilder *dibuilder, const char *filename, const char *directory);
-
-ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMDIScope *scope,
-        const char *name, const char *linkage_name, ZigLLVMDIFile *file, unsigned lineno,
-        ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition, unsigned scope_line,
-        unsigned flags, bool is_optimized, ZigLLVMDISubprogram *decl_subprogram);
-
-void ZigLLVMFnSetSubprogram(LLVMValueRef fn, ZigLLVMDISubprogram *subprogram);
-
-void ZigLLVMDIBuilderFinalize(ZigLLVMDIBuilder *dibuilder);
-
-LLVMValueRef ZigLLVMInsertDeclareAtEnd(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
-        ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMBasicBlockRef basic_block_ref);
-LLVMValueRef ZigLLVMInsertDeclare(ZigLLVMDIBuilder *dibuilder, LLVMValueRef storage,
-        ZigLLVMDILocalVariable *var_info, ZigLLVMDILocation *debug_loc, LLVMValueRef insert_before_instr);
-ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigned col, ZigLLVMDIScope *scope);
-
-void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state);
-
-void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value);
-void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);
-
-void ZigLLVMParseCommandLineOptions(int argc, const char *const *argv);
-
-
-// copied from include/llvm/ADT/Triple.h
-
-enum ZigLLVM_ArchType {
-    ZigLLVM_UnknownArch,
-
-    ZigLLVM_arm,            // ARM (little endian): arm, armv.*, xscale
-    ZigLLVM_armeb,          // ARM (big endian): armeb
-    ZigLLVM_aarch64,        // AArch64 (little endian): aarch64
-    ZigLLVM_aarch64_be,     // AArch64 (big endian): aarch64_be
-    ZigLLVM_avr,            // AVR: Atmel AVR microcontroller
-    ZigLLVM_bpfel,          // eBPF or extended BPF or 64-bit BPF (little endian)
-    ZigLLVM_bpfeb,          // eBPF or extended BPF or 64-bit BPF (big endian)
-    ZigLLVM_hexagon,        // Hexagon: hexagon
-    ZigLLVM_mips,           // MIPS: mips, mipsallegrex
-    ZigLLVM_mipsel,         // MIPSEL: mipsel, mipsallegrexel
-    ZigLLVM_mips64,         // MIPS64: mips64
-    ZigLLVM_mips64el,       // MIPS64EL: mips64el
-    ZigLLVM_msp430,         // MSP430: msp430
-    ZigLLVM_nios2,          // NIOSII: nios2
-    ZigLLVM_ppc,            // PPC: powerpc
-    ZigLLVM_ppc64,          // PPC64: powerpc64, ppu
-    ZigLLVM_ppc64le,        // PPC64LE: powerpc64le
-    ZigLLVM_r600,           // R600: AMD GPUs HD2XXX - HD6XXX
-    ZigLLVM_amdgcn,         // AMDGCN: AMD GCN GPUs
-    ZigLLVM_riscv32,        // RISC-V (32-bit): riscv32
-    ZigLLVM_riscv64,        // RISC-V (64-bit): riscv64
-    ZigLLVM_sparc,          // Sparc: sparc
-    ZigLLVM_sparcv9,        // Sparcv9: Sparcv9
-    ZigLLVM_sparcel,        // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
-    ZigLLVM_systemz,        // SystemZ: s390x
-    ZigLLVM_tce,            // TCE (http://tce.cs.tut.fi/): tce
-    ZigLLVM_tcele,          // TCE little endian (http://tce.cs.tut.fi/): tcele
-    ZigLLVM_thumb,          // Thumb (little endian): thumb, thumbv.*
-    ZigLLVM_thumbeb,        // Thumb (big endian): thumbeb
-    ZigLLVM_x86,            // X86: i[3-9]86
-    ZigLLVM_x86_64,         // X86-64: amd64, x86_64
-    ZigLLVM_xcore,          // XCore: xcore
-    ZigLLVM_nvptx,          // NVPTX: 32-bit
-    ZigLLVM_nvptx64,        // NVPTX: 64-bit
-    ZigLLVM_le32,           // le32: generic little-endian 32-bit CPU (PNaCl)
-    ZigLLVM_le64,           // le64: generic little-endian 64-bit CPU (PNaCl)
-    ZigLLVM_amdil,          // AMDIL
-    ZigLLVM_amdil64,        // AMDIL with 64-bit pointers
-    ZigLLVM_hsail,          // AMD HSAIL
-    ZigLLVM_hsail64,        // AMD HSAIL with 64-bit pointers
-    ZigLLVM_spir,           // SPIR: standard portable IR for OpenCL 32-bit version
-    ZigLLVM_spir64,         // SPIR: standard portable IR for OpenCL 64-bit version
-    ZigLLVM_kalimba,        // Kalimba: generic kalimba
-    ZigLLVM_shave,          // SHAVE: Movidius vector VLIW processors
-    ZigLLVM_lanai,          // Lanai: Lanai 32-bit
-    ZigLLVM_wasm32,         // WebAssembly with 32-bit pointers
-    ZigLLVM_wasm64,         // WebAssembly with 64-bit pointers
-    ZigLLVM_renderscript32, // 32-bit RenderScript
-    ZigLLVM_renderscript64, // 64-bit RenderScript
-
-    ZigLLVM_LastArchType = ZigLLVM_renderscript64
-};
-
-enum ZigLLVM_SubArchType {
-    ZigLLVM_NoSubArch,
-
-    ZigLLVM_ARMSubArch_v8_2a,
-    ZigLLVM_ARMSubArch_v8_1a,
-    ZigLLVM_ARMSubArch_v8,
-    ZigLLVM_ARMSubArch_v8r,
-    ZigLLVM_ARMSubArch_v8m_baseline,
-    ZigLLVM_ARMSubArch_v8m_mainline,
-    ZigLLVM_ARMSubArch_v7,
-    ZigLLVM_ARMSubArch_v7em,
-    ZigLLVM_ARMSubArch_v7m,
-    ZigLLVM_ARMSubArch_v7s,
-    ZigLLVM_ARMSubArch_v7k,
-    ZigLLVM_ARMSubArch_v7ve,
-    ZigLLVM_ARMSubArch_v6,
-    ZigLLVM_ARMSubArch_v6m,
-    ZigLLVM_ARMSubArch_v6k,
-    ZigLLVM_ARMSubArch_v6t2,
-    ZigLLVM_ARMSubArch_v5,
-    ZigLLVM_ARMSubArch_v5te,
-    ZigLLVM_ARMSubArch_v4t,
-
-    ZigLLVM_KalimbaSubArch_v3,
-    ZigLLVM_KalimbaSubArch_v4,
-    ZigLLVM_KalimbaSubArch_v5,
-};
-
-enum ZigLLVM_VendorType {
-    ZigLLVM_UnknownVendor,
-
-    ZigLLVM_Apple,
-    ZigLLVM_PC,
-    ZigLLVM_SCEI,
-    ZigLLVM_BGP,
-    ZigLLVM_BGQ,
-    ZigLLVM_Freescale,
-    ZigLLVM_IBM,
-    ZigLLVM_ImaginationTechnologies,
-    ZigLLVM_MipsTechnologies,
-    ZigLLVM_NVIDIA,
-    ZigLLVM_CSR,
-    ZigLLVM_Myriad,
-    ZigLLVM_AMD,
-    ZigLLVM_Mesa,
-    ZigLLVM_SUSE,
-
-    ZigLLVM_LastVendorType = ZigLLVM_SUSE
-};
-
-enum ZigLLVM_OSType {
-    ZigLLVM_UnknownOS,
-
-    ZigLLVM_Ananas,
-    ZigLLVM_CloudABI,
-    ZigLLVM_Darwin,
-    ZigLLVM_DragonFly,
-    ZigLLVM_FreeBSD,
-    ZigLLVM_Fuchsia,
-    ZigLLVM_IOS,
-    ZigLLVM_KFreeBSD,
-    ZigLLVM_Linux,
-    ZigLLVM_Lv2,        // PS3
-    ZigLLVM_MacOSX,
-    ZigLLVM_NetBSD,
-    ZigLLVM_OpenBSD,
-    ZigLLVM_Solaris,
-    ZigLLVM_Win32,
-    ZigLLVM_Haiku,
-    ZigLLVM_Minix,
-    ZigLLVM_RTEMS,
-    ZigLLVM_NaCl,       // Native Client
-    ZigLLVM_CNK,        // BG/P Compute-Node Kernel
-    ZigLLVM_Bitrig,
-    ZigLLVM_AIX,
-    ZigLLVM_CUDA,       // NVIDIA CUDA
-    ZigLLVM_NVCL,       // NVIDIA OpenCL
-    ZigLLVM_AMDHSA,     // AMD HSA Runtime
-    ZigLLVM_PS4,
-    ZigLLVM_ELFIAMCU,
-    ZigLLVM_TvOS,       // Apple tvOS
-    ZigLLVM_WatchOS,    // Apple watchOS
-    ZigLLVM_Mesa3D,
-    ZigLLVM_Contiki,
-
-    ZigLLVM_LastOSType = ZigLLVM_Contiki
-};
-
-enum ZigLLVM_EnvironmentType {
-    ZigLLVM_UnknownEnvironment,
-
-    ZigLLVM_GNU,
-    ZigLLVM_GNUABI64,
-    ZigLLVM_GNUEABI,
-    ZigLLVM_GNUEABIHF,
-    ZigLLVM_GNUX32,
-    ZigLLVM_CODE16,
-    ZigLLVM_EABI,
-    ZigLLVM_EABIHF,
-    ZigLLVM_Android,
-    ZigLLVM_Musl,
-    ZigLLVM_MuslEABI,
-    ZigLLVM_MuslEABIHF,
-
-    ZigLLVM_MSVC,
-    ZigLLVM_Itanium,
-    ZigLLVM_Cygnus,
-    ZigLLVM_AMDOpenCL,
-    ZigLLVM_CoreCLR,
-    ZigLLVM_OpenCL,
-
-    ZigLLVM_LastEnvironmentType = ZigLLVM_OpenCL
-};
-
-enum ZigLLVM_ObjectFormatType {
-    ZigLLVM_UnknownObjectFormat,
-
-    ZigLLVM_COFF,
-    ZigLLVM_ELF,
-    ZigLLVM_MachO,
-    ZigLLVM_Wasm,
-};
-
-const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch);
-const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch);
-const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor);
-const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os);
-const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type);
-
-/*
- * This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here.
- */
-struct Buf;
-
-bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, Buf *diag);
-
-void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type,
-        ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
-        ZigLLVM_ObjectFormatType *oformat);
-
-#endif
src-self-hosted/c.zig
@@ -1,7 +1,4 @@
 pub use @cImport({
-    @cInclude("llvm-c/Core.h");
-    @cInclude("llvm-c/Analysis.h");
-    @cInclude("llvm-c/Target.h");
-    @cInclude("llvm-c/Initialization.h");
-    @cInclude("llvm-c/TargetMachine.h");
+    @cInclude("config.h");
+    @cInclude("zig_llvm.h");
 });
src-self-hosted/ir.zig
@@ -0,0 +1,112 @@
+const Scope = @import("scope.zig").Scope;
+
+pub const Instruction = struct {
+    id: Id,
+    scope: &Scope,
+
+    pub const Id = enum {
+        Br,
+        CondBr,
+        SwitchBr,
+        SwitchVar,
+        SwitchTarget,
+        Phi,
+        UnOp,
+        BinOp,
+        DeclVar,
+        LoadPtr,
+        StorePtr,
+        FieldPtr,
+        StructFieldPtr,
+        UnionFieldPtr,
+        ElemPtr,
+        VarPtr,
+        Call,
+        Const,
+        Return,
+        Cast,
+        ContainerInitList,
+        ContainerInitFields,
+        StructInit,
+        UnionInit,
+        Unreachable,
+        TypeOf,
+        ToPtrType,
+        PtrTypeChild,
+        SetDebugSafety,
+        SetFloatMode,
+        ArrayType,
+        SliceType,
+        Asm,
+        SizeOf,
+        TestNonNull,
+        UnwrapMaybe,
+        MaybeWrap,
+        UnionTag,
+        Clz,
+        Ctz,
+        Import,
+        CImport,
+        CInclude,
+        CDefine,
+        CUndef,
+        ArrayLen,
+        Ref,
+        MinValue,
+        MaxValue,
+        CompileErr,
+        CompileLog,
+        ErrName,
+        EmbedFile,
+        Cmpxchg,
+        Fence,
+        Truncate,
+        IntType,
+        BoolNot,
+        Memset,
+        Memcpy,
+        Slice,
+        MemberCount,
+        MemberType,
+        MemberName,
+        Breakpoint,
+        ReturnAddress,
+        FrameAddress,
+        AlignOf,
+        OverflowOp,
+        TestErr,
+        UnwrapErrCode,
+        UnwrapErrPayload,
+        ErrWrapCode,
+        ErrWrapPayload,
+        FnProto,
+        TestComptime,
+        PtrCast,
+        BitCast,
+        WidenOrShorten,
+        IntToPtr,
+        PtrToInt,
+        IntToEnum,
+        IntToErr,
+        ErrToInt,
+        CheckSwitchProngs,
+        CheckStatementIsVoid,
+        TypeName,
+        CanImplicitCast,
+        DeclRef,
+        Panic,
+        TagName,
+        TagType,
+        FieldParentPtr,
+        OffsetOf,
+        TypeId,
+        SetEvalBranchQuota,
+        PtrTypeOf,
+        AlignCast,
+        OpaqueType,
+        SetAlignStack,
+        ArgType,
+        Export,
+    };
+
+};
src-self-hosted/main.zig
@@ -12,6 +12,7 @@ const ErrColor = Module.ErrColor;
 const Emit = Module.Emit;
 const builtin = @import("builtin");
 const ArrayList = std.ArrayList;
+const c = @import("c.zig");
 
 error InvalidCommandLineArguments;
 error ZigLibDirNotFound;
@@ -462,7 +463,11 @@ pub fn main2() -> %void {
                 else => unreachable,
             }
         },
-        Cmd.Version => @panic("TODO zig version"),
+        Cmd.Version => {
+            var stdout_file = %return io.getStdErr();
+            %return stdout_file.write(std.cstr.toSliceConst(c.ZIG_VERSION_STRING));
+            %return stdout_file.write("\n");
+        },
         Cmd.Targets => @panic("TODO zig targets"),
     }
 }
src-self-hosted/module.zig
@@ -199,6 +199,13 @@ pub const Module = struct {
     }
 
     pub fn build(self: &Module) -> %void {
+        if (self.llvm_argv.len != 0) {
+            var c_compatible_args = %return std.cstr.NullTerminated2DArray.fromSlices(self.allocator,
+                [][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, });
+            defer c_compatible_args.deinit();
+            c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
+        }
+
         const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path");
         const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| {
             %return printError("unable to open '{}': {}", root_src_path, err);
src-self-hosted/scope.zig
@@ -0,0 +1,16 @@
+pub const Scope = struct {
+    id: Id,
+    parent: &Scope,
+
+    pub const Id = enum {
+        Decls,
+        Block,
+        Defer,
+        DeferExpr,
+        VarDecl,
+        CImport,
+        Loop,
+        FnDef,
+        CompTime,
+    };
+};
std/build.zig
@@ -784,6 +784,13 @@ const Target = union(enum) {
         };
     }
 
+    pub fn libFileExt(self: &const Target) -> []const u8 {
+        return switch (self.getOs()) {
+            builtin.Os.windows => ".lib",
+            else => ".a",
+        };
+    }
+
     pub fn getOs(self: &const Target) -> builtin.Os {
         return switch (*self) {
             Target.Native => builtin.os,
std/cstr.zig
@@ -48,3 +48,57 @@ pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) -> %[]u8 {
     result[slice.len] = 0;
     return result;
 }
+
+pub const NullTerminated2DArray = struct {
+    allocator: &mem.Allocator,
+    byte_count: usize,
+    ptr: ?&?&u8,
+
+    /// Takes N lists of strings, concatenates the lists together, and adds a null terminator
+    /// Caller must deinit result
+    pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) -> %NullTerminated2DArray {
+        var new_len: usize = 1; // 1 for the list null
+        var byte_count: usize = 0;
+        for (slices) |slice| {
+            new_len += slice.len;
+            for (slice) |inner| {
+                byte_count += inner.len;
+            }
+            byte_count += slice.len; // for the null terminators of inner
+        }
+
+        const index_size = @sizeOf(usize) * new_len; // size of the ptrs
+        byte_count += index_size;
+
+        const buf = %return allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count);
+        %defer allocator.free(buf);
+
+        var write_index = index_size;
+        const index_buf = ([]?&u8)(buf);
+
+        var i: usize = 0;
+        for (slices) |slice| {
+            for (slice) |inner| {
+                index_buf[i] = &buf[write_index];
+                i += 1;
+                mem.copy(u8, buf[write_index..], inner);
+                write_index += inner.len;
+                buf[write_index] = 0;
+                write_index += 1;
+            }
+        }
+        index_buf[i] = null;
+
+        return NullTerminated2DArray {
+            .allocator = allocator,
+            .byte_count = byte_count,
+            .ptr = @ptrCast(?&?&u8, buf.ptr),
+        };
+    }
+
+    pub fn deinit(self: &NullTerminated2DArray) {
+        const buf = @ptrCast(&u8, self.ptr);
+        self.allocator.free(buf[0..self.byte_count]);
+    }
+};
+
build.zig
@@ -1,3 +1,4 @@
+const builtin = @import("builtin");
 const std = @import("std");
 const Builder = std.build.Builder;
 const tests = @import("test/tests.zig");
@@ -33,11 +34,32 @@ pub fn build(b: &Builder) {
     docs_step.dependOn(&docgen_home_cmd.step);
 
     if (findLLVM(b)) |llvm| {
+        // find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
+        const build_info = b.exec([][]const u8{b.zig_exe, "BUILD_INFO"});
+        var build_info_it = mem.split(build_info, "\n");
+        const cmake_binary_dir = ??build_info_it.next();
+        const cxx_compiler = ??build_info_it.next();
+
         var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
         exe.setBuildMode(mode);
-        exe.linkSystemLibrary("c");
+        exe.addIncludeDir("src");
+        exe.addIncludeDir(cmake_binary_dir);
+        addCppLib(b, exe, cmake_binary_dir, "libzig_cpp");
+        addCppLib(b, exe, cmake_binary_dir, "libembedded_lld_elf");
+        addCppLib(b, exe, cmake_binary_dir, "libembedded_lld_coff");
+        addCppLib(b, exe, cmake_binary_dir, "libembedded_lld_lib");
         dependOnLib(exe, llvm);
 
+        if (!exe.target.isWindows()) {
+            const libstdcxx_path_padded = b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"});
+            const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\n").next();
+            exe.addObjectFile(libstdcxx_path);
+
+            exe.linkSystemLibrary("pthread");
+        }
+
+        exe.linkSystemLibrary("c");
+
         b.default_step.dependOn(&exe.step);
         b.default_step.dependOn(docs_step);
 
@@ -91,6 +113,11 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) {
     }
 }
 
+fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) {
+    lib_exe_obj.addObjectFile(%%os.path.join(b.allocator, cmake_binary_dir, "zig_cpp",
+        b.fmt("{}{}", lib_name, lib_exe_obj.target.libFileExt())));
+}
+
 const LibraryDep = struct {
     libdirs: ArrayList([]const u8),
     libs: ArrayList([]const u8),
CMakeLists.txt
@@ -49,6 +49,8 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead
 find_package(llvm)
 find_package(clang)
 
+set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")
+
 if(ZIG_FORCE_EXTERNAL_LLD)
     find_package(lld)
     include_directories(${LLVM_INCLUDE_DIRS})
@@ -192,6 +194,7 @@ else()
         embedded_lld_coff
         embedded_lld_lib
     )
+    install(TARGETS embedded_lld_elf embedded_lld_coff embedded_lld_lib DESTINATION "${ZIG_CPP_LIB_DIR}")
 endif()
 
 # No patches have been applied to SoftFloat-3d
@@ -345,6 +348,8 @@ set(ZIG_SOURCES
     "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
     "${CMAKE_SOURCE_DIR}/src/util.cpp"
     "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
+)
+set(ZIG_CPP_SOURCES
     "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
 )
 
@@ -390,6 +395,8 @@ if(ZIG_TEST_COVERAGE)
     set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
 endif()
 
+add_library(zig_cpp STATIC ${ZIG_CPP_SOURCES})
+
 add_executable(zig ${ZIG_SOURCES})
 set_target_properties(zig PROPERTIES
     COMPILE_FLAGS ${EXE_CFLAGS}
@@ -397,6 +404,7 @@ set_target_properties(zig PROPERTIES
 )
 
 target_link_libraries(zig LINK_PUBLIC
+    zig_cpp
     ${SOFTFLOAT_LIBRARIES}
     ${CLANG_LIBRARIES}
     ${LLD_LIBRARIES}
@@ -407,6 +415,7 @@ if(MSVC OR MINGW)
     target_link_libraries(zig LINK_PUBLIC version)
 endif()
 install(TARGETS zig DESTINATION bin)
+install(TARGETS zig_cpp DESTINATION "${ZIG_CPP_LIB_DIR}")
 
 install(FILES "${CMAKE_SOURCE_DIR}/c_headers/__clang_cuda_builtin_vars.h" DESTINATION "${C_HEADERS_DEST}")
 install(FILES "${CMAKE_SOURCE_DIR}/c_headers/__clang_cuda_cmath.h" DESTINATION "${C_HEADERS_DEST}")
@@ -619,16 +628,3 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/udivti3.zig" DESTINAT
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/umodti3.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt")
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/panic.zig" DESTINATION "${ZIG_STD_DEST}/special")
 install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
-
-if (ZIG_TEST_COVERAGE)
-    add_custom_target(coverage
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        COMMAND lcov --directory . --zerocounters --rc lcov_branch_coverage=1
-        COMMAND ./zig build --build-file ../build.zig test
-        COMMAND lcov --directory . --capture --output-file coverage.info --rc lcov_branch_coverage=1
-        COMMAND lcov --remove coverage.info '/usr/*' --output-file coverage.info.cleaned --rc lcov_branch_coverage=1
-        COMMAND genhtml -o coverage coverage.info.cleaned --rc lcov_branch_coverage=1
-        COMMAND rm coverage.info coverage.info.cleaned
-    )
-endif()
-
README.md
@@ -26,7 +26,7 @@ clarity.
    always compiled against statically in source form. Compile units do not
    depend on libc unless explicitly linked.
  * Nullable type instead of null pointers.
- * Tagged union type instead of raw unions.
+ * Safe unions, tagged unions, and C ABI compatible unions.
  * Generics so that one can write efficient data structures that work for any
    data type.
  * No header files required. Top level declarations are entirely
@@ -35,7 +35,7 @@ clarity.
  * Partial compile-time function evaluation with eliminates the need for
    a preprocessor or macros.
  * The binaries produced by Zig have complete debugging information so you can,
-   for example, use GDB to debug your software.
+   for example, use GDB or MSVC to debug your software.
  * Built-in unit tests with `zig test`.
  * Friendly toward package maintainers. Reproducible build, bootstrapping
    process carefully documented. Issues filed by package maintainers are
@@ -78,10 +78,10 @@ that counts as "freestanding" for the purposes of this table.
 
 ### Wanted: Windows Developers
 
-Help get the tests passing on Windows, flesh out the standard library for
-Windows, streamline Zig installation and distribution for Windows. Work with
-LLVM and LLD teams to improve PDB/CodeView/MSVC debugging. Implement stack traces
-for Windows in the MinGW environment and the MSVC environment.
+Flesh out the standard library for Windows, streamline Zig installation and
+distribution for Windows. Work with LLVM and LLD teams to improve
+PDB/CodeView/MSVC debugging. Implement stack traces for Windows in the MinGW
+environment and the MSVC environment.
 
 ### Wanted: MacOS and iOS Developers
 
@@ -178,6 +178,10 @@ Dependencies are the same as Stage 1, except now you have a working zig compiler
 bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
 ```
 
+This produces `./stage2/bin/zig` which can be used for testing and development.
+Once it is feature complete, it will be used to build stage 3 - the final compiler
+binary.
+
 ### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
 
 This is the actual compiler binary that we will install to the system.
@@ -194,20 +198,6 @@ This is the actual compiler binary that we will install to the system.
 ./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
 ```
 
-### Test Coverage
-
-To see test coverage in Zig, configure with `-DZIG_TEST_COVERAGE=ON` as an
-additional parameter to the Debug build.
-
-You must have `lcov` installed and available.
-
-Then `make coverage`.
-
-With GCC you will get a nice HTML view of the coverage data. With clang,
-the last step will fail, but you can execute
-`llvm-cov gcov $(find CMakeFiles/ -name "*.gcda")` and then inspect the
-produced .gcov files.
-
 ### Related Projects
 
  * [zig-mode](https://github.com/AndreaOrru/zig-mode) - Emacs integration