| author | |
| committer | |
| log | 2df2f0020f4ddc41b3b914cd17efcb403cf0f6ad |
| tree | 8826f40cd08a1cbe945e82bc3f2495a0ed42ad7d |
| parent | f75d4cbe56f9f8212581f00700600a57ce545ba1 |
| parent | ec3aedffb173845b3fe6f7559e06e1bc3cfde6f7 |
| signature |
stage2: add initial impl of LLVM backend in self-hosted compiler14 files changed, 1069 insertions(+), 293 deletions(-)
CMakeLists.txt+2-2| ... | @@ -527,7 +527,6 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -527,7 +527,6 @@ set(ZIG_STAGE2_SOURCES |
| 527 | "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig" | 527 | "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig" |
| 528 | "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig" | 528 | "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig" |
| 529 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" | 529 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" |
| 530 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" | ||
| 531 | "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig" | 530 | "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig" |
| 532 | "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig" | 531 | "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig" |
| 533 | "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig" | 532 | "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig" |
| ... | @@ -549,7 +548,8 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -549,7 +548,8 @@ set(ZIG_STAGE2_SOURCES |
| 549 | "${CMAKE_SOURCE_DIR}/src/link/cbe.h" | 548 | "${CMAKE_SOURCE_DIR}/src/link/cbe.h" |
| 550 | "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin" | 549 | "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin" |
| 551 | "${CMAKE_SOURCE_DIR}/src/liveness.zig" | 550 | "${CMAKE_SOURCE_DIR}/src/liveness.zig" |
| 552 | "${CMAKE_SOURCE_DIR}/src/llvm.zig" | 551 | "${CMAKE_SOURCE_DIR}/src/llvm_backend.zig" |
| 552 | "${CMAKE_SOURCE_DIR}/src/llvm_bindings.zig" | ||
| 553 | "${CMAKE_SOURCE_DIR}/src/main.zig" | 553 | "${CMAKE_SOURCE_DIR}/src/main.zig" |
| 554 | "${CMAKE_SOURCE_DIR}/src/mingw.zig" | 554 | "${CMAKE_SOURCE_DIR}/src/mingw.zig" |
| 555 | "${CMAKE_SOURCE_DIR}/src/musl.zig" | 555 | "${CMAKE_SOURCE_DIR}/src/musl.zig" |
build.zig+20-13| ... | @@ -91,6 +91,20 @@ pub fn build(b: *Builder) !void { | ... | @@ -91,6 +91,20 @@ pub fn build(b: *Builder) !void { |
| 91 | exe.addBuildOption(bool, "have_llvm", enable_llvm); | 91 | exe.addBuildOption(bool, "have_llvm", enable_llvm); |
| 92 | if (enable_llvm) { | 92 | if (enable_llvm) { |
| 93 | const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option); | 93 | const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option); |
| 94 | |||
| 95 | const exe_cflags = [_][]const u8{ | ||
| 96 | "-std=c++14", | ||
| 97 | "-D__STDC_CONSTANT_MACROS", | ||
| 98 | "-D__STDC_FORMAT_MACROS", | ||
| 99 | "-D__STDC_LIMIT_MACROS", | ||
| 100 | "-D_GNU_SOURCE", | ||
| 101 | "-fvisibility-inlines-hidden", | ||
| 102 | "-fno-exceptions", | ||
| 103 | "-fno-rtti", | ||
| 104 | "-Werror=type-limits", | ||
| 105 | "-Wno-missing-braces", | ||
| 106 | "-Wno-comment", | ||
| 107 | }; | ||
| 94 | if (is_stage1) { | 108 | if (is_stage1) { |
| 95 | exe.addIncludeDir("src"); | 109 | exe.addIncludeDir("src"); |
| 96 | exe.addIncludeDir("deps/SoftFloat-3e/source/include"); | 110 | exe.addIncludeDir("deps/SoftFloat-3e/source/include"); |
| ... | @@ -109,19 +123,6 @@ pub fn build(b: *Builder) !void { | ... | @@ -109,19 +123,6 @@ pub fn build(b: *Builder) !void { |
| 109 | softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" }); | 123 | softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" }); |
| 110 | exe.linkLibrary(softfloat); | 124 | exe.linkLibrary(softfloat); |
| 111 | 125 | ||
| 112 | const exe_cflags = [_][]const u8{ | ||
| 113 | "-std=c++14", | ||
| 114 | "-D__STDC_CONSTANT_MACROS", | ||
| 115 | "-D__STDC_FORMAT_MACROS", | ||
| 116 | "-D__STDC_LIMIT_MACROS", | ||
| 117 | "-D_GNU_SOURCE", | ||
| 118 | "-fvisibility-inlines-hidden", | ||
| 119 | "-fno-exceptions", | ||
| 120 | "-fno-rtti", | ||
| 121 | "-Werror=type-limits", | ||
| 122 | "-Wno-missing-braces", | ||
| 123 | "-Wno-comment", | ||
| 124 | }; | ||
| 125 | exe.addCSourceFiles(&stage1_sources, &exe_cflags); | 126 | exe.addCSourceFiles(&stage1_sources, &exe_cflags); |
| 126 | exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); | 127 | exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); |
| 127 | if (cmake_cfg == null) { | 128 | if (cmake_cfg == null) { |
| ... | @@ -205,6 +206,12 @@ pub fn build(b: *Builder) !void { | ... | @@ -205,6 +206,12 @@ pub fn build(b: *Builder) !void { |
| 205 | exe.linkSystemLibrary(lib_name); | 206 | exe.linkSystemLibrary(lib_name); |
| 206 | } | 207 | } |
| 207 | 208 | ||
| 209 | // We need this because otherwise zig_clang_cc1_main.cpp ends up pulling | ||
| 210 | // in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is | ||
| 211 | // unavailable when LLVM is compiled in Release mode. | ||
| 212 | const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"}; | ||
| 213 | exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags); | ||
| 214 | |||
| 208 | // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. | 215 | // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. |
| 209 | exe.linkSystemLibrary("c++"); | 216 | exe.linkSystemLibrary("c++"); |
| 210 | 217 |
src/Compilation.zig+1-1| ... | @@ -2106,7 +2106,7 @@ pub fn addCCArgs( | ... | @@ -2106,7 +2106,7 @@ pub fn addCCArgs( |
| 2106 | try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); | 2106 | try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); |
| 2107 | } | 2107 | } |
| 2108 | 2108 | ||
| 2109 | const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target); | 2109 | const llvm_triple = try @import("llvm_backend.zig").targetTriple(arena, target); |
| 2110 | try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); | 2110 | try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); |
| 2111 | 2111 | ||
| 2112 | switch (ext) { | 2112 | switch (ext) { |
src/codegen/llvm.zig deleted-125| ... | @@ -1,125 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Allocator = std.mem.Allocator; | ||
| 3 | |||
| 4 | pub fn targetTriple(allocator: *Allocator, target: std.Target) ![]u8 { | ||
| 5 | const llvm_arch = switch (target.cpu.arch) { | ||
| 6 | .arm => "arm", | ||
| 7 | .armeb => "armeb", | ||
| 8 | .aarch64 => "aarch64", | ||
| 9 | .aarch64_be => "aarch64_be", | ||
| 10 | .aarch64_32 => "aarch64_32", | ||
| 11 | .arc => "arc", | ||
| 12 | .avr => "avr", | ||
| 13 | .bpfel => "bpfel", | ||
| 14 | .bpfeb => "bpfeb", | ||
| 15 | .hexagon => "hexagon", | ||
| 16 | .mips => "mips", | ||
| 17 | .mipsel => "mipsel", | ||
| 18 | .mips64 => "mips64", | ||
| 19 | .mips64el => "mips64el", | ||
| 20 | .msp430 => "msp430", | ||
| 21 | .powerpc => "powerpc", | ||
| 22 | .powerpc64 => "powerpc64", | ||
| 23 | .powerpc64le => "powerpc64le", | ||
| 24 | .r600 => "r600", | ||
| 25 | .amdgcn => "amdgcn", | ||
| 26 | .riscv32 => "riscv32", | ||
| 27 | .riscv64 => "riscv64", | ||
| 28 | .sparc => "sparc", | ||
| 29 | .sparcv9 => "sparcv9", | ||
| 30 | .sparcel => "sparcel", | ||
| 31 | .s390x => "s390x", | ||
| 32 | .tce => "tce", | ||
| 33 | .tcele => "tcele", | ||
| 34 | .thumb => "thumb", | ||
| 35 | .thumbeb => "thumbeb", | ||
| 36 | .i386 => "i386", | ||
| 37 | .x86_64 => "x86_64", | ||
| 38 | .xcore => "xcore", | ||
| 39 | .nvptx => "nvptx", | ||
| 40 | .nvptx64 => "nvptx64", | ||
| 41 | .le32 => "le32", | ||
| 42 | .le64 => "le64", | ||
| 43 | .amdil => "amdil", | ||
| 44 | .amdil64 => "amdil64", | ||
| 45 | .hsail => "hsail", | ||
| 46 | .hsail64 => "hsail64", | ||
| 47 | .spir => "spir", | ||
| 48 | .spir64 => "spir64", | ||
| 49 | .kalimba => "kalimba", | ||
| 50 | .shave => "shave", | ||
| 51 | .lanai => "lanai", | ||
| 52 | .wasm32 => "wasm32", | ||
| 53 | .wasm64 => "wasm64", | ||
| 54 | .renderscript32 => "renderscript32", | ||
| 55 | .renderscript64 => "renderscript64", | ||
| 56 | .ve => "ve", | ||
| 57 | .spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII, | ||
| 58 | }; | ||
| 59 | // TODO Add a sub-arch for some architectures depending on CPU features. | ||
| 60 | |||
| 61 | const llvm_os = switch (target.os.tag) { | ||
| 62 | .freestanding => "unknown", | ||
| 63 | .ananas => "ananas", | ||
| 64 | .cloudabi => "cloudabi", | ||
| 65 | .dragonfly => "dragonfly", | ||
| 66 | .freebsd => "freebsd", | ||
| 67 | .fuchsia => "fuchsia", | ||
| 68 | .ios => "ios", | ||
| 69 | .kfreebsd => "kfreebsd", | ||
| 70 | .linux => "linux", | ||
| 71 | .lv2 => "lv2", | ||
| 72 | .macos => "macosx", | ||
| 73 | .netbsd => "netbsd", | ||
| 74 | .openbsd => "openbsd", | ||
| 75 | .solaris => "solaris", | ||
| 76 | .windows => "windows", | ||
| 77 | .haiku => "haiku", | ||
| 78 | .minix => "minix", | ||
| 79 | .rtems => "rtems", | ||
| 80 | .nacl => "nacl", | ||
| 81 | .cnk => "cnk", | ||
| 82 | .aix => "aix", | ||
| 83 | .cuda => "cuda", | ||
| 84 | .nvcl => "nvcl", | ||
| 85 | .amdhsa => "amdhsa", | ||
| 86 | .ps4 => "ps4", | ||
| 87 | .elfiamcu => "elfiamcu", | ||
| 88 | .tvos => "tvos", | ||
| 89 | .watchos => "watchos", | ||
| 90 | .mesa3d => "mesa3d", | ||
| 91 | .contiki => "contiki", | ||
| 92 | .amdpal => "amdpal", | ||
| 93 | .hermit => "hermit", | ||
| 94 | .hurd => "hurd", | ||
| 95 | .wasi => "wasi", | ||
| 96 | .emscripten => "emscripten", | ||
| 97 | .uefi => "windows", | ||
| 98 | .other => "unknown", | ||
| 99 | }; | ||
| 100 | |||
| 101 | const llvm_abi = switch (target.abi) { | ||
| 102 | .none => "unknown", | ||
| 103 | .gnu => "gnu", | ||
| 104 | .gnuabin32 => "gnuabin32", | ||
| 105 | .gnuabi64 => "gnuabi64", | ||
| 106 | .gnueabi => "gnueabi", | ||
| 107 | .gnueabihf => "gnueabihf", | ||
| 108 | .gnux32 => "gnux32", | ||
| 109 | .code16 => "code16", | ||
| 110 | .eabi => "eabi", | ||
| 111 | .eabihf => "eabihf", | ||
| 112 | .android => "android", | ||
| 113 | .musl => "musl", | ||
| 114 | .musleabi => "musleabi", | ||
| 115 | .musleabihf => "musleabihf", | ||
| 116 | .msvc => "msvc", | ||
| 117 | .itanium => "itanium", | ||
| 118 | .cygnus => "cygnus", | ||
| 119 | .coreclr => "coreclr", | ||
| 120 | .simulator => "simulator", | ||
| 121 | .macabi => "macabi", | ||
| 122 | }; | ||
| 123 | |||
| 124 | return std.fmt.allocPrint(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi }); | ||
| 125 | } | ||
src/link.zig+1-1| ... | @@ -567,7 +567,7 @@ pub const File = struct { | ... | @@ -567,7 +567,7 @@ pub const File = struct { |
| 567 | std.debug.print("\n", .{}); | 567 | std.debug.print("\n", .{}); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | const llvm = @import("llvm.zig"); | 570 | const llvm = @import("llvm_bindings.zig"); |
| 571 | const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag); | 571 | const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag); |
| 572 | const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type); | 572 | const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type); |
| 573 | if (bad) return error.UnableToWriteArchive; | 573 | if (bad) return error.UnableToWriteArchive; |
src/link/Coff.zig+29-3| ... | @@ -16,6 +16,7 @@ const link = @import("../link.zig"); | ... | @@ -16,6 +16,7 @@ const link = @import("../link.zig"); |
| 16 | const build_options = @import("build_options"); | 16 | const build_options = @import("build_options"); |
| 17 | const Cache = @import("../Cache.zig"); | 17 | const Cache = @import("../Cache.zig"); |
| 18 | const mingw = @import("../mingw.zig"); | 18 | const mingw = @import("../mingw.zig"); |
| 19 | const llvm_backend = @import("../llvm_backend.zig"); | ||
| 19 | 20 | ||
| 20 | const allocation_padding = 4 / 3; | 21 | const allocation_padding = 4 / 3; |
| 21 | const minimum_text_block_size = 64 * allocation_padding; | 22 | const minimum_text_block_size = 64 * allocation_padding; |
| ... | @@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff; | ... | @@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff; |
| 32 | 33 | ||
| 33 | const msdos_stub = @embedFile("msdos-stub.bin"); | 34 | const msdos_stub = @embedFile("msdos-stub.bin"); |
| 34 | 35 | ||
| 36 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. | ||
| 37 | llvm_ir_module: ?*llvm_backend.LLVMIRModule = null, | ||
| 38 | |||
| 35 | base: link.File, | 39 | base: link.File, |
| 36 | ptr_width: PtrWidth, | 40 | ptr_width: PtrWidth, |
| 37 | error_flags: link.File.ErrorFlags = .{}, | 41 | error_flags: link.File.ErrorFlags = .{}, |
| ... | @@ -121,8 +125,13 @@ pub const SrcFn = void; | ... | @@ -121,8 +125,13 @@ pub const SrcFn = void; |
| 121 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff { | 125 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff { |
| 122 | assert(options.object_format == .coff); | 126 | assert(options.object_format == .coff); |
| 123 | 127 | ||
| 124 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO | 128 | if (build_options.have_llvm and options.use_llvm) { |
| 125 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO | 129 | const self = try createEmpty(allocator, options); |
| 130 | errdefer self.base.destroy(); | ||
| 131 | |||
| 132 | self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options); | ||
| 133 | return self; | ||
| 134 | } | ||
| 126 | 135 | ||
| 127 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ | 136 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 128 | .truncate = false, | 137 | .truncate = false, |
| ... | @@ -404,6 +413,8 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff { | ... | @@ -404,6 +413,8 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff { |
| 404 | } | 413 | } |
| 405 | 414 | ||
| 406 | pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void { | 415 | pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void { |
| 416 | if (self.llvm_ir_module) |_| return; | ||
| 417 | |||
| 407 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); | 418 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); |
| 408 | 419 | ||
| 409 | if (self.offset_table_free_list.popOrNull()) |i| { | 420 | if (self.offset_table_free_list.popOrNull()) |i| { |
| ... | @@ -648,6 +659,9 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { | ... | @@ -648,6 +659,9 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 648 | const tracy = trace(@src()); | 659 | const tracy = trace(@src()); |
| 649 | defer tracy.end(); | 660 | defer tracy.end(); |
| 650 | 661 | ||
| 662 | if (build_options.have_llvm) | ||
| 663 | if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl); | ||
| 664 | |||
| 651 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 665 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 652 | defer code_buffer.deinit(); | 666 | defer code_buffer.deinit(); |
| 653 | 667 | ||
| ... | @@ -698,12 +712,16 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { | ... | @@ -698,12 +712,16 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 698 | } | 712 | } |
| 699 | 713 | ||
| 700 | pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { | 714 | pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { |
| 715 | if (self.llvm_ir_module) |_| return; | ||
| 716 | |||
| 701 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 717 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 702 | self.freeTextBlock(&decl.link.coff); | 718 | self.freeTextBlock(&decl.link.coff); |
| 703 | self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {}; | 719 | self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {}; |
| 704 | } | 720 | } |
| 705 | 721 | ||
| 706 | pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void { | 722 | pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void { |
| 723 | if (self.llvm_ir_module) |_| return; | ||
| 724 | |||
| 707 | for (exports) |exp| { | 725 | for (exports) |exp| { |
| 708 | if (exp.options.section) |section_name| { | 726 | if (exp.options.section) |section_name| { |
| 709 | if (!mem.eql(u8, section_name, ".text")) { | 727 | if (!mem.eql(u8, section_name, ".text")) { |
| ... | @@ -744,6 +762,9 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { | ... | @@ -744,6 +762,9 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { |
| 744 | const tracy = trace(@src()); | 762 | const tracy = trace(@src()); |
| 745 | defer tracy.end(); | 763 | defer tracy.end(); |
| 746 | 764 | ||
| 765 | if (build_options.have_llvm) | ||
| 766 | if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp); | ||
| 767 | |||
| 747 | if (self.text_section_size_dirty) { | 768 | if (self.text_section_size_dirty) { |
| 748 | // Write the new raw size in the .text header | 769 | // Write the new raw size in the .text header |
| 749 | var buf: [4]u8 = undefined; | 770 | var buf: [4]u8 = undefined; |
| ... | @@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 1124 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 1145 | try argv.append(comp.libunwind_static_lib.?.full_object_path); |
| 1125 | } | 1146 | } |
| 1126 | 1147 | ||
| 1148 | // TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig | ||
| 1127 | // compiler-rt, libc and libssp | 1149 | // compiler-rt, libc and libssp |
| 1128 | if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) { | 1150 | if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and build_options.is_stage1) { |
| 1129 | if (!self.base.options.link_libc) { | 1151 | if (!self.base.options.link_libc) { |
| 1130 | try argv.append(comp.libc_static_lib.?.full_object_path); | 1152 | try argv.append(comp.libc_static_lib.?.full_object_path); |
| 1131 | } | 1153 | } |
| ... | @@ -1227,6 +1249,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -1227,6 +1249,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 1227 | } | 1249 | } |
| 1228 | 1250 | ||
| 1229 | pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 { | 1251 | pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 { |
| 1252 | assert(self.llvm_ir_module == null); | ||
| 1230 | return self.text_section_virtual_address + decl.link.coff.text_offset; | 1253 | return self.text_section_virtual_address + decl.link.coff.text_offset; |
| 1231 | } | 1254 | } |
| 1232 | 1255 | ||
| ... | @@ -1235,6 +1258,9 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v | ... | @@ -1235,6 +1258,9 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v |
| 1235 | } | 1258 | } |
| 1236 | 1259 | ||
| 1237 | pub fn deinit(self: *Coff) void { | 1260 | pub fn deinit(self: *Coff) void { |
| 1261 | if (build_options.have_llvm) | ||
| 1262 | if (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator); | ||
| 1263 | |||
| 1238 | self.text_block_free_list.deinit(self.base.allocator); | 1264 | self.text_block_free_list.deinit(self.base.allocator); |
| 1239 | self.offset_table.deinit(self.base.allocator); | 1265 | self.offset_table.deinit(self.base.allocator); |
| 1240 | self.offset_table_free_list.deinit(self.base.allocator); | 1266 | self.offset_table_free_list.deinit(self.base.allocator); |
src/link/Elf.zig+43-2| ... | @@ -24,6 +24,7 @@ const build_options = @import("build_options"); | ... | @@ -24,6 +24,7 @@ const build_options = @import("build_options"); |
| 24 | const target_util = @import("../target.zig"); | 24 | const target_util = @import("../target.zig"); |
| 25 | const glibc = @import("../glibc.zig"); | 25 | const glibc = @import("../glibc.zig"); |
| 26 | const Cache = @import("../Cache.zig"); | 26 | const Cache = @import("../Cache.zig"); |
| 27 | const llvm_backend = @import("../llvm_backend.zig"); | ||
| 27 | 28 | ||
| 28 | const default_entry_addr = 0x8000000; | 29 | const default_entry_addr = 0x8000000; |
| 29 | 30 | ||
| ... | @@ -33,6 +34,9 @@ base: File, | ... | @@ -33,6 +34,9 @@ base: File, |
| 33 | 34 | ||
| 34 | ptr_width: PtrWidth, | 35 | ptr_width: PtrWidth, |
| 35 | 36 | ||
| 37 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. | ||
| 38 | llvm_ir_module: ?*llvm_backend.LLVMIRModule = null, | ||
| 39 | |||
| 36 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 40 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 37 | /// Same order as in the file. | 41 | /// Same order as in the file. |
| 38 | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){}, | 42 | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){}, |
| ... | @@ -224,7 +228,13 @@ pub const SrcFn = struct { | ... | @@ -224,7 +228,13 @@ pub const SrcFn = struct { |
| 224 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Elf { | 228 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Elf { |
| 225 | assert(options.object_format == .elf); | 229 | assert(options.object_format == .elf); |
| 226 | 230 | ||
| 227 | if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO | 231 | if (build_options.have_llvm and options.use_llvm) { |
| 232 | const self = try createEmpty(allocator, options); | ||
| 233 | errdefer self.base.destroy(); | ||
| 234 | |||
| 235 | self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options); | ||
| 236 | return self; | ||
| 237 | } | ||
| 228 | 238 | ||
| 229 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ | 239 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 230 | .truncate = false, | 240 | .truncate = false, |
| ... | @@ -288,6 +298,10 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf { | ... | @@ -288,6 +298,10 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf { |
| 288 | } | 298 | } |
| 289 | 299 | ||
| 290 | pub fn deinit(self: *Elf) void { | 300 | pub fn deinit(self: *Elf) void { |
| 301 | if (build_options.have_llvm) | ||
| 302 | if (self.llvm_ir_module) |ir_module| | ||
| 303 | ir_module.deinit(self.base.allocator); | ||
| 304 | |||
| 291 | self.sections.deinit(self.base.allocator); | 305 | self.sections.deinit(self.base.allocator); |
| 292 | self.program_headers.deinit(self.base.allocator); | 306 | self.program_headers.deinit(self.base.allocator); |
| 293 | self.shstrtab.deinit(self.base.allocator); | 307 | self.shstrtab.deinit(self.base.allocator); |
| ... | @@ -304,6 +318,7 @@ pub fn deinit(self: *Elf) void { | ... | @@ -304,6 +318,7 @@ pub fn deinit(self: *Elf) void { |
| 304 | } | 318 | } |
| 305 | 319 | ||
| 306 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { | 320 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { |
| 321 | assert(self.llvm_ir_module == null); | ||
| 307 | assert(decl.link.elf.local_sym_index != 0); | 322 | assert(decl.link.elf.local_sym_index != 0); |
| 308 | return self.local_symbols.items[decl.link.elf.local_sym_index].st_value; | 323 | return self.local_symbols.items[decl.link.elf.local_sym_index].st_value; |
| 309 | } | 324 | } |
| ... | @@ -423,6 +438,8 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { | ... | @@ -423,6 +438,8 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { |
| 423 | } | 438 | } |
| 424 | 439 | ||
| 425 | pub fn populateMissingMetadata(self: *Elf) !void { | 440 | pub fn populateMissingMetadata(self: *Elf) !void { |
| 441 | assert(self.llvm_ir_module == null); | ||
| 442 | |||
| 426 | const small_ptr = switch (self.ptr_width) { | 443 | const small_ptr = switch (self.ptr_width) { |
| 427 | .p32 => true, | 444 | .p32 => true, |
| 428 | .p64 => false, | 445 | .p64 => false, |
| ... | @@ -727,6 +744,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { | ... | @@ -727,6 +744,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 727 | const tracy = trace(@src()); | 744 | const tracy = trace(@src()); |
| 728 | defer tracy.end(); | 745 | defer tracy.end(); |
| 729 | 746 | ||
| 747 | if (build_options.have_llvm) | ||
| 748 | if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp); | ||
| 749 | |||
| 730 | // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the | 750 | // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the |
| 731 | // Zig source code. | 751 | // Zig source code. |
| 732 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 752 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| ... | @@ -1261,6 +1281,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1261,6 +1281,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1261 | const stack_size = self.base.options.stack_size_override orelse 16777216; | 1281 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| 1262 | const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; | 1282 | const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; |
| 1263 | const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: { | 1283 | const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: { |
| 1284 | // TODO: remove when stage2 can build compiler_rt.zig | ||
| 1285 | if (!build_options.is_stage1) break :blk null; | ||
| 1286 | |||
| 1264 | if (is_exe_or_dyn_lib) { | 1287 | if (is_exe_or_dyn_lib) { |
| 1265 | break :blk comp.compiler_rt_static_lib.?.full_object_path; | 1288 | break :blk comp.compiler_rt_static_lib.?.full_object_path; |
| 1266 | } else { | 1289 | } else { |
| ... | @@ -1552,7 +1575,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1552,7 +1575,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1552 | } | 1575 | } |
| 1553 | 1576 | ||
| 1554 | // libc | 1577 | // libc |
| 1555 | if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and !self.base.options.link_libc) { | 1578 | // TODO: enable when stage2 can build c.zig |
| 1579 | if (is_exe_or_dyn_lib and | ||
| 1580 | !self.base.options.skip_linker_dependencies and | ||
| 1581 | !self.base.options.link_libc and | ||
| 1582 | build_options.is_stage1) | ||
| 1583 | { | ||
| 1556 | try argv.append(comp.libc_static_lib.?.full_object_path); | 1584 | try argv.append(comp.libc_static_lib.?.full_object_path); |
| 1557 | } | 1585 | } |
| 1558 | 1586 | ||
| ... | @@ -2046,6 +2074,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2046,6 +2074,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2046 | } | 2074 | } |
| 2047 | 2075 | ||
| 2048 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | 2076 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2077 | if (self.llvm_ir_module) |_| return; | ||
| 2078 | |||
| 2049 | if (decl.link.elf.local_sym_index != 0) return; | 2079 | if (decl.link.elf.local_sym_index != 0) return; |
| 2050 | 2080 | ||
| 2051 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); | 2081 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); |
| ... | @@ -2082,6 +2112,8 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | ... | @@ -2082,6 +2112,8 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2082 | } | 2112 | } |
| 2083 | 2113 | ||
| 2084 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | 2114 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 2115 | if (self.llvm_ir_module) |_| return; | ||
| 2116 | |||
| 2085 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 2117 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 2086 | self.freeTextBlock(&decl.link.elf); | 2118 | self.freeTextBlock(&decl.link.elf); |
| 2087 | if (decl.link.elf.local_sym_index != 0) { | 2119 | if (decl.link.elf.local_sym_index != 0) { |
| ... | @@ -2119,6 +2151,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | ... | @@ -2119,6 +2151,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2119 | const tracy = trace(@src()); | 2151 | const tracy = trace(@src()); |
| 2120 | defer tracy.end(); | 2152 | defer tracy.end(); |
| 2121 | 2153 | ||
| 2154 | if (build_options.have_llvm) | ||
| 2155 | if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl); | ||
| 2156 | |||
| 2122 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 2157 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2123 | defer code_buffer.deinit(); | 2158 | defer code_buffer.deinit(); |
| 2124 | 2159 | ||
| ... | @@ -2594,6 +2629,8 @@ pub fn updateDeclExports( | ... | @@ -2594,6 +2629,8 @@ pub fn updateDeclExports( |
| 2594 | decl: *const Module.Decl, | 2629 | decl: *const Module.Decl, |
| 2595 | exports: []const *Module.Export, | 2630 | exports: []const *Module.Export, |
| 2596 | ) !void { | 2631 | ) !void { |
| 2632 | if (self.llvm_ir_module) |_| return; | ||
| 2633 | |||
| 2597 | const tracy = trace(@src()); | 2634 | const tracy = trace(@src()); |
| 2598 | defer tracy.end(); | 2635 | defer tracy.end(); |
| 2599 | 2636 | ||
| ... | @@ -2667,6 +2704,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec | ... | @@ -2667,6 +2704,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec |
| 2667 | const tracy = trace(@src()); | 2704 | const tracy = trace(@src()); |
| 2668 | defer tracy.end(); | 2705 | defer tracy.end(); |
| 2669 | 2706 | ||
| 2707 | if (self.llvm_ir_module) |_| return; | ||
| 2708 | |||
| 2670 | const container_scope = decl.scope.cast(Module.Scope.Container).?; | 2709 | const container_scope = decl.scope.cast(Module.Scope.Container).?; |
| 2671 | const tree = container_scope.file_scope.contents.tree; | 2710 | const tree = container_scope.file_scope.contents.tree; |
| 2672 | const file_ast_decls = tree.root_node.decls(); | 2711 | const file_ast_decls = tree.root_node.decls(); |
| ... | @@ -2685,6 +2724,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec | ... | @@ -2685,6 +2724,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec |
| 2685 | } | 2724 | } |
| 2686 | 2725 | ||
| 2687 | pub fn deleteExport(self: *Elf, exp: Export) void { | 2726 | pub fn deleteExport(self: *Elf, exp: Export) void { |
| 2727 | if (self.llvm_ir_module) |_| return; | ||
| 2728 | |||
| 2688 | const sym_index = exp.sym_index orelse return; | 2729 | const sym_index = exp.sym_index orelse return; |
| 2689 | self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {}; | 2730 | self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {}; |
| 2690 | self.global_symbols.items[sym_index].st_info = 0; | 2731 | self.global_symbols.items[sym_index].st_info = 0; |
src/llvm.zig deleted-140| ... | @@ -1,140 +0,0 @@ | ||
| 1 | //! We do this instead of @cImport because the self-hosted compiler is easier | ||
| 2 | //! to bootstrap if it does not depend on translate-c. | ||
| 3 | |||
| 4 | extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 5 | extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 6 | extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 7 | extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 8 | |||
| 9 | pub const LinkCOFF = ZigLLDLinkCOFF; | ||
| 10 | pub const LinkELF = ZigLLDLinkELF; | ||
| 11 | pub const LinkMachO = ZigLLDLinkMachO; | ||
| 12 | pub const LinkWasm = ZigLLDLinkWasm; | ||
| 13 | |||
| 14 | pub const ObjectFormatType = extern enum(c_int) { | ||
| 15 | Unknown, | ||
| 16 | COFF, | ||
| 17 | ELF, | ||
| 18 | MachO, | ||
| 19 | Wasm, | ||
| 20 | XCOFF, | ||
| 21 | }; | ||
| 22 | |||
| 23 | pub const GetHostCPUName = LLVMGetHostCPUName; | ||
| 24 | extern fn LLVMGetHostCPUName() ?[*:0]u8; | ||
| 25 | |||
| 26 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | ||
| 27 | extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8; | ||
| 28 | |||
| 29 | pub const WriteArchive = ZigLLVMWriteArchive; | ||
| 30 | extern fn ZigLLVMWriteArchive( | ||
| 31 | archive_name: [*:0]const u8, | ||
| 32 | file_names_ptr: [*]const [*:0]const u8, | ||
| 33 | file_names_len: usize, | ||
| 34 | os_type: OSType, | ||
| 35 | ) bool; | ||
| 36 | |||
| 37 | pub const OSType = extern enum(c_int) { | ||
| 38 | UnknownOS = 0, | ||
| 39 | Ananas = 1, | ||
| 40 | CloudABI = 2, | ||
| 41 | Darwin = 3, | ||
| 42 | DragonFly = 4, | ||
| 43 | FreeBSD = 5, | ||
| 44 | Fuchsia = 6, | ||
| 45 | IOS = 7, | ||
| 46 | KFreeBSD = 8, | ||
| 47 | Linux = 9, | ||
| 48 | Lv2 = 10, | ||
| 49 | MacOSX = 11, | ||
| 50 | NetBSD = 12, | ||
| 51 | OpenBSD = 13, | ||
| 52 | Solaris = 14, | ||
| 53 | Win32 = 15, | ||
| 54 | Haiku = 16, | ||
| 55 | Minix = 17, | ||
| 56 | RTEMS = 18, | ||
| 57 | NaCl = 19, | ||
| 58 | CNK = 20, | ||
| 59 | AIX = 21, | ||
| 60 | CUDA = 22, | ||
| 61 | NVCL = 23, | ||
| 62 | AMDHSA = 24, | ||
| 63 | PS4 = 25, | ||
| 64 | ELFIAMCU = 26, | ||
| 65 | TvOS = 27, | ||
| 66 | WatchOS = 28, | ||
| 67 | Mesa3D = 29, | ||
| 68 | Contiki = 30, | ||
| 69 | AMDPAL = 31, | ||
| 70 | HermitCore = 32, | ||
| 71 | Hurd = 33, | ||
| 72 | WASI = 34, | ||
| 73 | Emscripten = 35, | ||
| 74 | }; | ||
| 75 | |||
| 76 | pub const ArchType = extern enum(c_int) { | ||
| 77 | UnknownArch = 0, | ||
| 78 | arm = 1, | ||
| 79 | armeb = 2, | ||
| 80 | aarch64 = 3, | ||
| 81 | aarch64_be = 4, | ||
| 82 | aarch64_32 = 5, | ||
| 83 | arc = 6, | ||
| 84 | avr = 7, | ||
| 85 | bpfel = 8, | ||
| 86 | bpfeb = 9, | ||
| 87 | hexagon = 10, | ||
| 88 | mips = 11, | ||
| 89 | mipsel = 12, | ||
| 90 | mips64 = 13, | ||
| 91 | mips64el = 14, | ||
| 92 | msp430 = 15, | ||
| 93 | ppc = 16, | ||
| 94 | ppc64 = 17, | ||
| 95 | ppc64le = 18, | ||
| 96 | r600 = 19, | ||
| 97 | amdgcn = 20, | ||
| 98 | riscv32 = 21, | ||
| 99 | riscv64 = 22, | ||
| 100 | sparc = 23, | ||
| 101 | sparcv9 = 24, | ||
| 102 | sparcel = 25, | ||
| 103 | systemz = 26, | ||
| 104 | tce = 27, | ||
| 105 | tcele = 28, | ||
| 106 | thumb = 29, | ||
| 107 | thumbeb = 30, | ||
| 108 | x86 = 31, | ||
| 109 | x86_64 = 32, | ||
| 110 | xcore = 33, | ||
| 111 | nvptx = 34, | ||
| 112 | nvptx64 = 35, | ||
| 113 | le32 = 36, | ||
| 114 | le64 = 37, | ||
| 115 | amdil = 38, | ||
| 116 | amdil64 = 39, | ||
| 117 | hsail = 40, | ||
| 118 | hsail64 = 41, | ||
| 119 | spir = 42, | ||
| 120 | spir64 = 43, | ||
| 121 | kalimba = 44, | ||
| 122 | shave = 45, | ||
| 123 | lanai = 46, | ||
| 124 | wasm32 = 47, | ||
| 125 | wasm64 = 48, | ||
| 126 | renderscript32 = 49, | ||
| 127 | renderscript64 = 50, | ||
| 128 | ve = 51, | ||
| 129 | }; | ||
| 130 | |||
| 131 | pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions; | ||
| 132 | extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void; | ||
| 133 | |||
| 134 | pub const WriteImportLibrary = ZigLLVMWriteImportLibrary; | ||
| 135 | extern fn ZigLLVMWriteImportLibrary( | ||
| 136 | def_path: [*:0]const u8, | ||
| 137 | arch: ArchType, | ||
| 138 | output_lib_path: [*c]const u8, | ||
| 139 | kill_at: bool, | ||
| 140 | ) bool; | ||
src/llvm_backend.zig created+442| ... | @@ -0,0 +1,442 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Allocator = std.mem.Allocator; | ||
| 3 | const Compilation = @import("Compilation.zig"); | ||
| 4 | const llvm = @import("llvm_bindings.zig"); | ||
| 5 | const link = @import("link.zig"); | ||
| 6 | |||
| 7 | const Module = @import("Module.zig"); | ||
| 8 | const TypedValue = @import("TypedValue.zig"); | ||
| 9 | const ir = @import("ir.zig"); | ||
| 10 | const Inst = ir.Inst; | ||
| 11 | |||
| 12 | const Value = @import("value.zig").Value; | ||
| 13 | const Type = @import("type.zig").Type; | ||
| 14 | |||
| 15 | pub fn targetTriple(allocator: *Allocator, target: std.Target) ![:0]u8 { | ||
| 16 | const llvm_arch = switch (target.cpu.arch) { | ||
| 17 | .arm => "arm", | ||
| 18 | .armeb => "armeb", | ||
| 19 | .aarch64 => "aarch64", | ||
| 20 | .aarch64_be => "aarch64_be", | ||
| 21 | .aarch64_32 => "aarch64_32", | ||
| 22 | .arc => "arc", | ||
| 23 | .avr => "avr", | ||
| 24 | .bpfel => "bpfel", | ||
| 25 | .bpfeb => "bpfeb", | ||
| 26 | .hexagon => "hexagon", | ||
| 27 | .mips => "mips", | ||
| 28 | .mipsel => "mipsel", | ||
| 29 | .mips64 => "mips64", | ||
| 30 | .mips64el => "mips64el", | ||
| 31 | .msp430 => "msp430", | ||
| 32 | .powerpc => "powerpc", | ||
| 33 | .powerpc64 => "powerpc64", | ||
| 34 | .powerpc64le => "powerpc64le", | ||
| 35 | .r600 => "r600", | ||
| 36 | .amdgcn => "amdgcn", | ||
| 37 | .riscv32 => "riscv32", | ||
| 38 | .riscv64 => "riscv64", | ||
| 39 | .sparc => "sparc", | ||
| 40 | .sparcv9 => "sparcv9", | ||
| 41 | .sparcel => "sparcel", | ||
| 42 | .s390x => "s390x", | ||
| 43 | .tce => "tce", | ||
| 44 | .tcele => "tcele", | ||
| 45 | .thumb => "thumb", | ||
| 46 | .thumbeb => "thumbeb", | ||
| 47 | .i386 => "i386", | ||
| 48 | .x86_64 => "x86_64", | ||
| 49 | .xcore => "xcore", | ||
| 50 | .nvptx => "nvptx", | ||
| 51 | .nvptx64 => "nvptx64", | ||
| 52 | .le32 => "le32", | ||
| 53 | .le64 => "le64", | ||
| 54 | .amdil => "amdil", | ||
| 55 | .amdil64 => "amdil64", | ||
| 56 | .hsail => "hsail", | ||
| 57 | .hsail64 => "hsail64", | ||
| 58 | .spir => "spir", | ||
| 59 | .spir64 => "spir64", | ||
| 60 | .kalimba => "kalimba", | ||
| 61 | .shave => "shave", | ||
| 62 | .lanai => "lanai", | ||
| 63 | .wasm32 => "wasm32", | ||
| 64 | .wasm64 => "wasm64", | ||
| 65 | .renderscript32 => "renderscript32", | ||
| 66 | .renderscript64 => "renderscript64", | ||
| 67 | .ve => "ve", | ||
| 68 | .spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII, | ||
| 69 | }; | ||
| 70 | // TODO Add a sub-arch for some architectures depending on CPU features. | ||
| 71 | |||
| 72 | const llvm_os = switch (target.os.tag) { | ||
| 73 | .freestanding => "unknown", | ||
| 74 | .ananas => "ananas", | ||
| 75 | .cloudabi => "cloudabi", | ||
| 76 | .dragonfly => "dragonfly", | ||
| 77 | .freebsd => "freebsd", | ||
| 78 | .fuchsia => "fuchsia", | ||
| 79 | .ios => "ios", | ||
| 80 | .kfreebsd => "kfreebsd", | ||
| 81 | .linux => "linux", | ||
| 82 | .lv2 => "lv2", | ||
| 83 | .macos => "macosx", | ||
| 84 | .netbsd => "netbsd", | ||
| 85 | .openbsd => "openbsd", | ||
| 86 | .solaris => "solaris", | ||
| 87 | .windows => "windows", | ||
| 88 | .haiku => "haiku", | ||
| 89 | .minix => "minix", | ||
| 90 | .rtems => "rtems", | ||
| 91 | .nacl => "nacl", | ||
| 92 | .cnk => "cnk", | ||
| 93 | .aix => "aix", | ||
| 94 | .cuda => "cuda", | ||
| 95 | .nvcl => "nvcl", | ||
| 96 | .amdhsa => "amdhsa", | ||
| 97 | .ps4 => "ps4", | ||
| 98 | .elfiamcu => "elfiamcu", | ||
| 99 | .tvos => "tvos", | ||
| 100 | .watchos => "watchos", | ||
| 101 | .mesa3d => "mesa3d", | ||
| 102 | .contiki => "contiki", | ||
| 103 | .amdpal => "amdpal", | ||
| 104 | .hermit => "hermit", | ||
| 105 | .hurd => "hurd", | ||
| 106 | .wasi => "wasi", | ||
| 107 | .emscripten => "emscripten", | ||
| 108 | .uefi => "windows", | ||
| 109 | .other => "unknown", | ||
| 110 | }; | ||
| 111 | |||
| 112 | const llvm_abi = switch (target.abi) { | ||
| 113 | .none => "unknown", | ||
| 114 | .gnu => "gnu", | ||
| 115 | .gnuabin32 => "gnuabin32", | ||
| 116 | .gnuabi64 => "gnuabi64", | ||
| 117 | .gnueabi => "gnueabi", | ||
| 118 | .gnueabihf => "gnueabihf", | ||
| 119 | .gnux32 => "gnux32", | ||
| 120 | .code16 => "code16", | ||
| 121 | .eabi => "eabi", | ||
| 122 | .eabihf => "eabihf", | ||
| 123 | .android => "android", | ||
| 124 | .musl => "musl", | ||
| 125 | .musleabi => "musleabi", | ||
| 126 | .musleabihf => "musleabihf", | ||
| 127 | .msvc => "msvc", | ||
| 128 | .itanium => "itanium", | ||
| 129 | .cygnus => "cygnus", | ||
| 130 | .coreclr => "coreclr", | ||
| 131 | .simulator => "simulator", | ||
| 132 | .macabi => "macabi", | ||
| 133 | }; | ||
| 134 | |||
| 135 | return std.fmt.allocPrintZ(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi }); | ||
| 136 | } | ||
| 137 | |||
| 138 | pub const LLVMIRModule = struct { | ||
| 139 | module: *Module, | ||
| 140 | llvm_module: *const llvm.ModuleRef, | ||
| 141 | target_machine: *const llvm.TargetMachineRef, | ||
| 142 | builder: *const llvm.BuilderRef, | ||
| 143 | |||
| 144 | output_path: []const u8, | ||
| 145 | |||
| 146 | gpa: *Allocator, | ||
| 147 | err_msg: ?*Compilation.ErrorMsg = null, | ||
| 148 | |||
| 149 | pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule { | ||
| 150 | const self = try allocator.create(LLVMIRModule); | ||
| 151 | errdefer allocator.destroy(self); | ||
| 152 | |||
| 153 | const gpa = options.module.?.gpa; | ||
| 154 | |||
| 155 | initializeLLVMTargets(); | ||
| 156 | |||
| 157 | const root_nameZ = try gpa.dupeZ(u8, options.root_name); | ||
| 158 | defer gpa.free(root_nameZ); | ||
| 159 | const llvm_module = llvm.ModuleRef.createWithName(root_nameZ.ptr); | ||
| 160 | errdefer llvm_module.disposeModule(); | ||
| 161 | |||
| 162 | const llvm_target_triple = try targetTriple(gpa, options.target); | ||
| 163 | defer gpa.free(llvm_target_triple); | ||
| 164 | |||
| 165 | var error_message: [*:0]const u8 = undefined; | ||
| 166 | var target_ref: *const llvm.TargetRef = undefined; | ||
| 167 | if (llvm.TargetRef.getTargetFromTriple(llvm_target_triple.ptr, &target_ref, &error_message)) { | ||
| 168 | defer llvm.disposeMessage(error_message); | ||
| 169 | |||
| 170 | const stderr = std.io.getStdErr().outStream(); | ||
| 171 | try stderr.print( | ||
| 172 | \\Zig is expecting LLVM to understand this target: '{s}' | ||
| 173 | \\However LLVM responded with: "{s}" | ||
| 174 | \\Zig is unable to continue. This is a bug in Zig: | ||
| 175 | \\https://github.com/ziglang/zig/issues/438 | ||
| 176 | \\ | ||
| 177 | , | ||
| 178 | .{ | ||
| 179 | llvm_target_triple, | ||
| 180 | error_message, | ||
| 181 | }, | ||
| 182 | ); | ||
| 183 | return error.InvalidLLVMTriple; | ||
| 184 | } | ||
| 185 | |||
| 186 | const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) .None else .Aggressive; | ||
| 187 | const target_machine = llvm.TargetMachineRef.createTargetMachine( | ||
| 188 | target_ref, | ||
| 189 | llvm_target_triple.ptr, | ||
| 190 | "", | ||
| 191 | "", | ||
| 192 | opt_level, | ||
| 193 | .Static, | ||
| 194 | .Default, | ||
| 195 | ); | ||
| 196 | errdefer target_machine.disposeTargetMachine(); | ||
| 197 | |||
| 198 | const builder = llvm.BuilderRef.createBuilder(); | ||
| 199 | errdefer builder.disposeBuilder(); | ||
| 200 | |||
| 201 | self.* = .{ | ||
| 202 | .module = options.module.?, | ||
| 203 | .llvm_module = llvm_module, | ||
| 204 | .target_machine = target_machine, | ||
| 205 | .builder = builder, | ||
| 206 | .output_path = sub_path, | ||
| 207 | .gpa = gpa, | ||
| 208 | }; | ||
| 209 | return self; | ||
| 210 | } | ||
| 211 | |||
| 212 | pub fn deinit(self: *LLVMIRModule, allocator: *Allocator) void { | ||
| 213 | self.builder.disposeBuilder(); | ||
| 214 | self.target_machine.disposeTargetMachine(); | ||
| 215 | self.llvm_module.disposeModule(); | ||
| 216 | allocator.destroy(self); | ||
| 217 | } | ||
| 218 | |||
| 219 | fn initializeLLVMTargets() void { | ||
| 220 | llvm.initializeAllTargets(); | ||
| 221 | llvm.initializeAllTargetInfos(); | ||
| 222 | llvm.initializeAllTargetMCs(); | ||
| 223 | llvm.initializeAllAsmPrinters(); | ||
| 224 | llvm.initializeAllAsmParsers(); | ||
| 225 | } | ||
| 226 | |||
| 227 | pub fn flushModule(self: *LLVMIRModule, comp: *Compilation) !void { | ||
| 228 | if (comp.verbose_llvm_ir) { | ||
| 229 | const dump = self.llvm_module.printToString(); | ||
| 230 | defer llvm.disposeMessage(dump); | ||
| 231 | |||
| 232 | const stderr = std.io.getStdErr().outStream(); | ||
| 233 | try stderr.writeAll(std.mem.spanZ(dump)); | ||
| 234 | } | ||
| 235 | |||
| 236 | { | ||
| 237 | var error_message: [*:0]const u8 = undefined; | ||
| 238 | // verifyModule always allocs the error_message even if there is no error | ||
| 239 | defer llvm.disposeMessage(error_message); | ||
| 240 | |||
| 241 | if (self.llvm_module.verifyModule(.ReturnStatus, &error_message)) { | ||
| 242 | const stderr = std.io.getStdErr().outStream(); | ||
| 243 | try stderr.print("broken LLVM module found: {s}\nThis is a bug in the Zig compiler.", .{error_message}); | ||
| 244 | return error.BrokenLLVMModule; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | const output_pathZ = try self.gpa.dupeZ(u8, self.output_path); | ||
| 249 | defer self.gpa.free(output_pathZ); | ||
| 250 | |||
| 251 | var error_message: [*:0]const u8 = undefined; | ||
| 252 | // TODO: where to put the output object, zig-cache something? | ||
| 253 | // TODO: caching? | ||
| 254 | if (self.target_machine.emitToFile( | ||
| 255 | self.llvm_module, | ||
| 256 | output_pathZ.ptr, | ||
| 257 | .ObjectFile, | ||
| 258 | &error_message, | ||
| 259 | )) { | ||
| 260 | defer llvm.disposeMessage(error_message); | ||
| 261 | |||
| 262 | const stderr = std.io.getStdErr().outStream(); | ||
| 263 | try stderr.print("LLVM failed to emit file: {s}\n", .{error_message}); | ||
| 264 | return error.FailedToEmit; | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | pub fn updateDecl(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void { | ||
| 269 | const typed_value = decl.typed_value.most_recent.typed_value; | ||
| 270 | self.gen(module, typed_value, decl.src()) catch |err| switch (err) { | ||
| 271 | error.CodegenFail => { | ||
| 272 | decl.analysis = .codegen_failure; | ||
| 273 | try module.failed_decls.put(module.gpa, decl, self.err_msg.?); | ||
| 274 | return; | ||
| 275 | }, | ||
| 276 | else => |e| return e, | ||
| 277 | }; | ||
| 278 | } | ||
| 279 | |||
| 280 | fn gen(self: *LLVMIRModule, module: *Module, typed_value: TypedValue, src: usize) !void { | ||
| 281 | switch (typed_value.ty.zigTypeTag()) { | ||
| 282 | .Fn => { | ||
| 283 | const func = typed_value.val.cast(Value.Payload.Function).?.func; | ||
| 284 | |||
| 285 | const llvm_func = try self.resolveLLVMFunction(func); | ||
| 286 | |||
| 287 | // We remove all the basic blocks of a function to support incremental | ||
| 288 | // compilation! | ||
| 289 | // TODO: remove all basic blocks if functions can have more than one | ||
| 290 | if (llvm_func.getFirstBasicBlock()) |bb| { | ||
| 291 | bb.deleteBasicBlock(); | ||
| 292 | } | ||
| 293 | |||
| 294 | const entry_block = llvm_func.appendBasicBlock("Entry"); | ||
| 295 | self.builder.positionBuilderAtEnd(entry_block); | ||
| 296 | |||
| 297 | const instructions = func.analysis.success.instructions; | ||
| 298 | for (instructions) |inst| { | ||
| 299 | switch (inst.tag) { | ||
| 300 | .breakpoint => try self.genBreakpoint(inst.castTag(.breakpoint).?), | ||
| 301 | .call => try self.genCall(inst.castTag(.call).?), | ||
| 302 | .unreach => self.genUnreach(inst.castTag(.unreach).?), | ||
| 303 | .retvoid => self.genRetVoid(inst.castTag(.retvoid).?), | ||
| 304 | .arg => self.genArg(inst.castTag(.arg).?), | ||
| 305 | .dbg_stmt => { | ||
| 306 | // TODO: implement debug info | ||
| 307 | }, | ||
| 308 | else => |tag| return self.fail(src, "TODO implement LLVM codegen for Zir instruction: {}", .{tag}), | ||
| 309 | } | ||
| 310 | } | ||
| 311 | }, | ||
| 312 | else => |ty| return self.fail(src, "TODO implement LLVM codegen for top-level decl type: {}", .{ty}), | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !void { | ||
| 317 | if (inst.func.cast(Inst.Constant)) |func_inst| { | ||
| 318 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | ||
| 319 | const func = func_val.func; | ||
| 320 | const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty; | ||
| 321 | const llvm_fn = try self.resolveLLVMFunction(func); | ||
| 322 | |||
| 323 | const num_args = inst.args.len; | ||
| 324 | |||
| 325 | const llvm_param_vals = try self.gpa.alloc(*const llvm.ValueRef, num_args); | ||
| 326 | defer self.gpa.free(llvm_param_vals); | ||
| 327 | |||
| 328 | for (inst.args) |arg, i| { | ||
| 329 | llvm_param_vals[i] = try self.resolveInst(arg); | ||
| 330 | } | ||
| 331 | |||
| 332 | // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs | ||
| 333 | // Do we need that? | ||
| 334 | const call = self.builder.buildCall( | ||
| 335 | llvm_fn, | ||
| 336 | if (num_args == 0) null else llvm_param_vals.ptr, | ||
| 337 | @intCast(c_uint, num_args), | ||
| 338 | "", | ||
| 339 | ); | ||
| 340 | |||
| 341 | if (zig_fn_type.fnReturnType().zigTypeTag() == .NoReturn) { | ||
| 342 | _ = self.builder.buildUnreachable(); | ||
| 343 | } | ||
| 344 | } | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | fn genRetVoid(self: *LLVMIRModule, inst: *Inst.NoOp) void { | ||
| 349 | _ = self.builder.buildRetVoid(); | ||
| 350 | } | ||
| 351 | |||
| 352 | fn genUnreach(self: *LLVMIRModule, inst: *Inst.NoOp) void { | ||
| 353 | _ = self.builder.buildUnreachable(); | ||
| 354 | } | ||
| 355 | |||
| 356 | fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) void { | ||
| 357 | // TODO: implement this | ||
| 358 | } | ||
| 359 | |||
| 360 | fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !void { | ||
| 361 | // TODO: Store this function somewhere such that we dont have to add it again | ||
| 362 | const fn_type = llvm.TypeRef.functionType(llvm.voidType(), null, 0, false); | ||
| 363 | const func = self.llvm_module.addFunction("llvm.debugtrap", fn_type); | ||
| 364 | // TODO: add assertion: LLVMGetIntrinsicID | ||
| 365 | _ = self.builder.buildCall(func, null, 0, ""); | ||
| 366 | } | ||
| 367 | |||
| 368 | fn resolveInst(self: *LLVMIRModule, inst: *ir.Inst) !*const llvm.ValueRef { | ||
| 369 | if (inst.castTag(.constant)) |const_inst| { | ||
| 370 | return self.genTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val }); | ||
| 371 | } | ||
| 372 | return self.fail(inst.src, "TODO implement resolveInst", .{}); | ||
| 373 | } | ||
| 374 | |||
| 375 | fn genTypedValue(self: *LLVMIRModule, src: usize, typed_value: TypedValue) !*const llvm.ValueRef { | ||
| 376 | const llvm_type = self.getLLVMType(typed_value.ty); | ||
| 377 | |||
| 378 | if (typed_value.val.isUndef()) | ||
| 379 | return llvm_type.getUndef(); | ||
| 380 | |||
| 381 | switch (typed_value.ty.zigTypeTag()) { | ||
| 382 | .Bool => return if (typed_value.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(), | ||
| 383 | else => return self.fail(src, "TODO implement const of type '{}'", .{typed_value.ty}), | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | /// If the llvm function does not exist, create it | ||
| 388 | fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Fn) !*const llvm.ValueRef { | ||
| 389 | // TODO: do we want to store this in our own datastructure? | ||
| 390 | if (self.llvm_module.getNamedFunction(func.owner_decl.name)) |llvm_fn| return llvm_fn; | ||
| 391 | |||
| 392 | const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty; | ||
| 393 | const return_type = zig_fn_type.fnReturnType(); | ||
| 394 | |||
| 395 | const fn_param_len = zig_fn_type.fnParamLen(); | ||
| 396 | |||
| 397 | const fn_param_types = try self.gpa.alloc(Type, fn_param_len); | ||
| 398 | defer self.gpa.free(fn_param_types); | ||
| 399 | zig_fn_type.fnParamTypes(fn_param_types); | ||
| 400 | |||
| 401 | const llvm_param = try self.gpa.alloc(*const llvm.TypeRef, fn_param_len); | ||
| 402 | defer self.gpa.free(llvm_param); | ||
| 403 | |||
| 404 | for (fn_param_types) |fn_param, i| { | ||
| 405 | llvm_param[i] = self.getLLVMType(fn_param); | ||
| 406 | } | ||
| 407 | |||
| 408 | const fn_type = llvm.TypeRef.functionType( | ||
| 409 | self.getLLVMType(return_type), | ||
| 410 | if (fn_param_len == 0) null else llvm_param.ptr, | ||
| 411 | @intCast(c_uint, fn_param_len), | ||
| 412 | false, | ||
| 413 | ); | ||
| 414 | const llvm_fn = self.llvm_module.addFunction(func.owner_decl.name, fn_type); | ||
| 415 | |||
| 416 | if (return_type.zigTypeTag() == .NoReturn) { | ||
| 417 | llvm_fn.addFnAttr("noreturn"); | ||
| 418 | } | ||
| 419 | |||
| 420 | return llvm_fn; | ||
| 421 | } | ||
| 422 | |||
| 423 | fn getLLVMType(self: *LLVMIRModule, t: Type) *const llvm.TypeRef { | ||
| 424 | switch (t.zigTypeTag()) { | ||
| 425 | .Void => return llvm.voidType(), | ||
| 426 | .NoReturn => return llvm.voidType(), | ||
| 427 | .Int => { | ||
| 428 | const info = t.intInfo(self.module.getTarget()); | ||
| 429 | return llvm.intType(info.bits); | ||
| 430 | }, | ||
| 431 | .Bool => return llvm.intType(1), | ||
| 432 | else => unreachable, | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { | ||
| 437 | @setCold(true); | ||
| 438 | std.debug.assert(self.err_msg == null); | ||
| 439 | self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args); | ||
| 440 | return error.CodegenFail; | ||
| 441 | } | ||
| 442 | }; | ||
src/llvm_bindings.zig created+507| ... | @@ -0,0 +1,507 @@ | ||
| 1 | //! We do this instead of @cImport because the self-hosted compiler is easier | ||
| 2 | //! to bootstrap if it does not depend on translate-c. | ||
| 3 | |||
| 4 | const std = @import("std"); | ||
| 5 | const assert = std.debug.assert; | ||
| 6 | |||
| 7 | const LLVMBool = bool; | ||
| 8 | pub const LLVMAttributeIndex = c_uint; | ||
| 9 | |||
| 10 | pub const ValueRef = opaque { | ||
| 11 | pub const addAttributeAtIndex = LLVMAddAttributeAtIndex; | ||
| 12 | extern fn LLVMAddAttributeAtIndex(*const ValueRef, Idx: LLVMAttributeIndex, A: *const AttributeRef) void; | ||
| 13 | |||
| 14 | pub const appendBasicBlock = LLVMAppendBasicBlock; | ||
| 15 | extern fn LLVMAppendBasicBlock(Fn: *const ValueRef, Name: [*:0]const u8) *const BasicBlockRef; | ||
| 16 | |||
| 17 | pub const getFirstBasicBlock = LLVMGetFirstBasicBlock; | ||
| 18 | extern fn LLVMGetFirstBasicBlock(Fn: *const ValueRef) ?*const BasicBlockRef; | ||
| 19 | |||
| 20 | // Helper functions | ||
| 21 | // TODO: Do we want to put these functions here? It allows for convienient function calls | ||
| 22 | // on ValueRef: llvm_fn.addFnAttr("noreturn") | ||
| 23 | fn addAttr(val: *const ValueRef, index: LLVMAttributeIndex, name: []const u8) void { | ||
| 24 | const kind_id = getEnumAttributeKindForName(name.ptr, name.len); | ||
| 25 | assert(kind_id != 0); | ||
| 26 | const llvm_attr = ContextRef.getGlobal().createEnumAttribute(kind_id, 0); | ||
| 27 | val.addAttributeAtIndex(index, llvm_attr); | ||
| 28 | } | ||
| 29 | |||
| 30 | pub fn addFnAttr(val: *const ValueRef, attr_name: []const u8) void { | ||
| 31 | // TODO: improve this API, `addAttr(-1, attr_name)` | ||
| 32 | val.addAttr(std.math.maxInt(LLVMAttributeIndex), attr_name); | ||
| 33 | } | ||
| 34 | }; | ||
| 35 | |||
| 36 | pub const TypeRef = opaque { | ||
| 37 | pub const functionType = LLVMFunctionType; | ||
| 38 | extern fn LLVMFunctionType(ReturnType: *const TypeRef, ParamTypes: ?[*]*const TypeRef, ParamCount: c_uint, IsVarArg: LLVMBool) *const TypeRef; | ||
| 39 | |||
| 40 | pub const constNull = LLVMConstNull; | ||
| 41 | extern fn LLVMConstNull(Ty: *const TypeRef) *const ValueRef; | ||
| 42 | |||
| 43 | pub const constAllOnes = LLVMConstAllOnes; | ||
| 44 | extern fn LLVMConstAllOnes(Ty: *const TypeRef) *const ValueRef; | ||
| 45 | |||
| 46 | pub const getUndef = LLVMGetUndef; | ||
| 47 | extern fn LLVMGetUndef(Ty: *const TypeRef) *const ValueRef; | ||
| 48 | }; | ||
| 49 | |||
| 50 | pub const ModuleRef = opaque { | ||
| 51 | pub const createWithName = LLVMModuleCreateWithName; | ||
| 52 | extern fn LLVMModuleCreateWithName(ModuleID: [*:0]const u8) *const ModuleRef; | ||
| 53 | |||
| 54 | pub const disposeModule = LLVMDisposeModule; | ||
| 55 | extern fn LLVMDisposeModule(*const ModuleRef) void; | ||
| 56 | |||
| 57 | pub const verifyModule = LLVMVerifyModule; | ||
| 58 | extern fn LLVMVerifyModule(*const ModuleRef, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) LLVMBool; | ||
| 59 | |||
| 60 | pub const addFunction = LLVMAddFunction; | ||
| 61 | extern fn LLVMAddFunction(*const ModuleRef, Name: [*:0]const u8, FunctionTy: *const TypeRef) *const ValueRef; | ||
| 62 | |||
| 63 | pub const getNamedFunction = LLVMGetNamedFunction; | ||
| 64 | extern fn LLVMGetNamedFunction(*const ModuleRef, Name: [*:0]const u8) ?*const ValueRef; | ||
| 65 | |||
| 66 | pub const printToString = LLVMPrintModuleToString; | ||
| 67 | extern fn LLVMPrintModuleToString(*const ModuleRef) [*:0]const u8; | ||
| 68 | }; | ||
| 69 | |||
| 70 | pub const disposeMessage = LLVMDisposeMessage; | ||
| 71 | extern fn LLVMDisposeMessage(Message: [*:0]const u8) void; | ||
| 72 | |||
| 73 | pub const VerifierFailureAction = extern enum { | ||
| 74 | AbortProcess, | ||
| 75 | PrintMessage, | ||
| 76 | ReturnStatus, | ||
| 77 | }; | ||
| 78 | |||
| 79 | pub const voidType = LLVMVoidType; | ||
| 80 | extern fn LLVMVoidType() *const TypeRef; | ||
| 81 | |||
| 82 | pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName; | ||
| 83 | extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint; | ||
| 84 | |||
| 85 | pub const AttributeRef = opaque {}; | ||
| 86 | |||
| 87 | pub const ContextRef = opaque { | ||
| 88 | pub const createEnumAttribute = LLVMCreateEnumAttribute; | ||
| 89 | extern fn LLVMCreateEnumAttribute(*const ContextRef, KindID: c_uint, Val: u64) *const AttributeRef; | ||
| 90 | |||
| 91 | pub const getGlobal = LLVMGetGlobalContext; | ||
| 92 | extern fn LLVMGetGlobalContext() *const ContextRef; | ||
| 93 | }; | ||
| 94 | |||
| 95 | pub const intType = LLVMIntType; | ||
| 96 | extern fn LLVMIntType(NumBits: c_uint) *const TypeRef; | ||
| 97 | |||
| 98 | pub const BuilderRef = opaque { | ||
| 99 | pub const createBuilder = LLVMCreateBuilder; | ||
| 100 | extern fn LLVMCreateBuilder() *const BuilderRef; | ||
| 101 | |||
| 102 | pub const disposeBuilder = LLVMDisposeBuilder; | ||
| 103 | extern fn LLVMDisposeBuilder(Builder: *const BuilderRef) void; | ||
| 104 | |||
| 105 | pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd; | ||
| 106 | extern fn LLVMPositionBuilderAtEnd(Builder: *const BuilderRef, Block: *const BasicBlockRef) void; | ||
| 107 | |||
| 108 | pub const getInsertBlock = LLVMGetInsertBlock; | ||
| 109 | extern fn LLVMGetInsertBlock(Builder: *const BuilderRef) *const BasicBlockRef; | ||
| 110 | |||
| 111 | pub const buildCall = LLVMBuildCall; | ||
| 112 | extern fn LLVMBuildCall(*const BuilderRef, Fn: *const ValueRef, Args: ?[*]*const ValueRef, NumArgs: c_uint, Name: [*:0]const u8) *const ValueRef; | ||
| 113 | |||
| 114 | pub const buildCall2 = LLVMBuildCall2; | ||
| 115 | extern fn LLVMBuildCall2(*const BuilderRef, *const TypeRef, Fn: *const ValueRef, Args: [*]*const ValueRef, NumArgs: c_uint, Name: [*:0]const u8) *const ValueRef; | ||
| 116 | |||
| 117 | pub const buildRetVoid = LLVMBuildRetVoid; | ||
| 118 | extern fn LLVMBuildRetVoid(*const BuilderRef) *const ValueRef; | ||
| 119 | |||
| 120 | pub const buildUnreachable = LLVMBuildUnreachable; | ||
| 121 | extern fn LLVMBuildUnreachable(*const BuilderRef) *const ValueRef; | ||
| 122 | |||
| 123 | pub const buildAlloca = LLVMBuildAlloca; | ||
| 124 | extern fn LLVMBuildAlloca(*const BuilderRef, Ty: *const TypeRef, Name: [*:0]const u8) *const ValueRef; | ||
| 125 | }; | ||
| 126 | |||
| 127 | pub const BasicBlockRef = opaque { | ||
| 128 | pub const deleteBasicBlock = LLVMDeleteBasicBlock; | ||
| 129 | extern fn LLVMDeleteBasicBlock(BB: *const BasicBlockRef) void; | ||
| 130 | }; | ||
| 131 | |||
| 132 | pub const TargetMachineRef = opaque { | ||
| 133 | pub const createTargetMachine = LLVMCreateTargetMachine; | ||
| 134 | extern fn LLVMCreateTargetMachine( | ||
| 135 | T: *const TargetRef, | ||
| 136 | Triple: [*:0]const u8, | ||
| 137 | CPU: [*:0]const u8, | ||
| 138 | Features: [*:0]const u8, | ||
| 139 | Level: CodeGenOptLevel, | ||
| 140 | Reloc: RelocMode, | ||
| 141 | CodeModel: CodeMode, | ||
| 142 | ) *const TargetMachineRef; | ||
| 143 | |||
| 144 | pub const disposeTargetMachine = LLVMDisposeTargetMachine; | ||
| 145 | extern fn LLVMDisposeTargetMachine(T: *const TargetMachineRef) void; | ||
| 146 | |||
| 147 | pub const emitToFile = LLVMTargetMachineEmitToFile; | ||
| 148 | extern fn LLVMTargetMachineEmitToFile(*const TargetMachineRef, M: *const ModuleRef, Filename: [*:0]const u8, codegen: CodeGenFileType, ErrorMessage: *[*:0]const u8) LLVMBool; | ||
| 149 | }; | ||
| 150 | |||
| 151 | pub const CodeMode = extern enum { | ||
| 152 | Default, | ||
| 153 | JITDefault, | ||
| 154 | Tiny, | ||
| 155 | Small, | ||
| 156 | Kernel, | ||
| 157 | Medium, | ||
| 158 | Large, | ||
| 159 | }; | ||
| 160 | |||
| 161 | pub const CodeGenOptLevel = extern enum { | ||
| 162 | None, | ||
| 163 | Less, | ||
| 164 | Default, | ||
| 165 | Aggressive, | ||
| 166 | }; | ||
| 167 | |||
| 168 | pub const RelocMode = extern enum { | ||
| 169 | Default, | ||
| 170 | Static, | ||
| 171 | PIC, | ||
| 172 | DynamicNoPic, | ||
| 173 | ROPI, | ||
| 174 | RWPI, | ||
| 175 | ROPI_RWPI, | ||
| 176 | }; | ||
| 177 | |||
| 178 | pub const CodeGenFileType = extern enum { | ||
| 179 | AssemblyFile, | ||
| 180 | ObjectFile, | ||
| 181 | }; | ||
| 182 | |||
| 183 | pub const TargetRef = opaque { | ||
| 184 | pub const getTargetFromTriple = LLVMGetTargetFromTriple; | ||
| 185 | extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const TargetRef, ErrorMessage: *[*:0]const u8) LLVMBool; | ||
| 186 | }; | ||
| 187 | |||
| 188 | extern fn LLVMInitializeAArch64TargetInfo() void; | ||
| 189 | extern fn LLVMInitializeAMDGPUTargetInfo() void; | ||
| 190 | extern fn LLVMInitializeARMTargetInfo() void; | ||
| 191 | extern fn LLVMInitializeAVRTargetInfo() void; | ||
| 192 | extern fn LLVMInitializeBPFTargetInfo() void; | ||
| 193 | extern fn LLVMInitializeHexagonTargetInfo() void; | ||
| 194 | extern fn LLVMInitializeLanaiTargetInfo() void; | ||
| 195 | extern fn LLVMInitializeMipsTargetInfo() void; | ||
| 196 | extern fn LLVMInitializeMSP430TargetInfo() void; | ||
| 197 | extern fn LLVMInitializeNVPTXTargetInfo() void; | ||
| 198 | extern fn LLVMInitializePowerPCTargetInfo() void; | ||
| 199 | extern fn LLVMInitializeRISCVTargetInfo() void; | ||
| 200 | extern fn LLVMInitializeSparcTargetInfo() void; | ||
| 201 | extern fn LLVMInitializeSystemZTargetInfo() void; | ||
| 202 | extern fn LLVMInitializeWebAssemblyTargetInfo() void; | ||
| 203 | extern fn LLVMInitializeX86TargetInfo() void; | ||
| 204 | extern fn LLVMInitializeXCoreTargetInfo() void; | ||
| 205 | extern fn LLVMInitializeAArch64Target() void; | ||
| 206 | extern fn LLVMInitializeAMDGPUTarget() void; | ||
| 207 | extern fn LLVMInitializeARMTarget() void; | ||
| 208 | extern fn LLVMInitializeAVRTarget() void; | ||
| 209 | extern fn LLVMInitializeBPFTarget() void; | ||
| 210 | extern fn LLVMInitializeHexagonTarget() void; | ||
| 211 | extern fn LLVMInitializeLanaiTarget() void; | ||
| 212 | extern fn LLVMInitializeMipsTarget() void; | ||
| 213 | extern fn LLVMInitializeMSP430Target() void; | ||
| 214 | extern fn LLVMInitializeNVPTXTarget() void; | ||
| 215 | extern fn LLVMInitializePowerPCTarget() void; | ||
| 216 | extern fn LLVMInitializeRISCVTarget() void; | ||
| 217 | extern fn LLVMInitializeSparcTarget() void; | ||
| 218 | extern fn LLVMInitializeSystemZTarget() void; | ||
| 219 | extern fn LLVMInitializeWebAssemblyTarget() void; | ||
| 220 | extern fn LLVMInitializeX86Target() void; | ||
| 221 | extern fn LLVMInitializeXCoreTarget() void; | ||
| 222 | extern fn LLVMInitializeAArch64TargetMC() void; | ||
| 223 | extern fn LLVMInitializeAMDGPUTargetMC() void; | ||
| 224 | extern fn LLVMInitializeARMTargetMC() void; | ||
| 225 | extern fn LLVMInitializeAVRTargetMC() void; | ||
| 226 | extern fn LLVMInitializeBPFTargetMC() void; | ||
| 227 | extern fn LLVMInitializeHexagonTargetMC() void; | ||
| 228 | extern fn LLVMInitializeLanaiTargetMC() void; | ||
| 229 | extern fn LLVMInitializeMipsTargetMC() void; | ||
| 230 | extern fn LLVMInitializeMSP430TargetMC() void; | ||
| 231 | extern fn LLVMInitializeNVPTXTargetMC() void; | ||
| 232 | extern fn LLVMInitializePowerPCTargetMC() void; | ||
| 233 | extern fn LLVMInitializeRISCVTargetMC() void; | ||
| 234 | extern fn LLVMInitializeSparcTargetMC() void; | ||
| 235 | extern fn LLVMInitializeSystemZTargetMC() void; | ||
| 236 | extern fn LLVMInitializeWebAssemblyTargetMC() void; | ||
| 237 | extern fn LLVMInitializeX86TargetMC() void; | ||
| 238 | extern fn LLVMInitializeXCoreTargetMC() void; | ||
| 239 | extern fn LLVMInitializeAArch64AsmPrinter() void; | ||
| 240 | extern fn LLVMInitializeAMDGPUAsmPrinter() void; | ||
| 241 | extern fn LLVMInitializeARMAsmPrinter() void; | ||
| 242 | extern fn LLVMInitializeAVRAsmPrinter() void; | ||
| 243 | extern fn LLVMInitializeBPFAsmPrinter() void; | ||
| 244 | extern fn LLVMInitializeHexagonAsmPrinter() void; | ||
| 245 | extern fn LLVMInitializeLanaiAsmPrinter() void; | ||
| 246 | extern fn LLVMInitializeMipsAsmPrinter() void; | ||
| 247 | extern fn LLVMInitializeMSP430AsmPrinter() void; | ||
| 248 | extern fn LLVMInitializeNVPTXAsmPrinter() void; | ||
| 249 | extern fn LLVMInitializePowerPCAsmPrinter() void; | ||
| 250 | extern fn LLVMInitializeRISCVAsmPrinter() void; | ||
| 251 | extern fn LLVMInitializeSparcAsmPrinter() void; | ||
| 252 | extern fn LLVMInitializeSystemZAsmPrinter() void; | ||
| 253 | extern fn LLVMInitializeWebAssemblyAsmPrinter() void; | ||
| 254 | extern fn LLVMInitializeX86AsmPrinter() void; | ||
| 255 | extern fn LLVMInitializeXCoreAsmPrinter() void; | ||
| 256 | extern fn LLVMInitializeAArch64AsmParser() void; | ||
| 257 | extern fn LLVMInitializeAMDGPUAsmParser() void; | ||
| 258 | extern fn LLVMInitializeARMAsmParser() void; | ||
| 259 | extern fn LLVMInitializeAVRAsmParser() void; | ||
| 260 | extern fn LLVMInitializeBPFAsmParser() void; | ||
| 261 | extern fn LLVMInitializeHexagonAsmParser() void; | ||
| 262 | extern fn LLVMInitializeLanaiAsmParser() void; | ||
| 263 | extern fn LLVMInitializeMipsAsmParser() void; | ||
| 264 | extern fn LLVMInitializeMSP430AsmParser() void; | ||
| 265 | extern fn LLVMInitializePowerPCAsmParser() void; | ||
| 266 | extern fn LLVMInitializeRISCVAsmParser() void; | ||
| 267 | extern fn LLVMInitializeSparcAsmParser() void; | ||
| 268 | extern fn LLVMInitializeSystemZAsmParser() void; | ||
| 269 | extern fn LLVMInitializeWebAssemblyAsmParser() void; | ||
| 270 | extern fn LLVMInitializeX86AsmParser() void; | ||
| 271 | |||
| 272 | pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos; | ||
| 273 | fn LLVMInitializeAllTargetInfos() callconv(.C) void { | ||
| 274 | LLVMInitializeAArch64TargetInfo(); | ||
| 275 | LLVMInitializeAMDGPUTargetInfo(); | ||
| 276 | LLVMInitializeARMTargetInfo(); | ||
| 277 | LLVMInitializeAVRTargetInfo(); | ||
| 278 | LLVMInitializeBPFTargetInfo(); | ||
| 279 | LLVMInitializeHexagonTargetInfo(); | ||
| 280 | LLVMInitializeLanaiTargetInfo(); | ||
| 281 | LLVMInitializeMipsTargetInfo(); | ||
| 282 | LLVMInitializeMSP430TargetInfo(); | ||
| 283 | LLVMInitializeNVPTXTargetInfo(); | ||
| 284 | LLVMInitializePowerPCTargetInfo(); | ||
| 285 | LLVMInitializeRISCVTargetInfo(); | ||
| 286 | LLVMInitializeSparcTargetInfo(); | ||
| 287 | LLVMInitializeSystemZTargetInfo(); | ||
| 288 | LLVMInitializeWebAssemblyTargetInfo(); | ||
| 289 | LLVMInitializeX86TargetInfo(); | ||
| 290 | LLVMInitializeXCoreTargetInfo(); | ||
| 291 | } | ||
| 292 | pub const initializeAllTargets = LLVMInitializeAllTargets; | ||
| 293 | fn LLVMInitializeAllTargets() callconv(.C) void { | ||
| 294 | LLVMInitializeAArch64Target(); | ||
| 295 | LLVMInitializeAMDGPUTarget(); | ||
| 296 | LLVMInitializeARMTarget(); | ||
| 297 | LLVMInitializeAVRTarget(); | ||
| 298 | LLVMInitializeBPFTarget(); | ||
| 299 | LLVMInitializeHexagonTarget(); | ||
| 300 | LLVMInitializeLanaiTarget(); | ||
| 301 | LLVMInitializeMipsTarget(); | ||
| 302 | LLVMInitializeMSP430Target(); | ||
| 303 | LLVMInitializeNVPTXTarget(); | ||
| 304 | LLVMInitializePowerPCTarget(); | ||
| 305 | LLVMInitializeRISCVTarget(); | ||
| 306 | LLVMInitializeSparcTarget(); | ||
| 307 | LLVMInitializeSystemZTarget(); | ||
| 308 | LLVMInitializeWebAssemblyTarget(); | ||
| 309 | LLVMInitializeX86Target(); | ||
| 310 | LLVMInitializeXCoreTarget(); | ||
| 311 | } | ||
| 312 | pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs; | ||
| 313 | fn LLVMInitializeAllTargetMCs() callconv(.C) void { | ||
| 314 | LLVMInitializeAArch64TargetMC(); | ||
| 315 | LLVMInitializeAMDGPUTargetMC(); | ||
| 316 | LLVMInitializeARMTargetMC(); | ||
| 317 | LLVMInitializeAVRTargetMC(); | ||
| 318 | LLVMInitializeBPFTargetMC(); | ||
| 319 | LLVMInitializeHexagonTargetMC(); | ||
| 320 | LLVMInitializeLanaiTargetMC(); | ||
| 321 | LLVMInitializeMipsTargetMC(); | ||
| 322 | LLVMInitializeMSP430TargetMC(); | ||
| 323 | LLVMInitializeNVPTXTargetMC(); | ||
| 324 | LLVMInitializePowerPCTargetMC(); | ||
| 325 | LLVMInitializeRISCVTargetMC(); | ||
| 326 | LLVMInitializeSparcTargetMC(); | ||
| 327 | LLVMInitializeSystemZTargetMC(); | ||
| 328 | LLVMInitializeWebAssemblyTargetMC(); | ||
| 329 | LLVMInitializeX86TargetMC(); | ||
| 330 | LLVMInitializeXCoreTargetMC(); | ||
| 331 | } | ||
| 332 | pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters; | ||
| 333 | fn LLVMInitializeAllAsmPrinters() callconv(.C) void { | ||
| 334 | LLVMInitializeAArch64AsmPrinter(); | ||
| 335 | LLVMInitializeAMDGPUAsmPrinter(); | ||
| 336 | LLVMInitializeARMAsmPrinter(); | ||
| 337 | LLVMInitializeAVRAsmPrinter(); | ||
| 338 | LLVMInitializeBPFAsmPrinter(); | ||
| 339 | LLVMInitializeHexagonAsmPrinter(); | ||
| 340 | LLVMInitializeLanaiAsmPrinter(); | ||
| 341 | LLVMInitializeMipsAsmPrinter(); | ||
| 342 | LLVMInitializeMSP430AsmPrinter(); | ||
| 343 | LLVMInitializeNVPTXAsmPrinter(); | ||
| 344 | LLVMInitializePowerPCAsmPrinter(); | ||
| 345 | LLVMInitializeRISCVAsmPrinter(); | ||
| 346 | LLVMInitializeSparcAsmPrinter(); | ||
| 347 | LLVMInitializeSystemZAsmPrinter(); | ||
| 348 | LLVMInitializeWebAssemblyAsmPrinter(); | ||
| 349 | LLVMInitializeX86AsmPrinter(); | ||
| 350 | LLVMInitializeXCoreAsmPrinter(); | ||
| 351 | } | ||
| 352 | pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers; | ||
| 353 | fn LLVMInitializeAllAsmParsers() callconv(.C) void { | ||
| 354 | LLVMInitializeAArch64AsmParser(); | ||
| 355 | LLVMInitializeAMDGPUAsmParser(); | ||
| 356 | LLVMInitializeARMAsmParser(); | ||
| 357 | LLVMInitializeAVRAsmParser(); | ||
| 358 | LLVMInitializeBPFAsmParser(); | ||
| 359 | LLVMInitializeHexagonAsmParser(); | ||
| 360 | LLVMInitializeLanaiAsmParser(); | ||
| 361 | LLVMInitializeMipsAsmParser(); | ||
| 362 | LLVMInitializeMSP430AsmParser(); | ||
| 363 | LLVMInitializePowerPCAsmParser(); | ||
| 364 | LLVMInitializeRISCVAsmParser(); | ||
| 365 | LLVMInitializeSparcAsmParser(); | ||
| 366 | LLVMInitializeSystemZAsmParser(); | ||
| 367 | LLVMInitializeWebAssemblyAsmParser(); | ||
| 368 | LLVMInitializeX86AsmParser(); | ||
| 369 | } | ||
| 370 | |||
| 371 | extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 372 | extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 373 | extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 374 | extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | ||
| 375 | |||
| 376 | pub const LinkCOFF = ZigLLDLinkCOFF; | ||
| 377 | pub const LinkELF = ZigLLDLinkELF; | ||
| 378 | pub const LinkMachO = ZigLLDLinkMachO; | ||
| 379 | pub const LinkWasm = ZigLLDLinkWasm; | ||
| 380 | |||
| 381 | pub const ObjectFormatType = extern enum(c_int) { | ||
| 382 | Unknown, | ||
| 383 | COFF, | ||
| 384 | ELF, | ||
| 385 | MachO, | ||
| 386 | Wasm, | ||
| 387 | XCOFF, | ||
| 388 | }; | ||
| 389 | |||
| 390 | pub const GetHostCPUName = LLVMGetHostCPUName; | ||
| 391 | extern fn LLVMGetHostCPUName() ?[*:0]u8; | ||
| 392 | |||
| 393 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | ||
| 394 | extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8; | ||
| 395 | |||
| 396 | pub const WriteArchive = ZigLLVMWriteArchive; | ||
| 397 | extern fn ZigLLVMWriteArchive( | ||
| 398 | archive_name: [*:0]const u8, | ||
| 399 | file_names_ptr: [*]const [*:0]const u8, | ||
| 400 | file_names_len: usize, | ||
| 401 | os_type: OSType, | ||
| 402 | ) bool; | ||
| 403 | |||
| 404 | pub const OSType = extern enum(c_int) { | ||
| 405 | UnknownOS = 0, | ||
| 406 | Ananas = 1, | ||
| 407 | CloudABI = 2, | ||
| 408 | Darwin = 3, | ||
| 409 | DragonFly = 4, | ||
| 410 | FreeBSD = 5, | ||
| 411 | Fuchsia = 6, | ||
| 412 | IOS = 7, | ||
| 413 | KFreeBSD = 8, | ||
| 414 | Linux = 9, | ||
| 415 | Lv2 = 10, | ||
| 416 | MacOSX = 11, | ||
| 417 | NetBSD = 12, | ||
| 418 | OpenBSD = 13, | ||
| 419 | Solaris = 14, | ||
| 420 | Win32 = 15, | ||
| 421 | Haiku = 16, | ||
| 422 | Minix = 17, | ||
| 423 | RTEMS = 18, | ||
| 424 | NaCl = 19, | ||
| 425 | CNK = 20, | ||
| 426 | AIX = 21, | ||
| 427 | CUDA = 22, | ||
| 428 | NVCL = 23, | ||
| 429 | AMDHSA = 24, | ||
| 430 | PS4 = 25, | ||
| 431 | ELFIAMCU = 26, | ||
| 432 | TvOS = 27, | ||
| 433 | WatchOS = 28, | ||
| 434 | Mesa3D = 29, | ||
| 435 | Contiki = 30, | ||
| 436 | AMDPAL = 31, | ||
| 437 | HermitCore = 32, | ||
| 438 | Hurd = 33, | ||
| 439 | WASI = 34, | ||
| 440 | Emscripten = 35, | ||
| 441 | }; | ||
| 442 | |||
| 443 | pub const ArchType = extern enum(c_int) { | ||
| 444 | UnknownArch = 0, | ||
| 445 | arm = 1, | ||
| 446 | armeb = 2, | ||
| 447 | aarch64 = 3, | ||
| 448 | aarch64_be = 4, | ||
| 449 | aarch64_32 = 5, | ||
| 450 | arc = 6, | ||
| 451 | avr = 7, | ||
| 452 | bpfel = 8, | ||
| 453 | bpfeb = 9, | ||
| 454 | hexagon = 10, | ||
| 455 | mips = 11, | ||
| 456 | mipsel = 12, | ||
| 457 | mips64 = 13, | ||
| 458 | mips64el = 14, | ||
| 459 | msp430 = 15, | ||
| 460 | ppc = 16, | ||
| 461 | ppc64 = 17, | ||
| 462 | ppc64le = 18, | ||
| 463 | r600 = 19, | ||
| 464 | amdgcn = 20, | ||
| 465 | riscv32 = 21, | ||
| 466 | riscv64 = 22, | ||
| 467 | sparc = 23, | ||
| 468 | sparcv9 = 24, | ||
| 469 | sparcel = 25, | ||
| 470 | systemz = 26, | ||
| 471 | tce = 27, | ||
| 472 | tcele = 28, | ||
| 473 | thumb = 29, | ||
| 474 | thumbeb = 30, | ||
| 475 | x86 = 31, | ||
| 476 | x86_64 = 32, | ||
| 477 | xcore = 33, | ||
| 478 | nvptx = 34, | ||
| 479 | nvptx64 = 35, | ||
| 480 | le32 = 36, | ||
| 481 | le64 = 37, | ||
| 482 | amdil = 38, | ||
| 483 | amdil64 = 39, | ||
| 484 | hsail = 40, | ||
| 485 | hsail64 = 41, | ||
| 486 | spir = 42, | ||
| 487 | spir64 = 43, | ||
| 488 | kalimba = 44, | ||
| 489 | shave = 45, | ||
| 490 | lanai = 46, | ||
| 491 | wasm32 = 47, | ||
| 492 | wasm64 = 48, | ||
| 493 | renderscript32 = 49, | ||
| 494 | renderscript64 = 50, | ||
| 495 | ve = 51, | ||
| 496 | }; | ||
| 497 | |||
| 498 | pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions; | ||
| 499 | extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void; | ||
| 500 | |||
| 501 | pub const WriteImportLibrary = ZigLLVMWriteImportLibrary; | ||
| 502 | extern fn ZigLLVMWriteImportLibrary( | ||
| 503 | def_path: [*:0]const u8, | ||
| 504 | arch: ArchType, | ||
| 505 | output_lib_path: [*c]const u8, | ||
| 506 | kill_at: bool, | ||
| 507 | ) bool; | ||
src/main.zig+3-3| ... | @@ -1676,7 +1676,7 @@ fn buildOutputType( | ... | @@ -1676,7 +1676,7 @@ fn buildOutputType( |
| 1676 | if (build_options.have_llvm and emit_asm != .no) { | 1676 | if (build_options.have_llvm and emit_asm != .no) { |
| 1677 | // LLVM has no way to set this non-globally. | 1677 | // LLVM has no way to set this non-globally. |
| 1678 | const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" }; | 1678 | const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" }; |
| 1679 | @import("llvm.zig").ParseCommandLineOptions(argv.len, &argv); | 1679 | @import("llvm_bindings.zig").ParseCommandLineOptions(argv.len, &argv); |
| 1680 | } | 1680 | } |
| 1681 | 1681 | ||
| 1682 | gimmeMoreOfThoseSweetSweetFileDescriptors(); | 1682 | gimmeMoreOfThoseSweetSweetFileDescriptors(); |
| ... | @@ -2839,7 +2839,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor | ... | @@ -2839,7 +2839,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor |
| 2839 | argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation. | 2839 | argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation. |
| 2840 | } | 2840 | } |
| 2841 | const exit_code = rc: { | 2841 | const exit_code = rc: { |
| 2842 | const llvm = @import("llvm.zig"); | 2842 | const llvm = @import("llvm_bindings.zig"); |
| 2843 | const argc = @intCast(c_int, argv.len); | 2843 | const argc = @intCast(c_int, argv.len); |
| 2844 | if (mem.eql(u8, args[1], "ld.lld")) { | 2844 | if (mem.eql(u8, args[1], "ld.lld")) { |
| 2845 | break :rc llvm.LinkELF(argc, argv.ptr, true); | 2845 | break :rc llvm.LinkELF(argc, argv.ptr, true); |
| ... | @@ -3224,7 +3224,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s | ... | @@ -3224,7 +3224,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s |
| 3224 | if (!build_options.have_llvm) | 3224 | if (!build_options.have_llvm) |
| 3225 | fatal("CPU features detection is not yet available for {} without LLVM extensions", .{@tagName(arch)}); | 3225 | fatal("CPU features detection is not yet available for {} without LLVM extensions", .{@tagName(arch)}); |
| 3226 | 3226 | ||
| 3227 | const llvm = @import("llvm.zig"); | 3227 | const llvm = @import("llvm_bindings.zig"); |
| 3228 | const llvm_cpu_name = llvm.GetHostCPUName(); | 3228 | const llvm_cpu_name = llvm.GetHostCPUName(); |
| 3229 | const llvm_cpu_features = llvm.GetNativeFeatures(); | 3229 | const llvm_cpu_features = llvm.GetNativeFeatures(); |
| 3230 | info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); | 3230 | info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); |
src/mingw.zig+1-1| ... | @@ -405,7 +405,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { | ... | @@ -405,7 +405,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 405 | }); | 405 | }); |
| 406 | errdefer comp.gpa.free(lib_final_path); | 406 | errdefer comp.gpa.free(lib_final_path); |
| 407 | 407 | ||
| 408 | const llvm = @import("llvm.zig"); | 408 | const llvm = @import("llvm_bindings.zig"); |
| 409 | const arch_type = @import("target.zig").archToLLVM(target.cpu.arch); | 409 | const arch_type = @import("target.zig").archToLLVM(target.cpu.arch); |
| 410 | const def_final_path_z = try arena.dupeZ(u8, def_final_path); | 410 | const def_final_path_z = try arena.dupeZ(u8, def_final_path); |
| 411 | const lib_final_path_z = try arena.dupeZ(u8, lib_final_path); | 411 | const lib_final_path_z = try arena.dupeZ(u8, lib_final_path); |
src/target.zig+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const llvm = @import("llvm.zig"); | 2 | const llvm = @import("llvm_bindings.zig"); |
| 3 | 3 | ||
| 4 | pub const ArchOsAbi = struct { | 4 | pub const ArchOsAbi = struct { |
| 5 | arch: std.Target.Cpu.Arch, | 5 | arch: std.Target.Cpu.Arch, |
src/zig_clang.h+19-1| ... | @@ -8,14 +8,32 @@ | ... | @@ -8,14 +8,32 @@ |
| 8 | #ifndef ZIG_ZIG_CLANG_H | 8 | #ifndef ZIG_ZIG_CLANG_H |
| 9 | #define ZIG_ZIG_CLANG_H | 9 | #define ZIG_ZIG_CLANG_H |
| 10 | 10 | ||
| 11 | #include "stage1/stage2.h" | ||
| 12 | #include <inttypes.h> | 11 | #include <inttypes.h> |
| 13 | #include <stdbool.h> | 12 | #include <stdbool.h> |
| 13 | #include <stddef.h> | ||
| 14 | |||
| 15 | #ifdef __cplusplus | ||
| 16 | #define ZIG_EXTERN_C extern "C" | ||
| 17 | #else | ||
| 18 | #define ZIG_EXTERN_C | ||
| 19 | #endif | ||
| 14 | 20 | ||
| 15 | // ATTENTION: If you modify this file, be sure to update the corresponding | 21 | // ATTENTION: If you modify this file, be sure to update the corresponding |
| 16 | // extern function declarations in the self-hosted compiler file | 22 | // extern function declarations in the self-hosted compiler file |
| 17 | // src/clang.zig. | 23 | // src/clang.zig. |
| 18 | 24 | ||
| 25 | // ABI warning | ||
| 26 | struct Stage2ErrorMsg { | ||
| 27 | const char *filename_ptr; // can be null | ||
| 28 | size_t filename_len; | ||
| 29 | const char *msg_ptr; | ||
| 30 | size_t msg_len; | ||
| 31 | const char *source; // valid until the ASTUnit is freed. can be null | ||
| 32 | unsigned line; // 0 based | ||
| 33 | unsigned column; // 0 based | ||
| 34 | unsigned offset; // byte offset into source | ||
| 35 | }; | ||
| 36 | |||
| 19 | struct ZigClangSourceLocation { | 37 | struct ZigClangSourceLocation { |
| 20 | unsigned ID; | 38 | unsigned ID; |
| 21 | }; | 39 | }; |