Linker pipeline
This commit is contained in:
		
							parent
							
								
									8126a5e9e8
								
							
						
					
					
						commit
						7ee458b93b
					
				
							
								
								
									
										23
									
								
								build.zig
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								build.zig
									
									
									
									
									
								
							@ -102,12 +102,22 @@ const LLVM = struct {
 | 
				
			|||||||
        llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1" });
 | 
					        llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1" });
 | 
				
			||||||
        llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1/x86_64-pc-linux-gnu" });
 | 
					        llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1/x86_64-pc-linux-gnu" });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        llvm.addObjectFile(.{ .cwd_relative = "/usr/lib/libstdc++.so.6" });
 | 
					        const needed_libraries: []const []const u8 = &.{ "unwind", "z" };
 | 
				
			||||||
        llvm.linkSystemLibrary("unwind", .{});
 | 
					 | 
				
			||||||
        llvm.linkSystemLibrary("z", .{});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (llvm_libs.items) |llvm_lib| {
 | 
					        llvm.addObjectFile(.{ .cwd_relative = "/usr/lib/libstdc++.so.6" });
 | 
				
			||||||
            llvm.linkSystemLibrary(llvm_lib, .{});
 | 
					
 | 
				
			||||||
 | 
					        const lld_libs: []const []const u8 = &.{ "lldCommon", "lldCOFF", "lldELF", "lldMachO", "lldMinGW", "lldWasm" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (needed_libraries) |lib| {
 | 
				
			||||||
 | 
					            llvm.linkSystemLibrary(lib, .{});
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (llvm_libs.items) |lib| {
 | 
				
			||||||
 | 
					            llvm.linkSystemLibrary(lib, .{});
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (lld_libs) |lib| {
 | 
				
			||||||
 | 
					            llvm.linkSystemLibrary(lib, .{});
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return LLVM{
 | 
					        return LLVM{
 | 
				
			||||||
@ -118,6 +128,9 @@ const LLVM = struct {
 | 
				
			|||||||
    fn link(llvm: LLVM, target: *std.Build.Step.Compile) void {
 | 
					    fn link(llvm: LLVM, target: *std.Build.Step.Compile) void {
 | 
				
			||||||
        if (target.root_module != llvm.module) {
 | 
					        if (target.root_module != llvm.module) {
 | 
				
			||||||
            target.root_module.addImport("llvm", llvm.module);
 | 
					            target.root_module.addImport("llvm", llvm.module);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // TODO: should we allow this case?
 | 
				
			||||||
 | 
					            unreachable;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										70
									
								
								src/LLVM.zig
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								src/LLVM.zig
									
									
									
									
									
								
							@ -653,6 +653,14 @@ pub const DwarfEmissionKind = enum(c_int) {
 | 
				
			|||||||
    line_tables_only,
 | 
					    line_tables_only,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const lld = struct {
 | 
				
			||||||
 | 
					    pub const Result = extern struct {
 | 
				
			||||||
 | 
					        stdout: String,
 | 
				
			||||||
 | 
					        stderr: String,
 | 
				
			||||||
 | 
					        success: bool,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const Thread = struct {
 | 
					pub const Thread = struct {
 | 
				
			||||||
    context: *Context,
 | 
					    context: *Context,
 | 
				
			||||||
    i1: Integer,
 | 
					    i1: Integer,
 | 
				
			||||||
@ -734,6 +742,21 @@ pub fn initialize_all() void {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const LldArgvBuilder = struct {
 | 
				
			||||||
 | 
					    buffer: [1024]?[*:0]const u8 = undefined,
 | 
				
			||||||
 | 
					    count: usize = 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn add(builder: *LldArgvBuilder, arg: [*:0]const u8) void {
 | 
				
			||||||
 | 
					        builder.buffer[builder.count] = arg;
 | 
				
			||||||
 | 
					        builder.count += 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn flush(builder: *LldArgvBuilder) [:null]const ?[*:0]const u8 {
 | 
				
			||||||
 | 
					        builder.buffer[builder.count] = null;
 | 
				
			||||||
 | 
					        return builder.buffer[0..builder.count :null];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn experiment() void {
 | 
					pub fn experiment() void {
 | 
				
			||||||
    const thread = &global.threads[0];
 | 
					    const thread = &global.threads[0];
 | 
				
			||||||
    thread.initialize();
 | 
					    thread.initialize();
 | 
				
			||||||
@ -780,8 +803,9 @@ pub fn experiment() void {
 | 
				
			|||||||
    module.set_target(target_machine);
 | 
					    module.set_target(target_machine);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    module.run_optimization_pipeline(target_machine, OptimizationPipelineOptions.default(.{ .optimization_level = .O3, .debug_info = 1 }));
 | 
					    module.run_optimization_pipeline(target_machine, OptimizationPipelineOptions.default(.{ .optimization_level = .O3, .debug_info = 1 }));
 | 
				
			||||||
 | 
					    const object_path = ".zig-cache/foo.o";
 | 
				
			||||||
    const result = module.run_code_generation_pipeline(target_machine, CodeGenerationPipelineOptions{
 | 
					    const result = module.run_code_generation_pipeline(target_machine, CodeGenerationPipelineOptions{
 | 
				
			||||||
        .output_file_path = String.from_slice(".zig-cache/foo.o"),
 | 
					        .output_file_path = String.from_slice(object_path),
 | 
				
			||||||
        .output_dwarf_file_path = .{},
 | 
					        .output_dwarf_file_path = .{},
 | 
				
			||||||
        .flags = .{
 | 
					        .flags = .{
 | 
				
			||||||
            .code_generation_file_type = .object_file,
 | 
					            .code_generation_file_type = .object_file,
 | 
				
			||||||
@ -792,4 +816,48 @@ pub fn experiment() void {
 | 
				
			|||||||
    if (result != .success) {
 | 
					    if (result != .success) {
 | 
				
			||||||
        unreachable;
 | 
					        unreachable;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var arg_builder = LldArgvBuilder{};
 | 
				
			||||||
 | 
					    arg_builder.add("ld.lld");
 | 
				
			||||||
 | 
					    arg_builder.add("--error-limit=0");
 | 
				
			||||||
 | 
					    arg_builder.add("-o");
 | 
				
			||||||
 | 
					    arg_builder.add(".zig-cache/foo");
 | 
				
			||||||
 | 
					    const objects: []const [*:0]const u8 = &.{object_path};
 | 
				
			||||||
 | 
					    for (objects) |object| {
 | 
				
			||||||
 | 
					        arg_builder.add(object);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arg_builder.add("-L/usr/lib");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const link_libcpp = false;
 | 
				
			||||||
 | 
					    if (link_libcpp) {
 | 
				
			||||||
 | 
					        arg_builder.add("-lstdc++");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const link_libc = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dynamic_linker = true;
 | 
				
			||||||
 | 
					    if (dynamic_linker) {
 | 
				
			||||||
 | 
					        arg_builder.add("-dynamic-linker");
 | 
				
			||||||
 | 
					        arg_builder.add("/usr/lib/ld-linux-x86-64.so.2");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (link_libc) {
 | 
				
			||||||
 | 
					        arg_builder.add("/usr/lib/Scrt1.o");
 | 
				
			||||||
 | 
					        arg_builder.add("-lc");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const lld_args = arg_builder.flush();
 | 
				
			||||||
 | 
					    const lld_result = api.lld_elf_link(lld_args.ptr, lld_args.len, true, false);
 | 
				
			||||||
 | 
					    const success = lld_result.success and lld_result.stderr.length == 0;
 | 
				
			||||||
 | 
					    if (!success) {
 | 
				
			||||||
 | 
					        if (lld_result.stdout.length != 0) {
 | 
				
			||||||
 | 
					            lib.print_string(lld_result.stdout.to_slice() orelse unreachable);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (lld_result.stderr.length != 0) {
 | 
				
			||||||
 | 
					            lib.print_string(lld_result.stderr.to_slice() orelse unreachable);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        lib.libc.exit(1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										87
									
								
								src/llvm.cpp
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								src/llvm.cpp
									
									
									
									
									
								
							@ -1,5 +1,13 @@
 | 
				
			|||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef uint8_t u8;
 | 
				
			||||||
 | 
					typedef uint16_t u16;
 | 
				
			||||||
 | 
					typedef uint32_t u32;
 | 
				
			||||||
 | 
					typedef uint64_t u64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXPORT extern "C"
 | 
				
			||||||
 | 
					#define fn static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "llvm/IR/IRBuilder.h"
 | 
					#include "llvm/IR/IRBuilder.h"
 | 
				
			||||||
#include "llvm/IR/Module.h"
 | 
					#include "llvm/IR/Module.h"
 | 
				
			||||||
#include "llvm/IR/Verifier.h"
 | 
					#include "llvm/IR/Verifier.h"
 | 
				
			||||||
@ -21,13 +29,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "llvm/Support/FileSystem.h"
 | 
					#include "llvm/Support/FileSystem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EXPORT extern "C"
 | 
					#include "lld/Common/Driver.h"
 | 
				
			||||||
#define fn static
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef uint8_t u8;
 | 
					 | 
				
			||||||
typedef uint16_t u16;
 | 
					 | 
				
			||||||
typedef uint32_t u32;
 | 
					 | 
				
			||||||
typedef uint64_t u64;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace llvm;
 | 
					using namespace llvm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -905,3 +908,75 @@ EXPORT BBLLVMCodeGenerationPipelineResult llvm_module_run_code_generation_pipeli
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return BBLLVMCodeGenerationPipelineResult::success;
 | 
					    return BBLLVMCodeGenerationPipelineResult::success;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct LLDResult
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BBLLVMString stdout_string;
 | 
				
			||||||
 | 
					    BBLLVMString stderr_string;
 | 
				
			||||||
 | 
					    bool success;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define lld_api_args() const char** argument_pointer, u64 argument_count, bool exit_early, bool disable_output
 | 
				
			||||||
 | 
					#define lld_api_function_decl(link_name) LLDResult lld_ ## link_name ## _link(lld_api_args())
 | 
				
			||||||
 | 
					#define lld_api_function_signature(name) bool name(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define lld_link_decl(link_name) \
 | 
				
			||||||
 | 
					namespace link_name \
 | 
				
			||||||
 | 
					{\
 | 
				
			||||||
 | 
					    lld_api_function_signature(link);\
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef lld_api_function_signature(LinkerFunction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace lld
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lld_link_decl(coff);
 | 
				
			||||||
 | 
					    lld_link_decl(elf);
 | 
				
			||||||
 | 
					    lld_link_decl(mingw);
 | 
				
			||||||
 | 
					    lld_link_decl(macho);
 | 
				
			||||||
 | 
					    lld_link_decl(wasm);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn LLDResult lld_api_generic(lld_api_args(), LinkerFunction linker_function)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    LLDResult result = {};
 | 
				
			||||||
 | 
					    auto arguments = llvm::ArrayRef(argument_pointer, argument_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string stdout_string;
 | 
				
			||||||
 | 
					    llvm::raw_string_ostream stdout_stream(stdout_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string stderr_string;
 | 
				
			||||||
 | 
					    llvm::raw_string_ostream stderr_stream(stderr_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result.success = linker_function(arguments, stdout_stream, stderr_stream, exit_early, disable_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto stdout_length = stdout_string.length();
 | 
				
			||||||
 | 
					    if (stdout_length)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto* stdout_pointer = new char[stdout_length];
 | 
				
			||||||
 | 
					        memcpy(stdout_pointer, stdout_string.data(), stdout_length);
 | 
				
			||||||
 | 
					        result.stdout_string = { stdout_pointer, stdout_length };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto stderr_length = stderr_string.length();
 | 
				
			||||||
 | 
					    if (stderr_length)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto* stderr_pointer = new char[stderr_length];
 | 
				
			||||||
 | 
					        memcpy(stderr_pointer, stderr_string.data(), stderr_length);
 | 
				
			||||||
 | 
					        result.stderr_string = { stderr_pointer, stderr_length };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define lld_api_function_impl(link_name) \
 | 
				
			||||||
 | 
					EXPORT lld_api_function_decl(link_name)\
 | 
				
			||||||
 | 
					{\
 | 
				
			||||||
 | 
					    return lld_api_generic(argument_pointer, argument_count, exit_early, disable_output, lld::link_name::link);\
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lld_api_function_impl(coff)
 | 
				
			||||||
 | 
					lld_api_function_impl(elf)
 | 
				
			||||||
 | 
					lld_api_function_impl(mingw)
 | 
				
			||||||
 | 
					lld_api_function_impl(macho)
 | 
				
			||||||
 | 
					lld_api_function_impl(wasm)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
const llvm = @import("LLVM.zig");
 | 
					const llvm = @import("LLVM.zig");
 | 
				
			||||||
 | 
					const lld = llvm.lld;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Bool = c_int;
 | 
					const Bool = c_int;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -118,3 +119,7 @@ pub fn get_initializer(comptime llvm_arch: llvm.Architecture) type {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LLD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub extern fn lld_elf_link(argument_pointer: [*:null]const ?[*:0]const u8, argument_length: u64, exit_early: bool, disable_output: bool) lld.Result;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user