authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-28 15:07:21-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-12-28 15:07:21-08:00
log2df2f0020f4ddc41b3b914cd17efcb403cf0f6ad
tree8826f40cd08a1cbe945e82bc3f2495a0ed42ad7d
parentf75d4cbe56f9f8212581f00700600a57ce545ba1
parentec3aedffb173845b3fe6f7559e06e1bc3cfde6f7
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7498 from FireFox317/stage2-llvm

stage2: add initial impl of LLVM backend in self-hosted compiler

14 files changed, 1069 insertions(+), 293 deletions(-)

CMakeLists.txt+2-2
......@@ -527,7 +527,6 @@ set(ZIG_STAGE2_SOURCES
527527 "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig"
528528 "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig"
529529 "${CMAKE_SOURCE_DIR}/src/codegen/c.zig"
530 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
531530 "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig"
532531 "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig"
533532 "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig"
......@@ -549,7 +548,8 @@ set(ZIG_STAGE2_SOURCES
549548 "${CMAKE_SOURCE_DIR}/src/link/cbe.h"
550549 "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin"
551550 "${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"
553553 "${CMAKE_SOURCE_DIR}/src/main.zig"
554554 "${CMAKE_SOURCE_DIR}/src/mingw.zig"
555555 "${CMAKE_SOURCE_DIR}/src/musl.zig"
build.zig+20-13
......@@ -91,6 +91,20 @@ pub fn build(b: *Builder) !void {
9191 exe.addBuildOption(bool, "have_llvm", enable_llvm);
9292 if (enable_llvm) {
9393 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 };
94108 if (is_stage1) {
95109 exe.addIncludeDir("src");
96110 exe.addIncludeDir("deps/SoftFloat-3e/source/include");
......@@ -109,19 +123,6 @@ pub fn build(b: *Builder) !void {
109123 softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" });
110124 exe.linkLibrary(softfloat);
111125
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 };
125126 exe.addCSourceFiles(&stage1_sources, &exe_cflags);
126127 exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
127128 if (cmake_cfg == null) {
......@@ -205,6 +206,12 @@ pub fn build(b: *Builder) !void {
205206 exe.linkSystemLibrary(lib_name);
206207 }
207208
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
208215 // This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries.
209216 exe.linkSystemLibrary("c++");
210217
src/Compilation.zig+1-1
......@@ -2106,7 +2106,7 @@ pub fn addCCArgs(
21062106 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
21072107 }
21082108
2109 const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
2109 const llvm_triple = try @import("llvm_backend.zig").targetTriple(arena, target);
21102110 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
21112111
21122112 switch (ext) {
src/codegen/llvm.zig deleted-125
......@@ -1,125 +0,0 @@
1const std = @import("std");
2const Allocator = std.mem.Allocator;
3
4pub 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 {
567567 std.debug.print("\n", .{});
568568 }
569569
570 const llvm = @import("llvm.zig");
570 const llvm = @import("llvm_bindings.zig");
571571 const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag);
572572 const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type);
573573 if (bad) return error.UnableToWriteArchive;
src/link/Coff.zig+29-3
......@@ -16,6 +16,7 @@ const link = @import("../link.zig");
1616const build_options = @import("build_options");
1717const Cache = @import("../Cache.zig");
1818const mingw = @import("../mingw.zig");
19const llvm_backend = @import("../llvm_backend.zig");
1920
2021const allocation_padding = 4 / 3;
2122const minimum_text_block_size = 64 * allocation_padding;
......@@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff;
3233
3334const msdos_stub = @embedFile("msdos-stub.bin");
3435
36/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
37llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
38
3539base: link.File,
3640ptr_width: PtrWidth,
3741error_flags: link.File.ErrorFlags = .{},
......@@ -121,8 +125,13 @@ pub const SrcFn = void;
121125pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff {
122126 assert(options.object_format == .coff);
123127
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 }
126135
127136 const file = try options.emit.?.directory.handle.createFile(sub_path, .{
128137 .truncate = false,
......@@ -404,6 +413,8 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff {
404413}
405414
406415pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void {
416 if (self.llvm_ir_module) |_| return;
417
407418 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
408419
409420 if (self.offset_table_free_list.popOrNull()) |i| {
......@@ -648,6 +659,9 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
648659 const tracy = trace(@src());
649660 defer tracy.end();
650661
662 if (build_options.have_llvm)
663 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
664
651665 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
652666 defer code_buffer.deinit();
653667
......@@ -698,12 +712,16 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
698712}
699713
700714pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
715 if (self.llvm_ir_module) |_| return;
716
701717 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
702718 self.freeTextBlock(&decl.link.coff);
703719 self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {};
704720}
705721
706722pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
723 if (self.llvm_ir_module) |_| return;
724
707725 for (exports) |exp| {
708726 if (exp.options.section) |section_name| {
709727 if (!mem.eql(u8, section_name, ".text")) {
......@@ -744,6 +762,9 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
744762 const tracy = trace(@src());
745763 defer tracy.end();
746764
765 if (build_options.have_llvm)
766 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp);
767
747768 if (self.text_section_size_dirty) {
748769 // Write the new raw size in the .text header
749770 var buf: [4]u8 = undefined;
......@@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
11241145 try argv.append(comp.libunwind_static_lib.?.full_object_path);
11251146 }
11261147
1148 // TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig
11271149 // 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) {
11291151 if (!self.base.options.link_libc) {
11301152 try argv.append(comp.libc_static_lib.?.full_object_path);
11311153 }
......@@ -1227,6 +1249,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
12271249}
12281250
12291251pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
1252 assert(self.llvm_ir_module == null);
12301253 return self.text_section_virtual_address + decl.link.coff.text_offset;
12311254}
12321255
......@@ -1235,6 +1258,9 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
12351258}
12361259
12371260pub 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
12381264 self.text_block_free_list.deinit(self.base.allocator);
12391265 self.offset_table.deinit(self.base.allocator);
12401266 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");
2424const target_util = @import("../target.zig");
2525const glibc = @import("../glibc.zig");
2626const Cache = @import("../Cache.zig");
27const llvm_backend = @import("../llvm_backend.zig");
2728
2829const default_entry_addr = 0x8000000;
2930
......@@ -33,6 +34,9 @@ base: File,
3334
3435ptr_width: PtrWidth,
3536
37/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
38llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
39
3640/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
3741/// Same order as in the file.
3842sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){},
......@@ -224,7 +228,13 @@ pub const SrcFn = struct {
224228pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Elf {
225229 assert(options.object_format == .elf);
226230
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 }
228238
229239 const file = try options.emit.?.directory.handle.createFile(sub_path, .{
230240 .truncate = false,
......@@ -288,6 +298,10 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf {
288298}
289299
290300pub 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
291305 self.sections.deinit(self.base.allocator);
292306 self.program_headers.deinit(self.base.allocator);
293307 self.shstrtab.deinit(self.base.allocator);
......@@ -304,6 +318,7 @@ pub fn deinit(self: *Elf) void {
304318}
305319
306320pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 {
321 assert(self.llvm_ir_module == null);
307322 assert(decl.link.elf.local_sym_index != 0);
308323 return self.local_symbols.items[decl.link.elf.local_sym_index].st_value;
309324}
......@@ -423,6 +438,8 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 {
423438}
424439
425440pub fn populateMissingMetadata(self: *Elf) !void {
441 assert(self.llvm_ir_module == null);
442
426443 const small_ptr = switch (self.ptr_width) {
427444 .p32 => true,
428445 .p64 => false,
......@@ -727,6 +744,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
727744 const tracy = trace(@src());
728745 defer tracy.end();
729746
747 if (build_options.have_llvm)
748 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp);
749
730750 // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the
731751 // Zig source code.
732752 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
......@@ -1261,6 +1281,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
12611281 const stack_size = self.base.options.stack_size_override orelse 16777216;
12621282 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
12631283 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
12641287 if (is_exe_or_dyn_lib) {
12651288 break :blk comp.compiler_rt_static_lib.?.full_object_path;
12661289 } else {
......@@ -1552,7 +1575,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
15521575 }
15531576
15541577 // 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 {
15561584 try argv.append(comp.libc_static_lib.?.full_object_path);
15571585 }
15581586
......@@ -2046,6 +2074,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
20462074}
20472075
20482076pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
2077 if (self.llvm_ir_module) |_| return;
2078
20492079 if (decl.link.elf.local_sym_index != 0) return;
20502080
20512081 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 {
20822112}
20832113
20842114pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
2115 if (self.llvm_ir_module) |_| return;
2116
20852117 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
20862118 self.freeTextBlock(&decl.link.elf);
20872119 if (decl.link.elf.local_sym_index != 0) {
......@@ -2119,6 +2151,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
21192151 const tracy = trace(@src());
21202152 defer tracy.end();
21212153
2154 if (build_options.have_llvm)
2155 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
2156
21222157 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
21232158 defer code_buffer.deinit();
21242159
......@@ -2594,6 +2629,8 @@ pub fn updateDeclExports(
25942629 decl: *const Module.Decl,
25952630 exports: []const *Module.Export,
25962631) !void {
2632 if (self.llvm_ir_module) |_| return;
2633
25972634 const tracy = trace(@src());
25982635 defer tracy.end();
25992636
......@@ -2667,6 +2704,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
26672704 const tracy = trace(@src());
26682705 defer tracy.end();
26692706
2707 if (self.llvm_ir_module) |_| return;
2708
26702709 const container_scope = decl.scope.cast(Module.Scope.Container).?;
26712710 const tree = container_scope.file_scope.contents.tree;
26722711 const file_ast_decls = tree.root_node.decls();
......@@ -2685,6 +2724,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
26852724}
26862725
26872726pub fn deleteExport(self: *Elf, exp: Export) void {
2727 if (self.llvm_ir_module) |_| return;
2728
26882729 const sym_index = exp.sym_index orelse return;
26892730 self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {};
26902731 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
4extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
5extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
6extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
7extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
8
9pub const LinkCOFF = ZigLLDLinkCOFF;
10pub const LinkELF = ZigLLDLinkELF;
11pub const LinkMachO = ZigLLDLinkMachO;
12pub const LinkWasm = ZigLLDLinkWasm;
13
14pub const ObjectFormatType = extern enum(c_int) {
15 Unknown,
16 COFF,
17 ELF,
18 MachO,
19 Wasm,
20 XCOFF,
21};
22
23pub const GetHostCPUName = LLVMGetHostCPUName;
24extern fn LLVMGetHostCPUName() ?[*:0]u8;
25
26pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
27extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
28
29pub const WriteArchive = ZigLLVMWriteArchive;
30extern 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
37pub 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
76pub 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
131pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
132extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
133
134pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
135extern 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 @@
1const std = @import("std");
2const Allocator = std.mem.Allocator;
3const Compilation = @import("Compilation.zig");
4const llvm = @import("llvm_bindings.zig");
5const link = @import("link.zig");
6
7const Module = @import("Module.zig");
8const TypedValue = @import("TypedValue.zig");
9const ir = @import("ir.zig");
10const Inst = ir.Inst;
11
12const Value = @import("value.zig").Value;
13const Type = @import("type.zig").Type;
14
15pub 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
138pub 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
4const std = @import("std");
5const assert = std.debug.assert;
6
7const LLVMBool = bool;
8pub const LLVMAttributeIndex = c_uint;
9
10pub 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
36pub 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
50pub 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
70pub const disposeMessage = LLVMDisposeMessage;
71extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
72
73pub const VerifierFailureAction = extern enum {
74 AbortProcess,
75 PrintMessage,
76 ReturnStatus,
77};
78
79pub const voidType = LLVMVoidType;
80extern fn LLVMVoidType() *const TypeRef;
81
82pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
83extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
84
85pub const AttributeRef = opaque {};
86
87pub 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
95pub const intType = LLVMIntType;
96extern fn LLVMIntType(NumBits: c_uint) *const TypeRef;
97
98pub 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
127pub const BasicBlockRef = opaque {
128 pub const deleteBasicBlock = LLVMDeleteBasicBlock;
129 extern fn LLVMDeleteBasicBlock(BB: *const BasicBlockRef) void;
130};
131
132pub 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
151pub const CodeMode = extern enum {
152 Default,
153 JITDefault,
154 Tiny,
155 Small,
156 Kernel,
157 Medium,
158 Large,
159};
160
161pub const CodeGenOptLevel = extern enum {
162 None,
163 Less,
164 Default,
165 Aggressive,
166};
167
168pub const RelocMode = extern enum {
169 Default,
170 Static,
171 PIC,
172 DynamicNoPic,
173 ROPI,
174 RWPI,
175 ROPI_RWPI,
176};
177
178pub const CodeGenFileType = extern enum {
179 AssemblyFile,
180 ObjectFile,
181};
182
183pub 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
188extern fn LLVMInitializeAArch64TargetInfo() void;
189extern fn LLVMInitializeAMDGPUTargetInfo() void;
190extern fn LLVMInitializeARMTargetInfo() void;
191extern fn LLVMInitializeAVRTargetInfo() void;
192extern fn LLVMInitializeBPFTargetInfo() void;
193extern fn LLVMInitializeHexagonTargetInfo() void;
194extern fn LLVMInitializeLanaiTargetInfo() void;
195extern fn LLVMInitializeMipsTargetInfo() void;
196extern fn LLVMInitializeMSP430TargetInfo() void;
197extern fn LLVMInitializeNVPTXTargetInfo() void;
198extern fn LLVMInitializePowerPCTargetInfo() void;
199extern fn LLVMInitializeRISCVTargetInfo() void;
200extern fn LLVMInitializeSparcTargetInfo() void;
201extern fn LLVMInitializeSystemZTargetInfo() void;
202extern fn LLVMInitializeWebAssemblyTargetInfo() void;
203extern fn LLVMInitializeX86TargetInfo() void;
204extern fn LLVMInitializeXCoreTargetInfo() void;
205extern fn LLVMInitializeAArch64Target() void;
206extern fn LLVMInitializeAMDGPUTarget() void;
207extern fn LLVMInitializeARMTarget() void;
208extern fn LLVMInitializeAVRTarget() void;
209extern fn LLVMInitializeBPFTarget() void;
210extern fn LLVMInitializeHexagonTarget() void;
211extern fn LLVMInitializeLanaiTarget() void;
212extern fn LLVMInitializeMipsTarget() void;
213extern fn LLVMInitializeMSP430Target() void;
214extern fn LLVMInitializeNVPTXTarget() void;
215extern fn LLVMInitializePowerPCTarget() void;
216extern fn LLVMInitializeRISCVTarget() void;
217extern fn LLVMInitializeSparcTarget() void;
218extern fn LLVMInitializeSystemZTarget() void;
219extern fn LLVMInitializeWebAssemblyTarget() void;
220extern fn LLVMInitializeX86Target() void;
221extern fn LLVMInitializeXCoreTarget() void;
222extern fn LLVMInitializeAArch64TargetMC() void;
223extern fn LLVMInitializeAMDGPUTargetMC() void;
224extern fn LLVMInitializeARMTargetMC() void;
225extern fn LLVMInitializeAVRTargetMC() void;
226extern fn LLVMInitializeBPFTargetMC() void;
227extern fn LLVMInitializeHexagonTargetMC() void;
228extern fn LLVMInitializeLanaiTargetMC() void;
229extern fn LLVMInitializeMipsTargetMC() void;
230extern fn LLVMInitializeMSP430TargetMC() void;
231extern fn LLVMInitializeNVPTXTargetMC() void;
232extern fn LLVMInitializePowerPCTargetMC() void;
233extern fn LLVMInitializeRISCVTargetMC() void;
234extern fn LLVMInitializeSparcTargetMC() void;
235extern fn LLVMInitializeSystemZTargetMC() void;
236extern fn LLVMInitializeWebAssemblyTargetMC() void;
237extern fn LLVMInitializeX86TargetMC() void;
238extern fn LLVMInitializeXCoreTargetMC() void;
239extern fn LLVMInitializeAArch64AsmPrinter() void;
240extern fn LLVMInitializeAMDGPUAsmPrinter() void;
241extern fn LLVMInitializeARMAsmPrinter() void;
242extern fn LLVMInitializeAVRAsmPrinter() void;
243extern fn LLVMInitializeBPFAsmPrinter() void;
244extern fn LLVMInitializeHexagonAsmPrinter() void;
245extern fn LLVMInitializeLanaiAsmPrinter() void;
246extern fn LLVMInitializeMipsAsmPrinter() void;
247extern fn LLVMInitializeMSP430AsmPrinter() void;
248extern fn LLVMInitializeNVPTXAsmPrinter() void;
249extern fn LLVMInitializePowerPCAsmPrinter() void;
250extern fn LLVMInitializeRISCVAsmPrinter() void;
251extern fn LLVMInitializeSparcAsmPrinter() void;
252extern fn LLVMInitializeSystemZAsmPrinter() void;
253extern fn LLVMInitializeWebAssemblyAsmPrinter() void;
254extern fn LLVMInitializeX86AsmPrinter() void;
255extern fn LLVMInitializeXCoreAsmPrinter() void;
256extern fn LLVMInitializeAArch64AsmParser() void;
257extern fn LLVMInitializeAMDGPUAsmParser() void;
258extern fn LLVMInitializeARMAsmParser() void;
259extern fn LLVMInitializeAVRAsmParser() void;
260extern fn LLVMInitializeBPFAsmParser() void;
261extern fn LLVMInitializeHexagonAsmParser() void;
262extern fn LLVMInitializeLanaiAsmParser() void;
263extern fn LLVMInitializeMipsAsmParser() void;
264extern fn LLVMInitializeMSP430AsmParser() void;
265extern fn LLVMInitializePowerPCAsmParser() void;
266extern fn LLVMInitializeRISCVAsmParser() void;
267extern fn LLVMInitializeSparcAsmParser() void;
268extern fn LLVMInitializeSystemZAsmParser() void;
269extern fn LLVMInitializeWebAssemblyAsmParser() void;
270extern fn LLVMInitializeX86AsmParser() void;
271
272pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos;
273fn 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}
292pub const initializeAllTargets = LLVMInitializeAllTargets;
293fn 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}
312pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs;
313fn 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}
332pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters;
333fn 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}
352pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers;
353fn 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
371extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
372extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
373extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
374extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
375
376pub const LinkCOFF = ZigLLDLinkCOFF;
377pub const LinkELF = ZigLLDLinkELF;
378pub const LinkMachO = ZigLLDLinkMachO;
379pub const LinkWasm = ZigLLDLinkWasm;
380
381pub const ObjectFormatType = extern enum(c_int) {
382 Unknown,
383 COFF,
384 ELF,
385 MachO,
386 Wasm,
387 XCOFF,
388};
389
390pub const GetHostCPUName = LLVMGetHostCPUName;
391extern fn LLVMGetHostCPUName() ?[*:0]u8;
392
393pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
394extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
395
396pub const WriteArchive = ZigLLVMWriteArchive;
397extern 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
404pub 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
443pub 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
498pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
499extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
500
501pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
502extern 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(
16761676 if (build_options.have_llvm and emit_asm != .no) {
16771677 // LLVM has no way to set this non-globally.
16781678 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);
16801680 }
16811681
16821682 gimmeMoreOfThoseSweetSweetFileDescriptors();
......@@ -2839,7 +2839,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor
28392839 argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.
28402840 }
28412841 const exit_code = rc: {
2842 const llvm = @import("llvm.zig");
2842 const llvm = @import("llvm_bindings.zig");
28432843 const argc = @intCast(c_int, argv.len);
28442844 if (mem.eql(u8, args[1], "ld.lld")) {
28452845 break :rc llvm.LinkELF(argc, argv.ptr, true);
......@@ -3224,7 +3224,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s
32243224 if (!build_options.have_llvm)
32253225 fatal("CPU features detection is not yet available for {} without LLVM extensions", .{@tagName(arch)});
32263226
3227 const llvm = @import("llvm.zig");
3227 const llvm = @import("llvm_bindings.zig");
32283228 const llvm_cpu_name = llvm.GetHostCPUName();
32293229 const llvm_cpu_features = llvm.GetNativeFeatures();
32303230 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 {
405405 });
406406 errdefer comp.gpa.free(lib_final_path);
407407
408 const llvm = @import("llvm.zig");
408 const llvm = @import("llvm_bindings.zig");
409409 const arch_type = @import("target.zig").archToLLVM(target.cpu.arch);
410410 const def_final_path_z = try arena.dupeZ(u8, def_final_path);
411411 const lib_final_path_z = try arena.dupeZ(u8, lib_final_path);
src/target.zig+1-1
......@@ -1,5 +1,5 @@
11const std = @import("std");
2const llvm = @import("llvm.zig");
2const llvm = @import("llvm_bindings.zig");
33
44pub const ArchOsAbi = struct {
55 arch: std.Target.Cpu.Arch,
src/zig_clang.h+19-1
......@@ -8,14 +8,32 @@
88#ifndef ZIG_ZIG_CLANG_H
99#define ZIG_ZIG_CLANG_H
1010
11#include "stage1/stage2.h"
1211#include <inttypes.h>
1312#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
1420
1521// ATTENTION: If you modify this file, be sure to update the corresponding
1622// extern function declarations in the self-hosted compiler file
1723// src/clang.zig.
1824
25// ABI warning
26struct 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
1937struct ZigClangSourceLocation {
2038 unsigned ID;
2139};