| 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 | 527 | "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig" |
| 528 | 528 | "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig" |
| 529 | 529 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" |
| 530 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" | |
| 531 | 530 | "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig" |
| 532 | 531 | "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig" |
| 533 | 532 | "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig" |
| ... | ... | @@ -549,7 +548,8 @@ set(ZIG_STAGE2_SOURCES |
| 549 | 548 | "${CMAKE_SOURCE_DIR}/src/link/cbe.h" |
| 550 | 549 | "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin" |
| 551 | 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 | 553 | "${CMAKE_SOURCE_DIR}/src/main.zig" |
| 554 | 554 | "${CMAKE_SOURCE_DIR}/src/mingw.zig" |
| 555 | 555 | "${CMAKE_SOURCE_DIR}/src/musl.zig" |
build.zig+20-13| ... | ... | @@ -91,6 +91,20 @@ pub fn build(b: *Builder) !void { |
| 91 | 91 | exe.addBuildOption(bool, "have_llvm", enable_llvm); |
| 92 | 92 | if (enable_llvm) { |
| 93 | 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 | 108 | if (is_stage1) { |
| 95 | 109 | exe.addIncludeDir("src"); |
| 96 | 110 | exe.addIncludeDir("deps/SoftFloat-3e/source/include"); |
| ... | ... | @@ -109,19 +123,6 @@ pub fn build(b: *Builder) !void { |
| 109 | 123 | softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" }); |
| 110 | 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 | 126 | exe.addCSourceFiles(&stage1_sources, &exe_cflags); |
| 126 | 127 | exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" }); |
| 127 | 128 | if (cmake_cfg == null) { |
| ... | ... | @@ -205,6 +206,12 @@ pub fn build(b: *Builder) !void { |
| 205 | 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 | 215 | // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries. |
| 209 | 216 | exe.linkSystemLibrary("c++"); |
| 210 | 217 |
src/Compilation.zig+1-1| ... | ... | @@ -2106,7 +2106,7 @@ pub fn addCCArgs( |
| 2106 | 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 | 2110 | try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); |
| 2111 | 2111 | |
| 2112 | 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 | 567 | std.debug.print("\n", .{}); |
| 568 | 568 | } |
| 569 | 569 | |
| 570 | const llvm = @import("llvm.zig"); | |
| 570 | const llvm = @import("llvm_bindings.zig"); | |
| 571 | 571 | const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag); |
| 572 | 572 | const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type); |
| 573 | 573 | if (bad) return error.UnableToWriteArchive; |
src/link/Coff.zig+29-3| ... | ... | @@ -16,6 +16,7 @@ const link = @import("../link.zig"); |
| 16 | 16 | const build_options = @import("build_options"); |
| 17 | 17 | const Cache = @import("../Cache.zig"); |
| 18 | 18 | const mingw = @import("../mingw.zig"); |
| 19 | const llvm_backend = @import("../llvm_backend.zig"); | |
| 19 | 20 | |
| 20 | 21 | const allocation_padding = 4 / 3; |
| 21 | 22 | const minimum_text_block_size = 64 * allocation_padding; |
| ... | ... | @@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff; |
| 32 | 33 | |
| 33 | 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 | 39 | base: link.File, |
| 36 | 40 | ptr_width: PtrWidth, |
| 37 | 41 | error_flags: link.File.ErrorFlags = .{}, |
| ... | ... | @@ -121,8 +125,13 @@ pub const SrcFn = void; |
| 121 | 125 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff { |
| 122 | 126 | assert(options.object_format == .coff); |
| 123 | 127 | |
| 124 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO | |
| 125 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO | |
| 128 | if (build_options.have_llvm and options.use_llvm) { | |
| 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 | 136 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 128 | 137 | .truncate = false, |
| ... | ... | @@ -404,6 +413,8 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff { |
| 404 | 413 | } |
| 405 | 414 | |
| 406 | 415 | pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void { |
| 416 | if (self.llvm_ir_module) |_| return; | |
| 417 | ||
| 407 | 418 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); |
| 408 | 419 | |
| 409 | 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 | 659 | const tracy = trace(@src()); |
| 649 | 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 | 665 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 652 | 666 | defer code_buffer.deinit(); |
| 653 | 667 | |
| ... | ... | @@ -698,12 +712,16 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 698 | 712 | } |
| 699 | 713 | |
| 700 | 714 | pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { |
| 715 | if (self.llvm_ir_module) |_| return; | |
| 716 | ||
| 701 | 717 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 702 | 718 | self.freeTextBlock(&decl.link.coff); |
| 703 | 719 | self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {}; |
| 704 | 720 | } |
| 705 | 721 | |
| 706 | 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 | 725 | for (exports) |exp| { |
| 708 | 726 | if (exp.options.section) |section_name| { |
| 709 | 727 | if (!mem.eql(u8, section_name, ".text")) { |
| ... | ... | @@ -744,6 +762,9 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { |
| 744 | 762 | const tracy = trace(@src()); |
| 745 | 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 | 768 | if (self.text_section_size_dirty) { |
| 748 | 769 | // Write the new raw size in the .text header |
| 749 | 770 | var buf: [4]u8 = undefined; |
| ... | ... | @@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 1124 | 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 | 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 | 1151 | if (!self.base.options.link_libc) { |
| 1130 | 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 | 1249 | } |
| 1228 | 1250 | |
| 1229 | 1251 | pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 { |
| 1252 | assert(self.llvm_ir_module == null); | |
| 1230 | 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 | 1258 | } |
| 1236 | 1259 | |
| 1237 | 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 | 1264 | self.text_block_free_list.deinit(self.base.allocator); |
| 1239 | 1265 | self.offset_table.deinit(self.base.allocator); |
| 1240 | 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 | 24 | const target_util = @import("../target.zig"); |
| 25 | 25 | const glibc = @import("../glibc.zig"); |
| 26 | 26 | const Cache = @import("../Cache.zig"); |
| 27 | const llvm_backend = @import("../llvm_backend.zig"); | |
| 27 | 28 | |
| 28 | 29 | const default_entry_addr = 0x8000000; |
| 29 | 30 | |
| ... | ... | @@ -33,6 +34,9 @@ base: File, |
| 33 | 34 | |
| 34 | 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 | 40 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 37 | 41 | /// Same order as in the file. |
| 38 | 42 | sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){}, |
| ... | ... | @@ -224,7 +228,13 @@ pub const SrcFn = struct { |
| 224 | 228 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Elf { |
| 225 | 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 | 239 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 230 | 240 | .truncate = false, |
| ... | ... | @@ -288,6 +298,10 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf { |
| 288 | 298 | } |
| 289 | 299 | |
| 290 | 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 | 305 | self.sections.deinit(self.base.allocator); |
| 292 | 306 | self.program_headers.deinit(self.base.allocator); |
| 293 | 307 | self.shstrtab.deinit(self.base.allocator); |
| ... | ... | @@ -304,6 +318,7 @@ pub fn deinit(self: *Elf) void { |
| 304 | 318 | } |
| 305 | 319 | |
| 306 | 320 | pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 { |
| 321 | assert(self.llvm_ir_module == null); | |
| 307 | 322 | assert(decl.link.elf.local_sym_index != 0); |
| 308 | 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 | 438 | } |
| 424 | 439 | |
| 425 | 440 | pub fn populateMissingMetadata(self: *Elf) !void { |
| 441 | assert(self.llvm_ir_module == null); | |
| 442 | ||
| 426 | 443 | const small_ptr = switch (self.ptr_width) { |
| 427 | 444 | .p32 => true, |
| 428 | 445 | .p64 => false, |
| ... | ... | @@ -727,6 +744,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 727 | 744 | const tracy = trace(@src()); |
| 728 | 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 | 750 | // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the |
| 731 | 751 | // Zig source code. |
| 732 | 752 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| ... | ... | @@ -1261,6 +1281,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1261 | 1281 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| 1262 | 1282 | const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; |
| 1263 | 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 | 1287 | if (is_exe_or_dyn_lib) { |
| 1265 | 1288 | break :blk comp.compiler_rt_static_lib.?.full_object_path; |
| 1266 | 1289 | } else { |
| ... | ... | @@ -1552,7 +1575,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1552 | 1575 | } |
| 1553 | 1576 | |
| 1554 | 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 | 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 | 2074 | } |
| 2047 | 2075 | |
| 2048 | 2076 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2077 | if (self.llvm_ir_module) |_| return; | |
| 2078 | ||
| 2049 | 2079 | if (decl.link.elf.local_sym_index != 0) return; |
| 2050 | 2080 | |
| 2051 | 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 | 2112 | } |
| 2083 | 2113 | |
| 2084 | 2114 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 2115 | if (self.llvm_ir_module) |_| return; | |
| 2116 | ||
| 2085 | 2117 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 2086 | 2118 | self.freeTextBlock(&decl.link.elf); |
| 2087 | 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 | 2151 | const tracy = trace(@src()); |
| 2120 | 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 | 2157 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2123 | 2158 | defer code_buffer.deinit(); |
| 2124 | 2159 | |
| ... | ... | @@ -2594,6 +2629,8 @@ pub fn updateDeclExports( |
| 2594 | 2629 | decl: *const Module.Decl, |
| 2595 | 2630 | exports: []const *Module.Export, |
| 2596 | 2631 | ) !void { |
| 2632 | if (self.llvm_ir_module) |_| return; | |
| 2633 | ||
| 2597 | 2634 | const tracy = trace(@src()); |
| 2598 | 2635 | defer tracy.end(); |
| 2599 | 2636 | |
| ... | ... | @@ -2667,6 +2704,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec |
| 2667 | 2704 | const tracy = trace(@src()); |
| 2668 | 2705 | defer tracy.end(); |
| 2669 | 2706 | |
| 2707 | if (self.llvm_ir_module) |_| return; | |
| 2708 | ||
| 2670 | 2709 | const container_scope = decl.scope.cast(Module.Scope.Container).?; |
| 2671 | 2710 | const tree = container_scope.file_scope.contents.tree; |
| 2672 | 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 | 2724 | } |
| 2686 | 2725 | |
| 2687 | 2726 | pub fn deleteExport(self: *Elf, exp: Export) void { |
| 2727 | if (self.llvm_ir_module) |_| return; | |
| 2728 | ||
| 2688 | 2729 | const sym_index = exp.sym_index orelse return; |
| 2689 | 2730 | self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {}; |
| 2690 | 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 | 1676 | if (build_options.have_llvm and emit_asm != .no) { |
| 1677 | 1677 | // LLVM has no way to set this non-globally. |
| 1678 | 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 | 1682 | gimmeMoreOfThoseSweetSweetFileDescriptors(); |
| ... | ... | @@ -2839,7 +2839,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor |
| 2839 | 2839 | argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation. |
| 2840 | 2840 | } |
| 2841 | 2841 | const exit_code = rc: { |
| 2842 | const llvm = @import("llvm.zig"); | |
| 2842 | const llvm = @import("llvm_bindings.zig"); | |
| 2843 | 2843 | const argc = @intCast(c_int, argv.len); |
| 2844 | 2844 | if (mem.eql(u8, args[1], "ld.lld")) { |
| 2845 | 2845 | break :rc llvm.LinkELF(argc, argv.ptr, true); |
| ... | ... | @@ -3224,7 +3224,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s |
| 3224 | 3224 | if (!build_options.have_llvm) |
| 3225 | 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 | 3228 | const llvm_cpu_name = llvm.GetHostCPUName(); |
| 3229 | 3229 | const llvm_cpu_features = llvm.GetNativeFeatures(); |
| 3230 | 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 | 405 | }); |
| 406 | 406 | errdefer comp.gpa.free(lib_final_path); |
| 407 | 407 | |
| 408 | const llvm = @import("llvm.zig"); | |
| 408 | const llvm = @import("llvm_bindings.zig"); | |
| 409 | 409 | const arch_type = @import("target.zig").archToLLVM(target.cpu.arch); |
| 410 | 410 | const def_final_path_z = try arena.dupeZ(u8, def_final_path); |
| 411 | 411 | const lib_final_path_z = try arena.dupeZ(u8, lib_final_path); |
src/target.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const llvm = @import("llvm.zig"); | |
| 2 | const llvm = @import("llvm_bindings.zig"); | |
| 3 | 3 | |
| 4 | 4 | pub const ArchOsAbi = struct { |
| 5 | 5 | arch: std.Target.Cpu.Arch, |
src/zig_clang.h+19-1| ... | ... | @@ -8,14 +8,32 @@ |
| 8 | 8 | #ifndef ZIG_ZIG_CLANG_H |
| 9 | 9 | #define ZIG_ZIG_CLANG_H |
| 10 | 10 | |
| 11 | #include "stage1/stage2.h" | |
| 12 | 11 | #include <inttypes.h> |
| 13 | 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 | 21 | // ATTENTION: If you modify this file, be sure to update the corresponding |
| 16 | 22 | // extern function declarations in the self-hosted compiler file |
| 17 | 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 | 37 | struct ZigClangSourceLocation { |
| 20 | 38 | unsigned ID; |
| 21 | 39 | }; |