| author | |
| committer | |
| log | 071417161d5d7ab91c32073693590ef161017dbe |
| tree | 891bfd9fecd90b9b341d95dfb78399788f62c3ed |
| parent | 4a0d64300bd9ab1a8c35c634856396e3413200f1 |
6 files changed, 813 insertions(+), 129 deletions(-)
CMakeLists.txt+1-1| ... | @@ -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,6 +548,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -549,6 +548,7 @@ 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" |
| 551 | "${CMAKE_SOURCE_DIR}/src/llvm_backend.zig" | ||
| 552 | "${CMAKE_SOURCE_DIR}/src/llvm_bindings.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" |
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/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 (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,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf { | ... | @@ -288,6 +298,7 @@ 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 (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator); | ||
| 291 | self.sections.deinit(self.base.allocator); | 302 | self.sections.deinit(self.base.allocator); |
| 292 | self.program_headers.deinit(self.base.allocator); | 303 | self.program_headers.deinit(self.base.allocator); |
| 293 | self.shstrtab.deinit(self.base.allocator); | 304 | self.shstrtab.deinit(self.base.allocator); |
| ... | @@ -423,6 +434,8 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { | ... | @@ -423,6 +434,8 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { |
| 423 | } | 434 | } |
| 424 | 435 | ||
| 425 | pub fn populateMissingMetadata(self: *Elf) !void { | 436 | pub fn populateMissingMetadata(self: *Elf) !void { |
| 437 | if (self.llvm_ir_module) |_| return; | ||
| 438 | |||
| 426 | const small_ptr = switch (self.ptr_width) { | 439 | const small_ptr = switch (self.ptr_width) { |
| 427 | .p32 => true, | 440 | .p32 => true, |
| 428 | .p64 => false, | 441 | .p64 => false, |
| ... | @@ -727,6 +740,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { | ... | @@ -727,6 +740,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 727 | const tracy = trace(@src()); | 740 | const tracy = trace(@src()); |
| 728 | defer tracy.end(); | 741 | defer tracy.end(); |
| 729 | 742 | ||
| 743 | if (self.llvm_ir_module) |llvm_ir_module| { | ||
| 744 | try llvm_ir_module.flushModule(comp); | ||
| 745 | return; | ||
| 746 | } | ||
| 747 | |||
| 730 | // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the | 748 | // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the |
| 731 | // Zig source code. | 749 | // Zig source code. |
| 732 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 750 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| ... | @@ -1261,6 +1279,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1261,6 +1279,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1261 | const stack_size = self.base.options.stack_size_override orelse 16777216; | 1279 | 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; | 1280 | 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: { | 1281 | const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: { |
| 1282 | // TODO: remove when stage2 can build compiler_rt.zig | ||
| 1283 | if (!build_options.is_stage1) break :blk null; | ||
| 1284 | |||
| 1264 | if (is_exe_or_dyn_lib) { | 1285 | if (is_exe_or_dyn_lib) { |
| 1265 | break :blk comp.compiler_rt_static_lib.?.full_object_path; | 1286 | break :blk comp.compiler_rt_static_lib.?.full_object_path; |
| 1266 | } else { | 1287 | } else { |
| ... | @@ -1552,7 +1573,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1552,7 +1573,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1552 | } | 1573 | } |
| 1553 | 1574 | ||
| 1554 | // libc | 1575 | // libc |
| 1555 | if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and !self.base.options.link_libc) { | 1576 | // TODO: enable when stage2 can build c.zig |
| 1577 | if (is_exe_or_dyn_lib and | ||
| 1578 | !self.base.options.skip_linker_dependencies and | ||
| 1579 | !self.base.options.link_libc and | ||
| 1580 | build_options.is_stage1) | ||
| 1581 | { | ||
| 1556 | try argv.append(comp.libc_static_lib.?.full_object_path); | 1582 | try argv.append(comp.libc_static_lib.?.full_object_path); |
| 1557 | } | 1583 | } |
| 1558 | 1584 | ||
| ... | @@ -2046,6 +2072,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al | ... | @@ -2046,6 +2072,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2046 | } | 2072 | } |
| 2047 | 2073 | ||
| 2048 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | 2074 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2075 | if (self.llvm_ir_module) |_| return; | ||
| 2076 | |||
| 2049 | if (decl.link.elf.local_sym_index != 0) return; | 2077 | if (decl.link.elf.local_sym_index != 0) return; |
| 2050 | 2078 | ||
| 2051 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); | 2079 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); |
| ... | @@ -2082,6 +2110,8 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | ... | @@ -2082,6 +2110,8 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 2082 | } | 2110 | } |
| 2083 | 2111 | ||
| 2084 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | 2112 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 2113 | if (self.llvm_ir_module) |_| return; | ||
| 2114 | |||
| 2085 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 2115 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 2086 | self.freeTextBlock(&decl.link.elf); | 2116 | self.freeTextBlock(&decl.link.elf); |
| 2087 | if (decl.link.elf.local_sym_index != 0) { | 2117 | if (decl.link.elf.local_sym_index != 0) { |
| ... | @@ -2119,6 +2149,11 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | ... | @@ -2119,6 +2149,11 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2119 | const tracy = trace(@src()); | 2149 | const tracy = trace(@src()); |
| 2120 | defer tracy.end(); | 2150 | defer tracy.end(); |
| 2121 | 2151 | ||
| 2152 | if (self.llvm_ir_module) |llvm_ir_module| { | ||
| 2153 | try llvm_ir_module.updateDecl(module, decl); | ||
| 2154 | return; | ||
| 2155 | } | ||
| 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_backend.zig created+410| ... | @@ -0,0 +1,410 @@ | ||
| 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 | llvm_module: *const llvm.ModuleRef, | ||
| 140 | target_machine: *const llvm.TargetMachineRef, | ||
| 141 | output_path: []const u8, | ||
| 142 | |||
| 143 | gpa: *Allocator, | ||
| 144 | err_msg: ?*Compilation.ErrorMsg = null, | ||
| 145 | |||
| 146 | pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule { | ||
| 147 | const self = try allocator.create(LLVMIRModule); | ||
| 148 | errdefer allocator.destroy(self); | ||
| 149 | |||
| 150 | const gpa = options.module.?.gpa; | ||
| 151 | |||
| 152 | initializeLLVMTargets(); | ||
| 153 | |||
| 154 | const root_nameZ = try gpa.dupeZ(u8, options.root_name); | ||
| 155 | defer gpa.free(root_nameZ); | ||
| 156 | const llvm_module = llvm.ModuleRef.createWithName(root_nameZ.ptr); | ||
| 157 | errdefer llvm_module.disposeModule(); | ||
| 158 | |||
| 159 | const llvm_target_triple = try targetTriple(gpa, options.target); | ||
| 160 | defer gpa.free(llvm_target_triple); | ||
| 161 | |||
| 162 | var error_message: [*:0]const u8 = undefined; | ||
| 163 | var target_ref: *const llvm.TargetRef = undefined; | ||
| 164 | if (llvm.TargetRef.getTargetFromTriple(llvm_target_triple.ptr, &target_ref, &error_message)) { | ||
| 165 | defer llvm.disposeMessage(error_message); | ||
| 166 | |||
| 167 | const stderr = std.io.getStdErr().outStream(); | ||
| 168 | try stderr.print( | ||
| 169 | \\Zig is expecting LLVM to understand this target: '{s}' | ||
| 170 | \\However LLVM responded with: "{s}" | ||
| 171 | \\Zig is unable to continue. This is a bug in Zig: | ||
| 172 | \\https://github.com/ziglang/zig/issues/438 | ||
| 173 | \\ | ||
| 174 | , | ||
| 175 | .{ | ||
| 176 | llvm_target_triple, | ||
| 177 | error_message, | ||
| 178 | }, | ||
| 179 | ); | ||
| 180 | return error.InvalidLLVMTriple; | ||
| 181 | } | ||
| 182 | |||
| 183 | const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) .None else .Aggressive; | ||
| 184 | const target_machine = llvm.TargetMachineRef.createTargetMachine( | ||
| 185 | target_ref, | ||
| 186 | llvm_target_triple.ptr, | ||
| 187 | "", | ||
| 188 | "", | ||
| 189 | opt_level, | ||
| 190 | .Static, | ||
| 191 | .Default, | ||
| 192 | ); | ||
| 193 | errdefer target_machine.disposeTargetMachine(); | ||
| 194 | |||
| 195 | self.* = .{ | ||
| 196 | .llvm_module = llvm_module, | ||
| 197 | .target_machine = target_machine, | ||
| 198 | .output_path = sub_path, | ||
| 199 | .gpa = gpa, | ||
| 200 | }; | ||
| 201 | return self; | ||
| 202 | } | ||
| 203 | |||
| 204 | pub fn deinit(self: *LLVMIRModule, allocator: *Allocator) void { | ||
| 205 | self.llvm_module.disposeModule(); | ||
| 206 | self.target_machine.disposeTargetMachine(); | ||
| 207 | allocator.destroy(self); | ||
| 208 | } | ||
| 209 | |||
| 210 | fn initializeLLVMTargets() void { | ||
| 211 | llvm.initializeAllTargets(); | ||
| 212 | llvm.initializeAllTargetInfos(); | ||
| 213 | llvm.initializeAllTargetMCs(); | ||
| 214 | llvm.initializeAllAsmPrinters(); | ||
| 215 | llvm.initializeAllAsmParsers(); | ||
| 216 | } | ||
| 217 | |||
| 218 | pub fn flushModule(self: *LLVMIRModule, comp: *Compilation) !void { | ||
| 219 | { | ||
| 220 | var error_message: [*:0]const u8 = undefined; | ||
| 221 | // verifyModule always allocs the error_message even if there is no error | ||
| 222 | defer llvm.disposeMessage(error_message); | ||
| 223 | |||
| 224 | if (self.llvm_module.verifyModule(.ReturnStatus, &error_message)) { | ||
| 225 | const stderr = std.io.getStdErr().outStream(); | ||
| 226 | try stderr.print("broken LLVM module found: {s}\nThis is a bug in the Zig compiler.", .{error_message}); | ||
| 227 | return error.BrokenLLVMModule; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | if (comp.verbose_llvm_ir) { | ||
| 232 | const dump = self.llvm_module.printToString(); | ||
| 233 | defer llvm.disposeMessage(dump); | ||
| 234 | |||
| 235 | const stderr = std.io.getStdErr().outStream(); | ||
| 236 | try stderr.writeAll(std.mem.spanZ(dump)); | ||
| 237 | } | ||
| 238 | |||
| 239 | const output_pathZ = try self.gpa.dupeZ(u8, self.output_path); | ||
| 240 | defer self.gpa.free(output_pathZ); | ||
| 241 | |||
| 242 | var error_message: [*:0]const u8 = undefined; | ||
| 243 | // TODO: where to put the output object, zig-cache something? | ||
| 244 | // TODO: caching? | ||
| 245 | if (self.target_machine.emitToFile( | ||
| 246 | self.llvm_module, | ||
| 247 | output_pathZ.ptr, | ||
| 248 | .ObjectFile, | ||
| 249 | &error_message, | ||
| 250 | )) { | ||
| 251 | defer llvm.disposeMessage(error_message); | ||
| 252 | |||
| 253 | const stderr = std.io.getStdErr().outStream(); | ||
| 254 | try stderr.print("LLVM failed to emit file: {s}\n", .{error_message}); | ||
| 255 | return error.FailedToEmit; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | pub fn updateDecl(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void { | ||
| 260 | const typed_value = decl.typed_value.most_recent.typed_value; | ||
| 261 | self.generate(module, typed_value, decl.src()) catch |err| switch (err) { | ||
| 262 | error.CodegenFail => { | ||
| 263 | decl.analysis = .codegen_failure; | ||
| 264 | try module.failed_decls.put(module.gpa, decl, self.err_msg.?); | ||
| 265 | return; | ||
| 266 | }, | ||
| 267 | else => |e| return e, | ||
| 268 | }; | ||
| 269 | } | ||
| 270 | |||
| 271 | fn generate(self: *LLVMIRModule, module: *Module, typed_value: TypedValue, src: usize) !void { | ||
| 272 | switch (typed_value.ty.zigTypeTag()) { | ||
| 273 | .Fn => { | ||
| 274 | const func = typed_value.val.cast(Value.Payload.Function).?.func; | ||
| 275 | |||
| 276 | var codegen = CodeGen{ | ||
| 277 | .module = module, | ||
| 278 | .llvm_module = self.llvm_module, | ||
| 279 | .builder = llvm.BuilderRef.createBuilder(), | ||
| 280 | }; | ||
| 281 | defer codegen.builder.disposeBuilder(); | ||
| 282 | |||
| 283 | const llvm_func = try codegen.resolveLLVMFunction(func); | ||
| 284 | |||
| 285 | // We remove all the basic blocks of a function to support incremental | ||
| 286 | // compilation! | ||
| 287 | // TODO: remove all basic blocks if functions can have more than one | ||
| 288 | if (llvm_func.getFirstBasicBlock()) |bb| { | ||
| 289 | bb.deleteBasicBlock(); | ||
| 290 | } | ||
| 291 | |||
| 292 | const entry_block = llvm_func.appendBasicBlock("Entry"); | ||
| 293 | codegen.builder.positionBuilderAtEnd(entry_block); | ||
| 294 | |||
| 295 | const instructions = func.analysis.success.instructions; | ||
| 296 | for (instructions) |inst| { | ||
| 297 | switch (inst.tag) { | ||
| 298 | .breakpoint => try codegen.generateBreakpoint(inst.castTag(.breakpoint).?), | ||
| 299 | .call => try codegen.generateCall(inst.castTag(.call).?), | ||
| 300 | .unreach => codegen.generateUnreach(inst.castTag(.unreach).?), | ||
| 301 | .retvoid => codegen.generateRetVoid(inst.castTag(.retvoid).?), | ||
| 302 | .dbg_stmt => { | ||
| 303 | // TODO: implement debug info | ||
| 304 | }, | ||
| 305 | else => |tag| return self.fail(src, "TODO implement LLVM codegen for Zir instruction: {}", .{tag}), | ||
| 306 | } | ||
| 307 | } | ||
| 308 | }, | ||
| 309 | else => |ty| return self.fail(src, "TODO implement LLVM codegen for top-level decl type: {}", .{ty}), | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { | ||
| 314 | @setCold(true); | ||
| 315 | std.debug.assert(self.err_msg == null); | ||
| 316 | self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args); | ||
| 317 | return error.CodegenFail; | ||
| 318 | } | ||
| 319 | }; | ||
| 320 | |||
| 321 | const CodeGen = struct { | ||
| 322 | module: *Module, | ||
| 323 | llvm_module: *const llvm.ModuleRef, | ||
| 324 | builder: *const llvm.BuilderRef, | ||
| 325 | |||
| 326 | fn generateCall(codegen: *CodeGen, inst: *Inst.Call) !void { | ||
| 327 | if (inst.func.cast(Inst.Constant)) |func_inst| { | ||
| 328 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | ||
| 329 | const func = func_val.func; | ||
| 330 | const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty; | ||
| 331 | const llvm_fn = try codegen.resolveLLVMFunction(func); | ||
| 332 | |||
| 333 | // TODO: handle more arguments, inst.args | ||
| 334 | |||
| 335 | // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs | ||
| 336 | // Do we need that? | ||
| 337 | const call = codegen.builder.buildCall(llvm_fn, null, 0, ""); | ||
| 338 | |||
| 339 | if (zig_fn_type.fnReturnType().zigTypeTag() == .NoReturn) { | ||
| 340 | _ = codegen.builder.buildUnreachable(); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | fn generateRetVoid(codegen: *CodeGen, inst: *Inst.NoOp) void { | ||
| 347 | _ = codegen.builder.buildRetVoid(); | ||
| 348 | } | ||
| 349 | |||
| 350 | fn generateUnreach(codegen: *CodeGen, inst: *Inst.NoOp) void { | ||
| 351 | _ = codegen.builder.buildUnreachable(); | ||
| 352 | } | ||
| 353 | |||
| 354 | fn generateBreakpoint(codegen: *CodeGen, inst: *Inst.NoOp) !void { | ||
| 355 | // TODO: Store this function somewhere such that we dont have to add it again | ||
| 356 | const fn_type = llvm.TypeRef.functionType(llvm.voidType(), null, 0, false); | ||
| 357 | const func = codegen.llvm_module.addFunction("llvm.debugtrap", fn_type); | ||
| 358 | // TODO: add assertion: LLVMGetIntrinsicID | ||
| 359 | _ = codegen.builder.buildCall(func, null, 0, ""); | ||
| 360 | } | ||
| 361 | |||
| 362 | /// If the llvm function does not exist, create it | ||
| 363 | fn resolveLLVMFunction(codegen: *CodeGen, func: *Module.Fn) !*const llvm.ValueRef { | ||
| 364 | // TODO: do we want to store this in our own datastructure? | ||
| 365 | if (codegen.llvm_module.getNamedFunction(func.owner_decl.name)) |llvm_fn| return llvm_fn; | ||
| 366 | |||
| 367 | const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty; | ||
| 368 | const return_type = zig_fn_type.fnReturnType(); | ||
| 369 | |||
| 370 | const fn_param_len = zig_fn_type.fnParamLen(); | ||
| 371 | |||
| 372 | const fn_param_types = try codegen.module.gpa.alloc(Type, fn_param_len); | ||
| 373 | defer codegen.module.gpa.free(fn_param_types); | ||
| 374 | zig_fn_type.fnParamTypes(fn_param_types); | ||
| 375 | |||
| 376 | const llvm_param = try codegen.module.gpa.alloc(*const llvm.TypeRef, fn_param_len); | ||
| 377 | defer codegen.module.gpa.free(llvm_param); | ||
| 378 | |||
| 379 | for (fn_param_types) |fn_param, i| { | ||
| 380 | llvm_param[i] = codegen.getLLVMType(fn_param); | ||
| 381 | } | ||
| 382 | |||
| 383 | const fn_type = llvm.TypeRef.functionType( | ||
| 384 | codegen.getLLVMType(return_type), | ||
| 385 | if (fn_param_len == 0) null else llvm_param.ptr, | ||
| 386 | @intCast(c_uint, fn_param_len), | ||
| 387 | false, | ||
| 388 | ); | ||
| 389 | const llvm_fn = codegen.llvm_module.addFunction(func.owner_decl.name, fn_type); | ||
| 390 | |||
| 391 | if (return_type.zigTypeTag() == .NoReturn) { | ||
| 392 | llvm_fn.addFnAttr("noreturn"); | ||
| 393 | } | ||
| 394 | |||
| 395 | return llvm_fn; | ||
| 396 | } | ||
| 397 | |||
| 398 | fn getLLVMType(codegen: *CodeGen, t: Type) *const llvm.TypeRef { | ||
| 399 | switch (t.zigTypeTag()) { | ||
| 400 | .Void => return llvm.voidType(), | ||
| 401 | .NoReturn => return llvm.voidType(), | ||
| 402 | .Int => { | ||
| 403 | const info = t.intInfo(codegen.module.getTarget()); | ||
| 404 | return llvm.intType(info.bits); | ||
| 405 | }, | ||
| 406 | .Bool => return llvm.intType(1), | ||
| 407 | else => unreachable, | ||
| 408 | } | ||
| 409 | } | ||
| 410 | }; | ||
src/llvm_bindings.zig+358| ... | @@ -1,6 +1,364 @@ | ... | @@ -1,6 +1,364 @@ |
| 1 | //! We do this instead of @cImport because the self-hosted compiler is easier | 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. | 2 | //! to bootstrap if it does not depend on translate-c. |
| 3 | 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 | |||
| 41 | pub const ModuleRef = opaque { | ||
| 42 | pub const createWithName = LLVMModuleCreateWithName; | ||
| 43 | extern fn LLVMModuleCreateWithName(ModuleID: [*:0]const u8) *const ModuleRef; | ||
| 44 | |||
| 45 | pub const disposeModule = LLVMDisposeModule; | ||
| 46 | extern fn LLVMDisposeModule(*const ModuleRef) void; | ||
| 47 | |||
| 48 | pub const verifyModule = LLVMVerifyModule; | ||
| 49 | extern fn LLVMVerifyModule(*const ModuleRef, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) LLVMBool; | ||
| 50 | |||
| 51 | pub const addFunction = LLVMAddFunction; | ||
| 52 | extern fn LLVMAddFunction(*const ModuleRef, Name: [*:0]const u8, FunctionTy: *const TypeRef) *const ValueRef; | ||
| 53 | |||
| 54 | pub const getNamedFunction = LLVMGetNamedFunction; | ||
| 55 | extern fn LLVMGetNamedFunction(*const ModuleRef, Name: [*:0]const u8) ?*const ValueRef; | ||
| 56 | |||
| 57 | pub const printToString = LLVMPrintModuleToString; | ||
| 58 | extern fn LLVMPrintModuleToString(*const ModuleRef) [*:0]const u8; | ||
| 59 | }; | ||
| 60 | |||
| 61 | pub const disposeMessage = LLVMDisposeMessage; | ||
| 62 | extern fn LLVMDisposeMessage(Message: [*:0]const u8) void; | ||
| 63 | |||
| 64 | pub const VerifierFailureAction = extern enum { | ||
| 65 | AbortProcess, | ||
| 66 | PrintMessage, | ||
| 67 | ReturnStatus, | ||
| 68 | }; | ||
| 69 | |||
| 70 | pub const voidType = LLVMVoidType; | ||
| 71 | extern fn LLVMVoidType() *const TypeRef; | ||
| 72 | |||
| 73 | pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName; | ||
| 74 | extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint; | ||
| 75 | |||
| 76 | pub const AttributeRef = opaque {}; | ||
| 77 | |||
| 78 | pub const ContextRef = opaque { | ||
| 79 | pub const createEnumAttribute = LLVMCreateEnumAttribute; | ||
| 80 | extern fn LLVMCreateEnumAttribute(*const ContextRef, KindID: c_uint, Val: u64) *const AttributeRef; | ||
| 81 | |||
| 82 | pub const getGlobal = LLVMGetGlobalContext; | ||
| 83 | extern fn LLVMGetGlobalContext() *const ContextRef; | ||
| 84 | }; | ||
| 85 | |||
| 86 | pub const intType = LLVMIntType; | ||
| 87 | extern fn LLVMIntType(NumBits: c_uint) *const TypeRef; | ||
| 88 | |||
| 89 | pub const BuilderRef = opaque { | ||
| 90 | pub const createBuilder = LLVMCreateBuilder; | ||
| 91 | extern fn LLVMCreateBuilder() *const BuilderRef; | ||
| 92 | |||
| 93 | pub const disposeBuilder = LLVMDisposeBuilder; | ||
| 94 | extern fn LLVMDisposeBuilder(Builder: *const BuilderRef) void; | ||
| 95 | |||
| 96 | pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd; | ||
| 97 | extern fn LLVMPositionBuilderAtEnd(Builder: *const BuilderRef, Block: *const BasicBlockRef) void; | ||
| 98 | |||
| 99 | pub const getInsertBlock = LLVMGetInsertBlock; | ||
| 100 | extern fn LLVMGetInsertBlock(Builder: *const BuilderRef) *const BasicBlockRef; | ||
| 101 | |||
| 102 | pub const buildCall = LLVMBuildCall; | ||
| 103 | extern fn LLVMBuildCall(*const BuilderRef, Fn: *const ValueRef, Args: ?[*]*const ValueRef, NumArgs: c_uint, Name: [*:0]const u8) *const ValueRef; | ||
| 104 | |||
| 105 | pub const buildCall2 = LLVMBuildCall2; | ||
| 106 | extern fn LLVMBuildCall2(*const BuilderRef, *const TypeRef, Fn: *const ValueRef, Args: [*]*const ValueRef, NumArgs: c_uint, Name: [*:0]const u8) *const ValueRef; | ||
| 107 | |||
| 108 | pub const buildRetVoid = LLVMBuildRetVoid; | ||
| 109 | extern fn LLVMBuildRetVoid(*const BuilderRef) *const ValueRef; | ||
| 110 | |||
| 111 | pub const buildUnreachable = LLVMBuildUnreachable; | ||
| 112 | extern fn LLVMBuildUnreachable(*const BuilderRef) *const ValueRef; | ||
| 113 | |||
| 114 | pub const buildAlloca = LLVMBuildAlloca; | ||
| 115 | extern fn LLVMBuildAlloca(*const BuilderRef, Ty: *const TypeRef, Name: [*:0]const u8) *const ValueRef; | ||
| 116 | }; | ||
| 117 | |||
| 118 | pub const BasicBlockRef = opaque { | ||
| 119 | pub const deleteBasicBlock = LLVMDeleteBasicBlock; | ||
| 120 | extern fn LLVMDeleteBasicBlock(BB: *const BasicBlockRef) void; | ||
| 121 | }; | ||
| 122 | |||
| 123 | pub const TargetMachineRef = opaque { | ||
| 124 | pub const createTargetMachine = LLVMCreateTargetMachine; | ||
| 125 | extern fn LLVMCreateTargetMachine( | ||
| 126 | T: *const TargetRef, | ||
| 127 | Triple: [*:0]const u8, | ||
| 128 | CPU: [*:0]const u8, | ||
| 129 | Features: [*:0]const u8, | ||
| 130 | Level: CodeGenOptLevel, | ||
| 131 | Reloc: RelocMode, | ||
| 132 | CodeModel: CodeMode, | ||
| 133 | ) *const TargetMachineRef; | ||
| 134 | |||
| 135 | pub const disposeTargetMachine = LLVMDisposeTargetMachine; | ||
| 136 | extern fn LLVMDisposeTargetMachine(T: *const TargetMachineRef) void; | ||
| 137 | |||
| 138 | pub const emitToFile = LLVMTargetMachineEmitToFile; | ||
| 139 | extern fn LLVMTargetMachineEmitToFile(*const TargetMachineRef, M: *const ModuleRef, Filename: [*:0]const u8, codegen: CodeGenFileType, ErrorMessage: *[*:0]const u8) LLVMBool; | ||
| 140 | }; | ||
| 141 | |||
| 142 | pub const CodeMode = extern enum { | ||
| 143 | Default, | ||
| 144 | JITDefault, | ||
| 145 | Tiny, | ||
| 146 | Small, | ||
| 147 | Kernel, | ||
| 148 | Medium, | ||
| 149 | Large, | ||
| 150 | }; | ||
| 151 | |||
| 152 | pub const CodeGenOptLevel = extern enum { | ||
| 153 | None, | ||
| 154 | Less, | ||
| 155 | Default, | ||
| 156 | Aggressive, | ||
| 157 | }; | ||
| 158 | |||
| 159 | pub const RelocMode = extern enum { | ||
| 160 | Default, | ||
| 161 | Static, | ||
| 162 | PIC, | ||
| 163 | DynamicNoPic, | ||
| 164 | ROPI, | ||
| 165 | RWPI, | ||
| 166 | ROPI_RWPI, | ||
| 167 | }; | ||
| 168 | |||
| 169 | pub const CodeGenFileType = extern enum { | ||
| 170 | AssemblyFile, | ||
| 171 | ObjectFile, | ||
| 172 | }; | ||
| 173 | |||
| 174 | pub const TargetRef = opaque { | ||
| 175 | pub const getTargetFromTriple = LLVMGetTargetFromTriple; | ||
| 176 | extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const TargetRef, ErrorMessage: *[*:0]const u8) LLVMBool; | ||
| 177 | }; | ||
| 178 | |||
| 179 | extern fn LLVMInitializeAArch64TargetInfo() void; | ||
| 180 | extern fn LLVMInitializeAMDGPUTargetInfo() void; | ||
| 181 | extern fn LLVMInitializeARMTargetInfo() void; | ||
| 182 | extern fn LLVMInitializeAVRTargetInfo() void; | ||
| 183 | extern fn LLVMInitializeBPFTargetInfo() void; | ||
| 184 | extern fn LLVMInitializeHexagonTargetInfo() void; | ||
| 185 | extern fn LLVMInitializeLanaiTargetInfo() void; | ||
| 186 | extern fn LLVMInitializeMipsTargetInfo() void; | ||
| 187 | extern fn LLVMInitializeMSP430TargetInfo() void; | ||
| 188 | extern fn LLVMInitializeNVPTXTargetInfo() void; | ||
| 189 | extern fn LLVMInitializePowerPCTargetInfo() void; | ||
| 190 | extern fn LLVMInitializeRISCVTargetInfo() void; | ||
| 191 | extern fn LLVMInitializeSparcTargetInfo() void; | ||
| 192 | extern fn LLVMInitializeSystemZTargetInfo() void; | ||
| 193 | extern fn LLVMInitializeWebAssemblyTargetInfo() void; | ||
| 194 | extern fn LLVMInitializeX86TargetInfo() void; | ||
| 195 | extern fn LLVMInitializeXCoreTargetInfo() void; | ||
| 196 | extern fn LLVMInitializeAArch64Target() void; | ||
| 197 | extern fn LLVMInitializeAMDGPUTarget() void; | ||
| 198 | extern fn LLVMInitializeARMTarget() void; | ||
| 199 | extern fn LLVMInitializeAVRTarget() void; | ||
| 200 | extern fn LLVMInitializeBPFTarget() void; | ||
| 201 | extern fn LLVMInitializeHexagonTarget() void; | ||
| 202 | extern fn LLVMInitializeLanaiTarget() void; | ||
| 203 | extern fn LLVMInitializeMipsTarget() void; | ||
| 204 | extern fn LLVMInitializeMSP430Target() void; | ||
| 205 | extern fn LLVMInitializeNVPTXTarget() void; | ||
| 206 | extern fn LLVMInitializePowerPCTarget() void; | ||
| 207 | extern fn LLVMInitializeRISCVTarget() void; | ||
| 208 | extern fn LLVMInitializeSparcTarget() void; | ||
| 209 | extern fn LLVMInitializeSystemZTarget() void; | ||
| 210 | extern fn LLVMInitializeWebAssemblyTarget() void; | ||
| 211 | extern fn LLVMInitializeX86Target() void; | ||
| 212 | extern fn LLVMInitializeXCoreTarget() void; | ||
| 213 | extern fn LLVMInitializeAArch64TargetMC() void; | ||
| 214 | extern fn LLVMInitializeAMDGPUTargetMC() void; | ||
| 215 | extern fn LLVMInitializeARMTargetMC() void; | ||
| 216 | extern fn LLVMInitializeAVRTargetMC() void; | ||
| 217 | extern fn LLVMInitializeBPFTargetMC() void; | ||
| 218 | extern fn LLVMInitializeHexagonTargetMC() void; | ||
| 219 | extern fn LLVMInitializeLanaiTargetMC() void; | ||
| 220 | extern fn LLVMInitializeMipsTargetMC() void; | ||
| 221 | extern fn LLVMInitializeMSP430TargetMC() void; | ||
| 222 | extern fn LLVMInitializeNVPTXTargetMC() void; | ||
| 223 | extern fn LLVMInitializePowerPCTargetMC() void; | ||
| 224 | extern fn LLVMInitializeRISCVTargetMC() void; | ||
| 225 | extern fn LLVMInitializeSparcTargetMC() void; | ||
| 226 | extern fn LLVMInitializeSystemZTargetMC() void; | ||
| 227 | extern fn LLVMInitializeWebAssemblyTargetMC() void; | ||
| 228 | extern fn LLVMInitializeX86TargetMC() void; | ||
| 229 | extern fn LLVMInitializeXCoreTargetMC() void; | ||
| 230 | extern fn LLVMInitializeAArch64AsmPrinter() void; | ||
| 231 | extern fn LLVMInitializeAMDGPUAsmPrinter() void; | ||
| 232 | extern fn LLVMInitializeARMAsmPrinter() void; | ||
| 233 | extern fn LLVMInitializeAVRAsmPrinter() void; | ||
| 234 | extern fn LLVMInitializeBPFAsmPrinter() void; | ||
| 235 | extern fn LLVMInitializeHexagonAsmPrinter() void; | ||
| 236 | extern fn LLVMInitializeLanaiAsmPrinter() void; | ||
| 237 | extern fn LLVMInitializeMipsAsmPrinter() void; | ||
| 238 | extern fn LLVMInitializeMSP430AsmPrinter() void; | ||
| 239 | extern fn LLVMInitializeNVPTXAsmPrinter() void; | ||
| 240 | extern fn LLVMInitializePowerPCAsmPrinter() void; | ||
| 241 | extern fn LLVMInitializeRISCVAsmPrinter() void; | ||
| 242 | extern fn LLVMInitializeSparcAsmPrinter() void; | ||
| 243 | extern fn LLVMInitializeSystemZAsmPrinter() void; | ||
| 244 | extern fn LLVMInitializeWebAssemblyAsmPrinter() void; | ||
| 245 | extern fn LLVMInitializeX86AsmPrinter() void; | ||
| 246 | extern fn LLVMInitializeXCoreAsmPrinter() void; | ||
| 247 | extern fn LLVMInitializeAArch64AsmParser() void; | ||
| 248 | extern fn LLVMInitializeAMDGPUAsmParser() void; | ||
| 249 | extern fn LLVMInitializeARMAsmParser() void; | ||
| 250 | extern fn LLVMInitializeAVRAsmParser() void; | ||
| 251 | extern fn LLVMInitializeBPFAsmParser() void; | ||
| 252 | extern fn LLVMInitializeHexagonAsmParser() void; | ||
| 253 | extern fn LLVMInitializeLanaiAsmParser() void; | ||
| 254 | extern fn LLVMInitializeMipsAsmParser() void; | ||
| 255 | extern fn LLVMInitializeMSP430AsmParser() void; | ||
| 256 | extern fn LLVMInitializePowerPCAsmParser() void; | ||
| 257 | extern fn LLVMInitializeRISCVAsmParser() void; | ||
| 258 | extern fn LLVMInitializeSparcAsmParser() void; | ||
| 259 | extern fn LLVMInitializeSystemZAsmParser() void; | ||
| 260 | extern fn LLVMInitializeWebAssemblyAsmParser() void; | ||
| 261 | extern fn LLVMInitializeX86AsmParser() void; | ||
| 262 | |||
| 263 | pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos; | ||
| 264 | fn LLVMInitializeAllTargetInfos() callconv(.C) void { | ||
| 265 | LLVMInitializeAArch64TargetInfo(); | ||
| 266 | LLVMInitializeAMDGPUTargetInfo(); | ||
| 267 | LLVMInitializeARMTargetInfo(); | ||
| 268 | LLVMInitializeAVRTargetInfo(); | ||
| 269 | LLVMInitializeBPFTargetInfo(); | ||
| 270 | LLVMInitializeHexagonTargetInfo(); | ||
| 271 | LLVMInitializeLanaiTargetInfo(); | ||
| 272 | LLVMInitializeMipsTargetInfo(); | ||
| 273 | LLVMInitializeMSP430TargetInfo(); | ||
| 274 | LLVMInitializeNVPTXTargetInfo(); | ||
| 275 | LLVMInitializePowerPCTargetInfo(); | ||
| 276 | LLVMInitializeRISCVTargetInfo(); | ||
| 277 | LLVMInitializeSparcTargetInfo(); | ||
| 278 | LLVMInitializeSystemZTargetInfo(); | ||
| 279 | LLVMInitializeWebAssemblyTargetInfo(); | ||
| 280 | LLVMInitializeX86TargetInfo(); | ||
| 281 | LLVMInitializeXCoreTargetInfo(); | ||
| 282 | } | ||
| 283 | pub const initializeAllTargets = LLVMInitializeAllTargets; | ||
| 284 | fn LLVMInitializeAllTargets() callconv(.C) void { | ||
| 285 | LLVMInitializeAArch64Target(); | ||
| 286 | LLVMInitializeAMDGPUTarget(); | ||
| 287 | LLVMInitializeARMTarget(); | ||
| 288 | LLVMInitializeAVRTarget(); | ||
| 289 | LLVMInitializeBPFTarget(); | ||
| 290 | LLVMInitializeHexagonTarget(); | ||
| 291 | LLVMInitializeLanaiTarget(); | ||
| 292 | LLVMInitializeMipsTarget(); | ||
| 293 | LLVMInitializeMSP430Target(); | ||
| 294 | LLVMInitializeNVPTXTarget(); | ||
| 295 | LLVMInitializePowerPCTarget(); | ||
| 296 | LLVMInitializeRISCVTarget(); | ||
| 297 | LLVMInitializeSparcTarget(); | ||
| 298 | LLVMInitializeSystemZTarget(); | ||
| 299 | LLVMInitializeWebAssemblyTarget(); | ||
| 300 | LLVMInitializeX86Target(); | ||
| 301 | LLVMInitializeXCoreTarget(); | ||
| 302 | } | ||
| 303 | pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs; | ||
| 304 | fn LLVMInitializeAllTargetMCs() callconv(.C) void { | ||
| 305 | LLVMInitializeAArch64TargetMC(); | ||
| 306 | LLVMInitializeAMDGPUTargetMC(); | ||
| 307 | LLVMInitializeARMTargetMC(); | ||
| 308 | LLVMInitializeAVRTargetMC(); | ||
| 309 | LLVMInitializeBPFTargetMC(); | ||
| 310 | LLVMInitializeHexagonTargetMC(); | ||
| 311 | LLVMInitializeLanaiTargetMC(); | ||
| 312 | LLVMInitializeMipsTargetMC(); | ||
| 313 | LLVMInitializeMSP430TargetMC(); | ||
| 314 | LLVMInitializeNVPTXTargetMC(); | ||
| 315 | LLVMInitializePowerPCTargetMC(); | ||
| 316 | LLVMInitializeRISCVTargetMC(); | ||
| 317 | LLVMInitializeSparcTargetMC(); | ||
| 318 | LLVMInitializeSystemZTargetMC(); | ||
| 319 | LLVMInitializeWebAssemblyTargetMC(); | ||
| 320 | LLVMInitializeX86TargetMC(); | ||
| 321 | LLVMInitializeXCoreTargetMC(); | ||
| 322 | } | ||
| 323 | pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters; | ||
| 324 | fn LLVMInitializeAllAsmPrinters() callconv(.C) void { | ||
| 325 | LLVMInitializeAArch64AsmPrinter(); | ||
| 326 | LLVMInitializeAMDGPUAsmPrinter(); | ||
| 327 | LLVMInitializeARMAsmPrinter(); | ||
| 328 | LLVMInitializeAVRAsmPrinter(); | ||
| 329 | LLVMInitializeBPFAsmPrinter(); | ||
| 330 | LLVMInitializeHexagonAsmPrinter(); | ||
| 331 | LLVMInitializeLanaiAsmPrinter(); | ||
| 332 | LLVMInitializeMipsAsmPrinter(); | ||
| 333 | LLVMInitializeMSP430AsmPrinter(); | ||
| 334 | LLVMInitializeNVPTXAsmPrinter(); | ||
| 335 | LLVMInitializePowerPCAsmPrinter(); | ||
| 336 | LLVMInitializeRISCVAsmPrinter(); | ||
| 337 | LLVMInitializeSparcAsmPrinter(); | ||
| 338 | LLVMInitializeSystemZAsmPrinter(); | ||
| 339 | LLVMInitializeWebAssemblyAsmPrinter(); | ||
| 340 | LLVMInitializeX86AsmPrinter(); | ||
| 341 | LLVMInitializeXCoreAsmPrinter(); | ||
| 342 | } | ||
| 343 | pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers; | ||
| 344 | fn LLVMInitializeAllAsmParsers() callconv(.C) void { | ||
| 345 | LLVMInitializeAArch64AsmParser(); | ||
| 346 | LLVMInitializeAMDGPUAsmParser(); | ||
| 347 | LLVMInitializeARMAsmParser(); | ||
| 348 | LLVMInitializeAVRAsmParser(); | ||
| 349 | LLVMInitializeBPFAsmParser(); | ||
| 350 | LLVMInitializeHexagonAsmParser(); | ||
| 351 | LLVMInitializeLanaiAsmParser(); | ||
| 352 | LLVMInitializeMipsAsmParser(); | ||
| 353 | LLVMInitializeMSP430AsmParser(); | ||
| 354 | LLVMInitializePowerPCAsmParser(); | ||
| 355 | LLVMInitializeRISCVAsmParser(); | ||
| 356 | LLVMInitializeSparcAsmParser(); | ||
| 357 | LLVMInitializeSystemZAsmParser(); | ||
| 358 | LLVMInitializeWebAssemblyAsmParser(); | ||
| 359 | LLVMInitializeX86AsmParser(); | ||
| 360 | } | ||
| 361 | |||
| 4 | extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | 362 | 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; | 363 | 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; | 364 | extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; |