mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 23:23:07 +00:00
Merge pull request #7498 from FireFox317/stage2-llvm
stage2: add initial impl of LLVM backend in self-hosted compiler
This commit is contained in:
commit
2df2f0020f
@ -527,7 +527,6 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/arm.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/c.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig"
|
||||
@ -549,7 +548,8 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/link/cbe.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin"
|
||||
"${CMAKE_SOURCE_DIR}/src/liveness.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/llvm.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/llvm_backend.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/llvm_bindings.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/main.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/mingw.zig"
|
||||
"${CMAKE_SOURCE_DIR}/src/musl.zig"
|
||||
|
||||
33
build.zig
33
build.zig
@ -91,6 +91,20 @@ pub fn build(b: *Builder) !void {
|
||||
exe.addBuildOption(bool, "have_llvm", enable_llvm);
|
||||
if (enable_llvm) {
|
||||
const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option);
|
||||
|
||||
const exe_cflags = [_][]const u8{
|
||||
"-std=c++14",
|
||||
"-D__STDC_CONSTANT_MACROS",
|
||||
"-D__STDC_FORMAT_MACROS",
|
||||
"-D__STDC_LIMIT_MACROS",
|
||||
"-D_GNU_SOURCE",
|
||||
"-fvisibility-inlines-hidden",
|
||||
"-fno-exceptions",
|
||||
"-fno-rtti",
|
||||
"-Werror=type-limits",
|
||||
"-Wno-missing-braces",
|
||||
"-Wno-comment",
|
||||
};
|
||||
if (is_stage1) {
|
||||
exe.addIncludeDir("src");
|
||||
exe.addIncludeDir("deps/SoftFloat-3e/source/include");
|
||||
@ -109,19 +123,6 @@ pub fn build(b: *Builder) !void {
|
||||
softfloat.addCSourceFiles(&softfloat_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
exe.linkLibrary(softfloat);
|
||||
|
||||
const exe_cflags = [_][]const u8{
|
||||
"-std=c++14",
|
||||
"-D__STDC_CONSTANT_MACROS",
|
||||
"-D__STDC_FORMAT_MACROS",
|
||||
"-D__STDC_LIMIT_MACROS",
|
||||
"-D_GNU_SOURCE",
|
||||
"-fvisibility-inlines-hidden",
|
||||
"-fno-exceptions",
|
||||
"-fno-rtti",
|
||||
"-Werror=type-limits",
|
||||
"-Wno-missing-braces",
|
||||
"-Wno-comment",
|
||||
};
|
||||
exe.addCSourceFiles(&stage1_sources, &exe_cflags);
|
||||
exe.addCSourceFiles(&optimized_c_sources, &[_][]const u8{ "-std=c99", "-O3" });
|
||||
if (cmake_cfg == null) {
|
||||
@ -205,6 +206,12 @@ pub fn build(b: *Builder) !void {
|
||||
exe.linkSystemLibrary(lib_name);
|
||||
}
|
||||
|
||||
// We need this because otherwise zig_clang_cc1_main.cpp ends up pulling
|
||||
// in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is
|
||||
// unavailable when LLVM is compiled in Release mode.
|
||||
const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"};
|
||||
exe.addCSourceFiles(&zig_cpp_sources, &zig_cpp_cflags);
|
||||
|
||||
// This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries.
|
||||
exe.linkSystemLibrary("c++");
|
||||
|
||||
|
||||
@ -2106,7 +2106,7 @@ pub fn addCCArgs(
|
||||
try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
|
||||
}
|
||||
|
||||
const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
|
||||
const llvm_triple = try @import("llvm_backend.zig").targetTriple(arena, target);
|
||||
try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
|
||||
|
||||
switch (ext) {
|
||||
|
||||
@ -1,125 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn targetTriple(allocator: *Allocator, target: std.Target) ![]u8 {
|
||||
const llvm_arch = switch (target.cpu.arch) {
|
||||
.arm => "arm",
|
||||
.armeb => "armeb",
|
||||
.aarch64 => "aarch64",
|
||||
.aarch64_be => "aarch64_be",
|
||||
.aarch64_32 => "aarch64_32",
|
||||
.arc => "arc",
|
||||
.avr => "avr",
|
||||
.bpfel => "bpfel",
|
||||
.bpfeb => "bpfeb",
|
||||
.hexagon => "hexagon",
|
||||
.mips => "mips",
|
||||
.mipsel => "mipsel",
|
||||
.mips64 => "mips64",
|
||||
.mips64el => "mips64el",
|
||||
.msp430 => "msp430",
|
||||
.powerpc => "powerpc",
|
||||
.powerpc64 => "powerpc64",
|
||||
.powerpc64le => "powerpc64le",
|
||||
.r600 => "r600",
|
||||
.amdgcn => "amdgcn",
|
||||
.riscv32 => "riscv32",
|
||||
.riscv64 => "riscv64",
|
||||
.sparc => "sparc",
|
||||
.sparcv9 => "sparcv9",
|
||||
.sparcel => "sparcel",
|
||||
.s390x => "s390x",
|
||||
.tce => "tce",
|
||||
.tcele => "tcele",
|
||||
.thumb => "thumb",
|
||||
.thumbeb => "thumbeb",
|
||||
.i386 => "i386",
|
||||
.x86_64 => "x86_64",
|
||||
.xcore => "xcore",
|
||||
.nvptx => "nvptx",
|
||||
.nvptx64 => "nvptx64",
|
||||
.le32 => "le32",
|
||||
.le64 => "le64",
|
||||
.amdil => "amdil",
|
||||
.amdil64 => "amdil64",
|
||||
.hsail => "hsail",
|
||||
.hsail64 => "hsail64",
|
||||
.spir => "spir",
|
||||
.spir64 => "spir64",
|
||||
.kalimba => "kalimba",
|
||||
.shave => "shave",
|
||||
.lanai => "lanai",
|
||||
.wasm32 => "wasm32",
|
||||
.wasm64 => "wasm64",
|
||||
.renderscript32 => "renderscript32",
|
||||
.renderscript64 => "renderscript64",
|
||||
.ve => "ve",
|
||||
.spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
|
||||
};
|
||||
// TODO Add a sub-arch for some architectures depending on CPU features.
|
||||
|
||||
const llvm_os = switch (target.os.tag) {
|
||||
.freestanding => "unknown",
|
||||
.ananas => "ananas",
|
||||
.cloudabi => "cloudabi",
|
||||
.dragonfly => "dragonfly",
|
||||
.freebsd => "freebsd",
|
||||
.fuchsia => "fuchsia",
|
||||
.ios => "ios",
|
||||
.kfreebsd => "kfreebsd",
|
||||
.linux => "linux",
|
||||
.lv2 => "lv2",
|
||||
.macos => "macosx",
|
||||
.netbsd => "netbsd",
|
||||
.openbsd => "openbsd",
|
||||
.solaris => "solaris",
|
||||
.windows => "windows",
|
||||
.haiku => "haiku",
|
||||
.minix => "minix",
|
||||
.rtems => "rtems",
|
||||
.nacl => "nacl",
|
||||
.cnk => "cnk",
|
||||
.aix => "aix",
|
||||
.cuda => "cuda",
|
||||
.nvcl => "nvcl",
|
||||
.amdhsa => "amdhsa",
|
||||
.ps4 => "ps4",
|
||||
.elfiamcu => "elfiamcu",
|
||||
.tvos => "tvos",
|
||||
.watchos => "watchos",
|
||||
.mesa3d => "mesa3d",
|
||||
.contiki => "contiki",
|
||||
.amdpal => "amdpal",
|
||||
.hermit => "hermit",
|
||||
.hurd => "hurd",
|
||||
.wasi => "wasi",
|
||||
.emscripten => "emscripten",
|
||||
.uefi => "windows",
|
||||
.other => "unknown",
|
||||
};
|
||||
|
||||
const llvm_abi = switch (target.abi) {
|
||||
.none => "unknown",
|
||||
.gnu => "gnu",
|
||||
.gnuabin32 => "gnuabin32",
|
||||
.gnuabi64 => "gnuabi64",
|
||||
.gnueabi => "gnueabi",
|
||||
.gnueabihf => "gnueabihf",
|
||||
.gnux32 => "gnux32",
|
||||
.code16 => "code16",
|
||||
.eabi => "eabi",
|
||||
.eabihf => "eabihf",
|
||||
.android => "android",
|
||||
.musl => "musl",
|
||||
.musleabi => "musleabi",
|
||||
.musleabihf => "musleabihf",
|
||||
.msvc => "msvc",
|
||||
.itanium => "itanium",
|
||||
.cygnus => "cygnus",
|
||||
.coreclr => "coreclr",
|
||||
.simulator => "simulator",
|
||||
.macabi => "macabi",
|
||||
};
|
||||
|
||||
return std.fmt.allocPrint(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi });
|
||||
}
|
||||
@ -567,7 +567,7 @@ pub const File = struct {
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
const llvm = @import("llvm.zig");
|
||||
const llvm = @import("llvm_bindings.zig");
|
||||
const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag);
|
||||
const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type);
|
||||
if (bad) return error.UnableToWriteArchive;
|
||||
|
||||
@ -16,6 +16,7 @@ const link = @import("../link.zig");
|
||||
const build_options = @import("build_options");
|
||||
const Cache = @import("../Cache.zig");
|
||||
const mingw = @import("../mingw.zig");
|
||||
const llvm_backend = @import("../llvm_backend.zig");
|
||||
|
||||
const allocation_padding = 4 / 3;
|
||||
const minimum_text_block_size = 64 * allocation_padding;
|
||||
@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff;
|
||||
|
||||
const msdos_stub = @embedFile("msdos-stub.bin");
|
||||
|
||||
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
|
||||
llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
|
||||
|
||||
base: link.File,
|
||||
ptr_width: PtrWidth,
|
||||
error_flags: link.File.ErrorFlags = .{},
|
||||
@ -121,8 +125,13 @@ pub const SrcFn = void;
|
||||
pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff {
|
||||
assert(options.object_format == .coff);
|
||||
|
||||
if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO
|
||||
if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO
|
||||
if (build_options.have_llvm and options.use_llvm) {
|
||||
const self = try createEmpty(allocator, options);
|
||||
errdefer self.base.destroy();
|
||||
|
||||
self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options);
|
||||
return self;
|
||||
}
|
||||
|
||||
const file = try options.emit.?.directory.handle.createFile(sub_path, .{
|
||||
.truncate = false,
|
||||
@ -404,6 +413,8 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff {
|
||||
}
|
||||
|
||||
pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
|
||||
|
||||
if (self.offset_table_free_list.popOrNull()) |i| {
|
||||
@ -648,6 +659,9 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (build_options.have_llvm)
|
||||
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
@ -698,12 +712,16 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
|
||||
}
|
||||
|
||||
pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
|
||||
self.freeTextBlock(&decl.link.coff);
|
||||
self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {};
|
||||
}
|
||||
|
||||
pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
for (exports) |exp| {
|
||||
if (exp.options.section) |section_name| {
|
||||
if (!mem.eql(u8, section_name, ".text")) {
|
||||
@ -744,6 +762,9 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (build_options.have_llvm)
|
||||
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp);
|
||||
|
||||
if (self.text_section_size_dirty) {
|
||||
// Write the new raw size in the .text header
|
||||
var buf: [4]u8 = undefined;
|
||||
@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
|
||||
try argv.append(comp.libunwind_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig
|
||||
// compiler-rt, libc and libssp
|
||||
if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) {
|
||||
if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and build_options.is_stage1) {
|
||||
if (!self.base.options.link_libc) {
|
||||
try argv.append(comp.libc_static_lib.?.full_object_path);
|
||||
}
|
||||
@ -1227,6 +1249,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
|
||||
assert(self.llvm_ir_module == null);
|
||||
return self.text_section_virtual_address + decl.link.coff.text_offset;
|
||||
}
|
||||
|
||||
@ -1235,6 +1258,9 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Coff) void {
|
||||
if (build_options.have_llvm)
|
||||
if (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator);
|
||||
|
||||
self.text_block_free_list.deinit(self.base.allocator);
|
||||
self.offset_table.deinit(self.base.allocator);
|
||||
self.offset_table_free_list.deinit(self.base.allocator);
|
||||
|
||||
@ -24,6 +24,7 @@ const build_options = @import("build_options");
|
||||
const target_util = @import("../target.zig");
|
||||
const glibc = @import("../glibc.zig");
|
||||
const Cache = @import("../Cache.zig");
|
||||
const llvm_backend = @import("../llvm_backend.zig");
|
||||
|
||||
const default_entry_addr = 0x8000000;
|
||||
|
||||
@ -33,6 +34,9 @@ base: File,
|
||||
|
||||
ptr_width: PtrWidth,
|
||||
|
||||
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
|
||||
llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
|
||||
|
||||
/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
|
||||
/// Same order as in the file.
|
||||
sections: std.ArrayListUnmanaged(elf.Elf64_Shdr) = std.ArrayListUnmanaged(elf.Elf64_Shdr){},
|
||||
@ -224,7 +228,13 @@ pub const SrcFn = struct {
|
||||
pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Elf {
|
||||
assert(options.object_format == .elf);
|
||||
|
||||
if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO
|
||||
if (build_options.have_llvm and options.use_llvm) {
|
||||
const self = try createEmpty(allocator, options);
|
||||
errdefer self.base.destroy();
|
||||
|
||||
self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options);
|
||||
return self;
|
||||
}
|
||||
|
||||
const file = try options.emit.?.directory.handle.createFile(sub_path, .{
|
||||
.truncate = false,
|
||||
@ -288,6 +298,10 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Elf) void {
|
||||
if (build_options.have_llvm)
|
||||
if (self.llvm_ir_module) |ir_module|
|
||||
ir_module.deinit(self.base.allocator);
|
||||
|
||||
self.sections.deinit(self.base.allocator);
|
||||
self.program_headers.deinit(self.base.allocator);
|
||||
self.shstrtab.deinit(self.base.allocator);
|
||||
@ -304,6 +318,7 @@ pub fn deinit(self: *Elf) void {
|
||||
}
|
||||
|
||||
pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 {
|
||||
assert(self.llvm_ir_module == null);
|
||||
assert(decl.link.elf.local_sym_index != 0);
|
||||
return self.local_symbols.items[decl.link.elf.local_sym_index].st_value;
|
||||
}
|
||||
@ -423,6 +438,8 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 {
|
||||
}
|
||||
|
||||
pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
assert(self.llvm_ir_module == null);
|
||||
|
||||
const small_ptr = switch (self.ptr_width) {
|
||||
.p32 => true,
|
||||
.p64 => false,
|
||||
@ -727,6 +744,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (build_options.have_llvm)
|
||||
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp);
|
||||
|
||||
// TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the
|
||||
// Zig source code.
|
||||
const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
@ -1261,6 +1281,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
const stack_size = self.base.options.stack_size_override orelse 16777216;
|
||||
const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
|
||||
const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: {
|
||||
// TODO: remove when stage2 can build compiler_rt.zig
|
||||
if (!build_options.is_stage1) break :blk null;
|
||||
|
||||
if (is_exe_or_dyn_lib) {
|
||||
break :blk comp.compiler_rt_static_lib.?.full_object_path;
|
||||
} else {
|
||||
@ -1552,7 +1575,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
// libc
|
||||
if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and !self.base.options.link_libc) {
|
||||
// TODO: enable when stage2 can build c.zig
|
||||
if (is_exe_or_dyn_lib and
|
||||
!self.base.options.skip_linker_dependencies and
|
||||
!self.base.options.link_libc and
|
||||
build_options.is_stage1)
|
||||
{
|
||||
try argv.append(comp.libc_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
@ -2046,6 +2074,8 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
|
||||
}
|
||||
|
||||
pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
if (decl.link.elf.local_sym_index != 0) return;
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
|
||||
self.freeTextBlock(&decl.link.elf);
|
||||
if (decl.link.elf.local_sym_index != 0) {
|
||||
@ -2119,6 +2151,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (build_options.have_llvm)
|
||||
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
@ -2594,6 +2629,8 @@ pub fn updateDeclExports(
|
||||
decl: *const Module.Decl,
|
||||
exports: []const *Module.Export,
|
||||
) !void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -2667,6 +2704,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
const container_scope = decl.scope.cast(Module.Scope.Container).?;
|
||||
const tree = container_scope.file_scope.contents.tree;
|
||||
const file_ast_decls = tree.root_node.decls();
|
||||
@ -2685,6 +2724,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
|
||||
}
|
||||
|
||||
pub fn deleteExport(self: *Elf, exp: Export) void {
|
||||
if (self.llvm_ir_module) |_| return;
|
||||
|
||||
const sym_index = exp.sym_index orelse return;
|
||||
self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {};
|
||||
self.global_symbols.items[sym_index].st_info = 0;
|
||||
|
||||
140
src/llvm.zig
140
src/llvm.zig
@ -1,140 +0,0 @@
|
||||
//! We do this instead of @cImport because the self-hosted compiler is easier
|
||||
//! to bootstrap if it does not depend on translate-c.
|
||||
|
||||
extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
|
||||
pub const LinkCOFF = ZigLLDLinkCOFF;
|
||||
pub const LinkELF = ZigLLDLinkELF;
|
||||
pub const LinkMachO = ZigLLDLinkMachO;
|
||||
pub const LinkWasm = ZigLLDLinkWasm;
|
||||
|
||||
pub const ObjectFormatType = extern enum(c_int) {
|
||||
Unknown,
|
||||
COFF,
|
||||
ELF,
|
||||
MachO,
|
||||
Wasm,
|
||||
XCOFF,
|
||||
};
|
||||
|
||||
pub const GetHostCPUName = LLVMGetHostCPUName;
|
||||
extern fn LLVMGetHostCPUName() ?[*:0]u8;
|
||||
|
||||
pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
|
||||
extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
|
||||
|
||||
pub const WriteArchive = ZigLLVMWriteArchive;
|
||||
extern fn ZigLLVMWriteArchive(
|
||||
archive_name: [*:0]const u8,
|
||||
file_names_ptr: [*]const [*:0]const u8,
|
||||
file_names_len: usize,
|
||||
os_type: OSType,
|
||||
) bool;
|
||||
|
||||
pub const OSType = extern enum(c_int) {
|
||||
UnknownOS = 0,
|
||||
Ananas = 1,
|
||||
CloudABI = 2,
|
||||
Darwin = 3,
|
||||
DragonFly = 4,
|
||||
FreeBSD = 5,
|
||||
Fuchsia = 6,
|
||||
IOS = 7,
|
||||
KFreeBSD = 8,
|
||||
Linux = 9,
|
||||
Lv2 = 10,
|
||||
MacOSX = 11,
|
||||
NetBSD = 12,
|
||||
OpenBSD = 13,
|
||||
Solaris = 14,
|
||||
Win32 = 15,
|
||||
Haiku = 16,
|
||||
Minix = 17,
|
||||
RTEMS = 18,
|
||||
NaCl = 19,
|
||||
CNK = 20,
|
||||
AIX = 21,
|
||||
CUDA = 22,
|
||||
NVCL = 23,
|
||||
AMDHSA = 24,
|
||||
PS4 = 25,
|
||||
ELFIAMCU = 26,
|
||||
TvOS = 27,
|
||||
WatchOS = 28,
|
||||
Mesa3D = 29,
|
||||
Contiki = 30,
|
||||
AMDPAL = 31,
|
||||
HermitCore = 32,
|
||||
Hurd = 33,
|
||||
WASI = 34,
|
||||
Emscripten = 35,
|
||||
};
|
||||
|
||||
pub const ArchType = extern enum(c_int) {
|
||||
UnknownArch = 0,
|
||||
arm = 1,
|
||||
armeb = 2,
|
||||
aarch64 = 3,
|
||||
aarch64_be = 4,
|
||||
aarch64_32 = 5,
|
||||
arc = 6,
|
||||
avr = 7,
|
||||
bpfel = 8,
|
||||
bpfeb = 9,
|
||||
hexagon = 10,
|
||||
mips = 11,
|
||||
mipsel = 12,
|
||||
mips64 = 13,
|
||||
mips64el = 14,
|
||||
msp430 = 15,
|
||||
ppc = 16,
|
||||
ppc64 = 17,
|
||||
ppc64le = 18,
|
||||
r600 = 19,
|
||||
amdgcn = 20,
|
||||
riscv32 = 21,
|
||||
riscv64 = 22,
|
||||
sparc = 23,
|
||||
sparcv9 = 24,
|
||||
sparcel = 25,
|
||||
systemz = 26,
|
||||
tce = 27,
|
||||
tcele = 28,
|
||||
thumb = 29,
|
||||
thumbeb = 30,
|
||||
x86 = 31,
|
||||
x86_64 = 32,
|
||||
xcore = 33,
|
||||
nvptx = 34,
|
||||
nvptx64 = 35,
|
||||
le32 = 36,
|
||||
le64 = 37,
|
||||
amdil = 38,
|
||||
amdil64 = 39,
|
||||
hsail = 40,
|
||||
hsail64 = 41,
|
||||
spir = 42,
|
||||
spir64 = 43,
|
||||
kalimba = 44,
|
||||
shave = 45,
|
||||
lanai = 46,
|
||||
wasm32 = 47,
|
||||
wasm64 = 48,
|
||||
renderscript32 = 49,
|
||||
renderscript64 = 50,
|
||||
ve = 51,
|
||||
};
|
||||
|
||||
pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
|
||||
extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
|
||||
|
||||
pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
|
||||
extern fn ZigLLVMWriteImportLibrary(
|
||||
def_path: [*:0]const u8,
|
||||
arch: ArchType,
|
||||
output_lib_path: [*c]const u8,
|
||||
kill_at: bool,
|
||||
) bool;
|
||||
442
src/llvm_backend.zig
Normal file
442
src/llvm_backend.zig
Normal file
@ -0,0 +1,442 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const llvm = @import("llvm_bindings.zig");
|
||||
const link = @import("link.zig");
|
||||
|
||||
const Module = @import("Module.zig");
|
||||
const TypedValue = @import("TypedValue.zig");
|
||||
const ir = @import("ir.zig");
|
||||
const Inst = ir.Inst;
|
||||
|
||||
const Value = @import("value.zig").Value;
|
||||
const Type = @import("type.zig").Type;
|
||||
|
||||
pub fn targetTriple(allocator: *Allocator, target: std.Target) ![:0]u8 {
|
||||
const llvm_arch = switch (target.cpu.arch) {
|
||||
.arm => "arm",
|
||||
.armeb => "armeb",
|
||||
.aarch64 => "aarch64",
|
||||
.aarch64_be => "aarch64_be",
|
||||
.aarch64_32 => "aarch64_32",
|
||||
.arc => "arc",
|
||||
.avr => "avr",
|
||||
.bpfel => "bpfel",
|
||||
.bpfeb => "bpfeb",
|
||||
.hexagon => "hexagon",
|
||||
.mips => "mips",
|
||||
.mipsel => "mipsel",
|
||||
.mips64 => "mips64",
|
||||
.mips64el => "mips64el",
|
||||
.msp430 => "msp430",
|
||||
.powerpc => "powerpc",
|
||||
.powerpc64 => "powerpc64",
|
||||
.powerpc64le => "powerpc64le",
|
||||
.r600 => "r600",
|
||||
.amdgcn => "amdgcn",
|
||||
.riscv32 => "riscv32",
|
||||
.riscv64 => "riscv64",
|
||||
.sparc => "sparc",
|
||||
.sparcv9 => "sparcv9",
|
||||
.sparcel => "sparcel",
|
||||
.s390x => "s390x",
|
||||
.tce => "tce",
|
||||
.tcele => "tcele",
|
||||
.thumb => "thumb",
|
||||
.thumbeb => "thumbeb",
|
||||
.i386 => "i386",
|
||||
.x86_64 => "x86_64",
|
||||
.xcore => "xcore",
|
||||
.nvptx => "nvptx",
|
||||
.nvptx64 => "nvptx64",
|
||||
.le32 => "le32",
|
||||
.le64 => "le64",
|
||||
.amdil => "amdil",
|
||||
.amdil64 => "amdil64",
|
||||
.hsail => "hsail",
|
||||
.hsail64 => "hsail64",
|
||||
.spir => "spir",
|
||||
.spir64 => "spir64",
|
||||
.kalimba => "kalimba",
|
||||
.shave => "shave",
|
||||
.lanai => "lanai",
|
||||
.wasm32 => "wasm32",
|
||||
.wasm64 => "wasm64",
|
||||
.renderscript32 => "renderscript32",
|
||||
.renderscript64 => "renderscript64",
|
||||
.ve => "ve",
|
||||
.spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
|
||||
};
|
||||
// TODO Add a sub-arch for some architectures depending on CPU features.
|
||||
|
||||
const llvm_os = switch (target.os.tag) {
|
||||
.freestanding => "unknown",
|
||||
.ananas => "ananas",
|
||||
.cloudabi => "cloudabi",
|
||||
.dragonfly => "dragonfly",
|
||||
.freebsd => "freebsd",
|
||||
.fuchsia => "fuchsia",
|
||||
.ios => "ios",
|
||||
.kfreebsd => "kfreebsd",
|
||||
.linux => "linux",
|
||||
.lv2 => "lv2",
|
||||
.macos => "macosx",
|
||||
.netbsd => "netbsd",
|
||||
.openbsd => "openbsd",
|
||||
.solaris => "solaris",
|
||||
.windows => "windows",
|
||||
.haiku => "haiku",
|
||||
.minix => "minix",
|
||||
.rtems => "rtems",
|
||||
.nacl => "nacl",
|
||||
.cnk => "cnk",
|
||||
.aix => "aix",
|
||||
.cuda => "cuda",
|
||||
.nvcl => "nvcl",
|
||||
.amdhsa => "amdhsa",
|
||||
.ps4 => "ps4",
|
||||
.elfiamcu => "elfiamcu",
|
||||
.tvos => "tvos",
|
||||
.watchos => "watchos",
|
||||
.mesa3d => "mesa3d",
|
||||
.contiki => "contiki",
|
||||
.amdpal => "amdpal",
|
||||
.hermit => "hermit",
|
||||
.hurd => "hurd",
|
||||
.wasi => "wasi",
|
||||
.emscripten => "emscripten",
|
||||
.uefi => "windows",
|
||||
.other => "unknown",
|
||||
};
|
||||
|
||||
const llvm_abi = switch (target.abi) {
|
||||
.none => "unknown",
|
||||
.gnu => "gnu",
|
||||
.gnuabin32 => "gnuabin32",
|
||||
.gnuabi64 => "gnuabi64",
|
||||
.gnueabi => "gnueabi",
|
||||
.gnueabihf => "gnueabihf",
|
||||
.gnux32 => "gnux32",
|
||||
.code16 => "code16",
|
||||
.eabi => "eabi",
|
||||
.eabihf => "eabihf",
|
||||
.android => "android",
|
||||
.musl => "musl",
|
||||
.musleabi => "musleabi",
|
||||
.musleabihf => "musleabihf",
|
||||
.msvc => "msvc",
|
||||
.itanium => "itanium",
|
||||
.cygnus => "cygnus",
|
||||
.coreclr => "coreclr",
|
||||
.simulator => "simulator",
|
||||
.macabi => "macabi",
|
||||
};
|
||||
|
||||
return std.fmt.allocPrintZ(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi });
|
||||
}
|
||||
|
||||
pub const LLVMIRModule = struct {
|
||||
module: *Module,
|
||||
llvm_module: *const llvm.ModuleRef,
|
||||
target_machine: *const llvm.TargetMachineRef,
|
||||
builder: *const llvm.BuilderRef,
|
||||
|
||||
output_path: []const u8,
|
||||
|
||||
gpa: *Allocator,
|
||||
err_msg: ?*Compilation.ErrorMsg = null,
|
||||
|
||||
pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule {
|
||||
const self = try allocator.create(LLVMIRModule);
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
const gpa = options.module.?.gpa;
|
||||
|
||||
initializeLLVMTargets();
|
||||
|
||||
const root_nameZ = try gpa.dupeZ(u8, options.root_name);
|
||||
defer gpa.free(root_nameZ);
|
||||
const llvm_module = llvm.ModuleRef.createWithName(root_nameZ.ptr);
|
||||
errdefer llvm_module.disposeModule();
|
||||
|
||||
const llvm_target_triple = try targetTriple(gpa, options.target);
|
||||
defer gpa.free(llvm_target_triple);
|
||||
|
||||
var error_message: [*:0]const u8 = undefined;
|
||||
var target_ref: *const llvm.TargetRef = undefined;
|
||||
if (llvm.TargetRef.getTargetFromTriple(llvm_target_triple.ptr, &target_ref, &error_message)) {
|
||||
defer llvm.disposeMessage(error_message);
|
||||
|
||||
const stderr = std.io.getStdErr().outStream();
|
||||
try stderr.print(
|
||||
\\Zig is expecting LLVM to understand this target: '{s}'
|
||||
\\However LLVM responded with: "{s}"
|
||||
\\Zig is unable to continue. This is a bug in Zig:
|
||||
\\https://github.com/ziglang/zig/issues/438
|
||||
\\
|
||||
,
|
||||
.{
|
||||
llvm_target_triple,
|
||||
error_message,
|
||||
},
|
||||
);
|
||||
return error.InvalidLLVMTriple;
|
||||
}
|
||||
|
||||
const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) .None else .Aggressive;
|
||||
const target_machine = llvm.TargetMachineRef.createTargetMachine(
|
||||
target_ref,
|
||||
llvm_target_triple.ptr,
|
||||
"",
|
||||
"",
|
||||
opt_level,
|
||||
.Static,
|
||||
.Default,
|
||||
);
|
||||
errdefer target_machine.disposeTargetMachine();
|
||||
|
||||
const builder = llvm.BuilderRef.createBuilder();
|
||||
errdefer builder.disposeBuilder();
|
||||
|
||||
self.* = .{
|
||||
.module = options.module.?,
|
||||
.llvm_module = llvm_module,
|
||||
.target_machine = target_machine,
|
||||
.builder = builder,
|
||||
.output_path = sub_path,
|
||||
.gpa = gpa,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *LLVMIRModule, allocator: *Allocator) void {
|
||||
self.builder.disposeBuilder();
|
||||
self.target_machine.disposeTargetMachine();
|
||||
self.llvm_module.disposeModule();
|
||||
allocator.destroy(self);
|
||||
}
|
||||
|
||||
fn initializeLLVMTargets() void {
|
||||
llvm.initializeAllTargets();
|
||||
llvm.initializeAllTargetInfos();
|
||||
llvm.initializeAllTargetMCs();
|
||||
llvm.initializeAllAsmPrinters();
|
||||
llvm.initializeAllAsmParsers();
|
||||
}
|
||||
|
||||
pub fn flushModule(self: *LLVMIRModule, comp: *Compilation) !void {
|
||||
if (comp.verbose_llvm_ir) {
|
||||
const dump = self.llvm_module.printToString();
|
||||
defer llvm.disposeMessage(dump);
|
||||
|
||||
const stderr = std.io.getStdErr().outStream();
|
||||
try stderr.writeAll(std.mem.spanZ(dump));
|
||||
}
|
||||
|
||||
{
|
||||
var error_message: [*:0]const u8 = undefined;
|
||||
// verifyModule always allocs the error_message even if there is no error
|
||||
defer llvm.disposeMessage(error_message);
|
||||
|
||||
if (self.llvm_module.verifyModule(.ReturnStatus, &error_message)) {
|
||||
const stderr = std.io.getStdErr().outStream();
|
||||
try stderr.print("broken LLVM module found: {s}\nThis is a bug in the Zig compiler.", .{error_message});
|
||||
return error.BrokenLLVMModule;
|
||||
}
|
||||
}
|
||||
|
||||
const output_pathZ = try self.gpa.dupeZ(u8, self.output_path);
|
||||
defer self.gpa.free(output_pathZ);
|
||||
|
||||
var error_message: [*:0]const u8 = undefined;
|
||||
// TODO: where to put the output object, zig-cache something?
|
||||
// TODO: caching?
|
||||
if (self.target_machine.emitToFile(
|
||||
self.llvm_module,
|
||||
output_pathZ.ptr,
|
||||
.ObjectFile,
|
||||
&error_message,
|
||||
)) {
|
||||
defer llvm.disposeMessage(error_message);
|
||||
|
||||
const stderr = std.io.getStdErr().outStream();
|
||||
try stderr.print("LLVM failed to emit file: {s}\n", .{error_message});
|
||||
return error.FailedToEmit;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateDecl(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void {
|
||||
const typed_value = decl.typed_value.most_recent.typed_value;
|
||||
self.gen(module, typed_value, decl.src()) catch |err| switch (err) {
|
||||
error.CodegenFail => {
|
||||
decl.analysis = .codegen_failure;
|
||||
try module.failed_decls.put(module.gpa, decl, self.err_msg.?);
|
||||
return;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
fn gen(self: *LLVMIRModule, module: *Module, typed_value: TypedValue, src: usize) !void {
|
||||
switch (typed_value.ty.zigTypeTag()) {
|
||||
.Fn => {
|
||||
const func = typed_value.val.cast(Value.Payload.Function).?.func;
|
||||
|
||||
const llvm_func = try self.resolveLLVMFunction(func);
|
||||
|
||||
// We remove all the basic blocks of a function to support incremental
|
||||
// compilation!
|
||||
// TODO: remove all basic blocks if functions can have more than one
|
||||
if (llvm_func.getFirstBasicBlock()) |bb| {
|
||||
bb.deleteBasicBlock();
|
||||
}
|
||||
|
||||
const entry_block = llvm_func.appendBasicBlock("Entry");
|
||||
self.builder.positionBuilderAtEnd(entry_block);
|
||||
|
||||
const instructions = func.analysis.success.instructions;
|
||||
for (instructions) |inst| {
|
||||
switch (inst.tag) {
|
||||
.breakpoint => try self.genBreakpoint(inst.castTag(.breakpoint).?),
|
||||
.call => try self.genCall(inst.castTag(.call).?),
|
||||
.unreach => self.genUnreach(inst.castTag(.unreach).?),
|
||||
.retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
|
||||
.arg => self.genArg(inst.castTag(.arg).?),
|
||||
.dbg_stmt => {
|
||||
// TODO: implement debug info
|
||||
},
|
||||
else => |tag| return self.fail(src, "TODO implement LLVM codegen for Zir instruction: {}", .{tag}),
|
||||
}
|
||||
}
|
||||
},
|
||||
else => |ty| return self.fail(src, "TODO implement LLVM codegen for top-level decl type: {}", .{ty}),
|
||||
}
|
||||
}
|
||||
|
||||
fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !void {
|
||||
if (inst.func.cast(Inst.Constant)) |func_inst| {
|
||||
if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
|
||||
const func = func_val.func;
|
||||
const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;
|
||||
const llvm_fn = try self.resolveLLVMFunction(func);
|
||||
|
||||
const num_args = inst.args.len;
|
||||
|
||||
const llvm_param_vals = try self.gpa.alloc(*const llvm.ValueRef, num_args);
|
||||
defer self.gpa.free(llvm_param_vals);
|
||||
|
||||
for (inst.args) |arg, i| {
|
||||
llvm_param_vals[i] = try self.resolveInst(arg);
|
||||
}
|
||||
|
||||
// TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs
|
||||
// Do we need that?
|
||||
const call = self.builder.buildCall(
|
||||
llvm_fn,
|
||||
if (num_args == 0) null else llvm_param_vals.ptr,
|
||||
@intCast(c_uint, num_args),
|
||||
"",
|
||||
);
|
||||
|
||||
if (zig_fn_type.fnReturnType().zigTypeTag() == .NoReturn) {
|
||||
_ = self.builder.buildUnreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn genRetVoid(self: *LLVMIRModule, inst: *Inst.NoOp) void {
|
||||
_ = self.builder.buildRetVoid();
|
||||
}
|
||||
|
||||
fn genUnreach(self: *LLVMIRModule, inst: *Inst.NoOp) void {
|
||||
_ = self.builder.buildUnreachable();
|
||||
}
|
||||
|
||||
fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) void {
|
||||
// TODO: implement this
|
||||
}
|
||||
|
||||
fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !void {
|
||||
// TODO: Store this function somewhere such that we dont have to add it again
|
||||
const fn_type = llvm.TypeRef.functionType(llvm.voidType(), null, 0, false);
|
||||
const func = self.llvm_module.addFunction("llvm.debugtrap", fn_type);
|
||||
// TODO: add assertion: LLVMGetIntrinsicID
|
||||
_ = self.builder.buildCall(func, null, 0, "");
|
||||
}
|
||||
|
||||
fn resolveInst(self: *LLVMIRModule, inst: *ir.Inst) !*const llvm.ValueRef {
|
||||
if (inst.castTag(.constant)) |const_inst| {
|
||||
return self.genTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val });
|
||||
}
|
||||
return self.fail(inst.src, "TODO implement resolveInst", .{});
|
||||
}
|
||||
|
||||
fn genTypedValue(self: *LLVMIRModule, src: usize, typed_value: TypedValue) !*const llvm.ValueRef {
|
||||
const llvm_type = self.getLLVMType(typed_value.ty);
|
||||
|
||||
if (typed_value.val.isUndef())
|
||||
return llvm_type.getUndef();
|
||||
|
||||
switch (typed_value.ty.zigTypeTag()) {
|
||||
.Bool => return if (typed_value.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(),
|
||||
else => return self.fail(src, "TODO implement const of type '{}'", .{typed_value.ty}),
|
||||
}
|
||||
}
|
||||
|
||||
/// If the llvm function does not exist, create it
|
||||
fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Fn) !*const llvm.ValueRef {
|
||||
// TODO: do we want to store this in our own datastructure?
|
||||
if (self.llvm_module.getNamedFunction(func.owner_decl.name)) |llvm_fn| return llvm_fn;
|
||||
|
||||
const zig_fn_type = func.owner_decl.typed_value.most_recent.typed_value.ty;
|
||||
const return_type = zig_fn_type.fnReturnType();
|
||||
|
||||
const fn_param_len = zig_fn_type.fnParamLen();
|
||||
|
||||
const fn_param_types = try self.gpa.alloc(Type, fn_param_len);
|
||||
defer self.gpa.free(fn_param_types);
|
||||
zig_fn_type.fnParamTypes(fn_param_types);
|
||||
|
||||
const llvm_param = try self.gpa.alloc(*const llvm.TypeRef, fn_param_len);
|
||||
defer self.gpa.free(llvm_param);
|
||||
|
||||
for (fn_param_types) |fn_param, i| {
|
||||
llvm_param[i] = self.getLLVMType(fn_param);
|
||||
}
|
||||
|
||||
const fn_type = llvm.TypeRef.functionType(
|
||||
self.getLLVMType(return_type),
|
||||
if (fn_param_len == 0) null else llvm_param.ptr,
|
||||
@intCast(c_uint, fn_param_len),
|
||||
false,
|
||||
);
|
||||
const llvm_fn = self.llvm_module.addFunction(func.owner_decl.name, fn_type);
|
||||
|
||||
if (return_type.zigTypeTag() == .NoReturn) {
|
||||
llvm_fn.addFnAttr("noreturn");
|
||||
}
|
||||
|
||||
return llvm_fn;
|
||||
}
|
||||
|
||||
fn getLLVMType(self: *LLVMIRModule, t: Type) *const llvm.TypeRef {
|
||||
switch (t.zigTypeTag()) {
|
||||
.Void => return llvm.voidType(),
|
||||
.NoReturn => return llvm.voidType(),
|
||||
.Int => {
|
||||
const info = t.intInfo(self.module.getTarget());
|
||||
return llvm.intType(info.bits);
|
||||
},
|
||||
.Bool => return llvm.intType(1),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
|
||||
@setCold(true);
|
||||
std.debug.assert(self.err_msg == null);
|
||||
self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args);
|
||||
return error.CodegenFail;
|
||||
}
|
||||
};
|
||||
507
src/llvm_bindings.zig
Normal file
507
src/llvm_bindings.zig
Normal file
@ -0,0 +1,507 @@
|
||||
//! We do this instead of @cImport because the self-hosted compiler is easier
|
||||
//! to bootstrap if it does not depend on translate-c.
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const LLVMBool = bool;
|
||||
pub const LLVMAttributeIndex = c_uint;
|
||||
|
||||
pub const ValueRef = opaque {
|
||||
pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
|
||||
extern fn LLVMAddAttributeAtIndex(*const ValueRef, Idx: LLVMAttributeIndex, A: *const AttributeRef) void;
|
||||
|
||||
pub const appendBasicBlock = LLVMAppendBasicBlock;
|
||||
extern fn LLVMAppendBasicBlock(Fn: *const ValueRef, Name: [*:0]const u8) *const BasicBlockRef;
|
||||
|
||||
pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
|
||||
extern fn LLVMGetFirstBasicBlock(Fn: *const ValueRef) ?*const BasicBlockRef;
|
||||
|
||||
// Helper functions
|
||||
// TODO: Do we want to put these functions here? It allows for convienient function calls
|
||||
// on ValueRef: llvm_fn.addFnAttr("noreturn")
|
||||
fn addAttr(val: *const ValueRef, index: LLVMAttributeIndex, name: []const u8) void {
|
||||
const kind_id = getEnumAttributeKindForName(name.ptr, name.len);
|
||||
assert(kind_id != 0);
|
||||
const llvm_attr = ContextRef.getGlobal().createEnumAttribute(kind_id, 0);
|
||||
val.addAttributeAtIndex(index, llvm_attr);
|
||||
}
|
||||
|
||||
pub fn addFnAttr(val: *const ValueRef, attr_name: []const u8) void {
|
||||
// TODO: improve this API, `addAttr(-1, attr_name)`
|
||||
val.addAttr(std.math.maxInt(LLVMAttributeIndex), attr_name);
|
||||
}
|
||||
};
|
||||
|
||||
pub const TypeRef = opaque {
|
||||
pub const functionType = LLVMFunctionType;
|
||||
extern fn LLVMFunctionType(ReturnType: *const TypeRef, ParamTypes: ?[*]*const TypeRef, ParamCount: c_uint, IsVarArg: LLVMBool) *const TypeRef;
|
||||
|
||||
pub const constNull = LLVMConstNull;
|
||||
extern fn LLVMConstNull(Ty: *const TypeRef) *const ValueRef;
|
||||
|
||||
pub const constAllOnes = LLVMConstAllOnes;
|
||||
extern fn LLVMConstAllOnes(Ty: *const TypeRef) *const ValueRef;
|
||||
|
||||
pub const getUndef = LLVMGetUndef;
|
||||
extern fn LLVMGetUndef(Ty: *const TypeRef) *const ValueRef;
|
||||
};
|
||||
|
||||
pub const ModuleRef = opaque {
|
||||
pub const createWithName = LLVMModuleCreateWithName;
|
||||
extern fn LLVMModuleCreateWithName(ModuleID: [*:0]const u8) *const ModuleRef;
|
||||
|
||||
pub const disposeModule = LLVMDisposeModule;
|
||||
extern fn LLVMDisposeModule(*const ModuleRef) void;
|
||||
|
||||
pub const verifyModule = LLVMVerifyModule;
|
||||
extern fn LLVMVerifyModule(*const ModuleRef, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) LLVMBool;
|
||||
|
||||
pub const addFunction = LLVMAddFunction;
|
||||
extern fn LLVMAddFunction(*const ModuleRef, Name: [*:0]const u8, FunctionTy: *const TypeRef) *const ValueRef;
|
||||
|
||||
pub const getNamedFunction = LLVMGetNamedFunction;
|
||||
extern fn LLVMGetNamedFunction(*const ModuleRef, Name: [*:0]const u8) ?*const ValueRef;
|
||||
|
||||
pub const printToString = LLVMPrintModuleToString;
|
||||
extern fn LLVMPrintModuleToString(*const ModuleRef) [*:0]const u8;
|
||||
};
|
||||
|
||||
pub const disposeMessage = LLVMDisposeMessage;
|
||||
extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
|
||||
|
||||
pub const VerifierFailureAction = extern enum {
|
||||
AbortProcess,
|
||||
PrintMessage,
|
||||
ReturnStatus,
|
||||
};
|
||||
|
||||
pub const voidType = LLVMVoidType;
|
||||
extern fn LLVMVoidType() *const TypeRef;
|
||||
|
||||
pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
|
||||
extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
|
||||
|
||||
pub const AttributeRef = opaque {};
|
||||
|
||||
pub const ContextRef = opaque {
|
||||
pub const createEnumAttribute = LLVMCreateEnumAttribute;
|
||||
extern fn LLVMCreateEnumAttribute(*const ContextRef, KindID: c_uint, Val: u64) *const AttributeRef;
|
||||
|
||||
pub const getGlobal = LLVMGetGlobalContext;
|
||||
extern fn LLVMGetGlobalContext() *const ContextRef;
|
||||
};
|
||||
|
||||
pub const intType = LLVMIntType;
|
||||
extern fn LLVMIntType(NumBits: c_uint) *const TypeRef;
|
||||
|
||||
pub const BuilderRef = opaque {
|
||||
pub const createBuilder = LLVMCreateBuilder;
|
||||
extern fn LLVMCreateBuilder() *const BuilderRef;
|
||||
|
||||
pub const disposeBuilder = LLVMDisposeBuilder;
|
||||
extern fn LLVMDisposeBuilder(Builder: *const BuilderRef) void;
|
||||
|
||||
pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd;
|
||||
extern fn LLVMPositionBuilderAtEnd(Builder: *const BuilderRef, Block: *const BasicBlockRef) void;
|
||||
|
||||
pub const getInsertBlock = LLVMGetInsertBlock;
|
||||
extern fn LLVMGetInsertBlock(Builder: *const BuilderRef) *const BasicBlockRef;
|
||||
|
||||
pub const buildCall = LLVMBuildCall;
|
||||
extern fn LLVMBuildCall(*const BuilderRef, Fn: *const ValueRef, Args: ?[*]*const ValueRef, NumArgs: c_uint, Name: [*:0]const u8) *const ValueRef;
|
||||
|
||||
pub const buildCall2 = LLVMBuildCall2;
|
||||
extern fn LLVMBuildCall2(*const BuilderRef, *const TypeRef, Fn: *const ValueRef, Args: [*]*const ValueRef, NumArgs: c_uint, Name: [*:0]const u8) *const ValueRef;
|
||||
|
||||
pub const buildRetVoid = LLVMBuildRetVoid;
|
||||
extern fn LLVMBuildRetVoid(*const BuilderRef) *const ValueRef;
|
||||
|
||||
pub const buildUnreachable = LLVMBuildUnreachable;
|
||||
extern fn LLVMBuildUnreachable(*const BuilderRef) *const ValueRef;
|
||||
|
||||
pub const buildAlloca = LLVMBuildAlloca;
|
||||
extern fn LLVMBuildAlloca(*const BuilderRef, Ty: *const TypeRef, Name: [*:0]const u8) *const ValueRef;
|
||||
};
|
||||
|
||||
pub const BasicBlockRef = opaque {
|
||||
pub const deleteBasicBlock = LLVMDeleteBasicBlock;
|
||||
extern fn LLVMDeleteBasicBlock(BB: *const BasicBlockRef) void;
|
||||
};
|
||||
|
||||
pub const TargetMachineRef = opaque {
|
||||
pub const createTargetMachine = LLVMCreateTargetMachine;
|
||||
extern fn LLVMCreateTargetMachine(
|
||||
T: *const TargetRef,
|
||||
Triple: [*:0]const u8,
|
||||
CPU: [*:0]const u8,
|
||||
Features: [*:0]const u8,
|
||||
Level: CodeGenOptLevel,
|
||||
Reloc: RelocMode,
|
||||
CodeModel: CodeMode,
|
||||
) *const TargetMachineRef;
|
||||
|
||||
pub const disposeTargetMachine = LLVMDisposeTargetMachine;
|
||||
extern fn LLVMDisposeTargetMachine(T: *const TargetMachineRef) void;
|
||||
|
||||
pub const emitToFile = LLVMTargetMachineEmitToFile;
|
||||
extern fn LLVMTargetMachineEmitToFile(*const TargetMachineRef, M: *const ModuleRef, Filename: [*:0]const u8, codegen: CodeGenFileType, ErrorMessage: *[*:0]const u8) LLVMBool;
|
||||
};
|
||||
|
||||
pub const CodeMode = extern enum {
|
||||
Default,
|
||||
JITDefault,
|
||||
Tiny,
|
||||
Small,
|
||||
Kernel,
|
||||
Medium,
|
||||
Large,
|
||||
};
|
||||
|
||||
pub const CodeGenOptLevel = extern enum {
|
||||
None,
|
||||
Less,
|
||||
Default,
|
||||
Aggressive,
|
||||
};
|
||||
|
||||
pub const RelocMode = extern enum {
|
||||
Default,
|
||||
Static,
|
||||
PIC,
|
||||
DynamicNoPic,
|
||||
ROPI,
|
||||
RWPI,
|
||||
ROPI_RWPI,
|
||||
};
|
||||
|
||||
pub const CodeGenFileType = extern enum {
|
||||
AssemblyFile,
|
||||
ObjectFile,
|
||||
};
|
||||
|
||||
pub const TargetRef = opaque {
|
||||
pub const getTargetFromTriple = LLVMGetTargetFromTriple;
|
||||
extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const TargetRef, ErrorMessage: *[*:0]const u8) LLVMBool;
|
||||
};
|
||||
|
||||
extern fn LLVMInitializeAArch64TargetInfo() void;
|
||||
extern fn LLVMInitializeAMDGPUTargetInfo() void;
|
||||
extern fn LLVMInitializeARMTargetInfo() void;
|
||||
extern fn LLVMInitializeAVRTargetInfo() void;
|
||||
extern fn LLVMInitializeBPFTargetInfo() void;
|
||||
extern fn LLVMInitializeHexagonTargetInfo() void;
|
||||
extern fn LLVMInitializeLanaiTargetInfo() void;
|
||||
extern fn LLVMInitializeMipsTargetInfo() void;
|
||||
extern fn LLVMInitializeMSP430TargetInfo() void;
|
||||
extern fn LLVMInitializeNVPTXTargetInfo() void;
|
||||
extern fn LLVMInitializePowerPCTargetInfo() void;
|
||||
extern fn LLVMInitializeRISCVTargetInfo() void;
|
||||
extern fn LLVMInitializeSparcTargetInfo() void;
|
||||
extern fn LLVMInitializeSystemZTargetInfo() void;
|
||||
extern fn LLVMInitializeWebAssemblyTargetInfo() void;
|
||||
extern fn LLVMInitializeX86TargetInfo() void;
|
||||
extern fn LLVMInitializeXCoreTargetInfo() void;
|
||||
extern fn LLVMInitializeAArch64Target() void;
|
||||
extern fn LLVMInitializeAMDGPUTarget() void;
|
||||
extern fn LLVMInitializeARMTarget() void;
|
||||
extern fn LLVMInitializeAVRTarget() void;
|
||||
extern fn LLVMInitializeBPFTarget() void;
|
||||
extern fn LLVMInitializeHexagonTarget() void;
|
||||
extern fn LLVMInitializeLanaiTarget() void;
|
||||
extern fn LLVMInitializeMipsTarget() void;
|
||||
extern fn LLVMInitializeMSP430Target() void;
|
||||
extern fn LLVMInitializeNVPTXTarget() void;
|
||||
extern fn LLVMInitializePowerPCTarget() void;
|
||||
extern fn LLVMInitializeRISCVTarget() void;
|
||||
extern fn LLVMInitializeSparcTarget() void;
|
||||
extern fn LLVMInitializeSystemZTarget() void;
|
||||
extern fn LLVMInitializeWebAssemblyTarget() void;
|
||||
extern fn LLVMInitializeX86Target() void;
|
||||
extern fn LLVMInitializeXCoreTarget() void;
|
||||
extern fn LLVMInitializeAArch64TargetMC() void;
|
||||
extern fn LLVMInitializeAMDGPUTargetMC() void;
|
||||
extern fn LLVMInitializeARMTargetMC() void;
|
||||
extern fn LLVMInitializeAVRTargetMC() void;
|
||||
extern fn LLVMInitializeBPFTargetMC() void;
|
||||
extern fn LLVMInitializeHexagonTargetMC() void;
|
||||
extern fn LLVMInitializeLanaiTargetMC() void;
|
||||
extern fn LLVMInitializeMipsTargetMC() void;
|
||||
extern fn LLVMInitializeMSP430TargetMC() void;
|
||||
extern fn LLVMInitializeNVPTXTargetMC() void;
|
||||
extern fn LLVMInitializePowerPCTargetMC() void;
|
||||
extern fn LLVMInitializeRISCVTargetMC() void;
|
||||
extern fn LLVMInitializeSparcTargetMC() void;
|
||||
extern fn LLVMInitializeSystemZTargetMC() void;
|
||||
extern fn LLVMInitializeWebAssemblyTargetMC() void;
|
||||
extern fn LLVMInitializeX86TargetMC() void;
|
||||
extern fn LLVMInitializeXCoreTargetMC() void;
|
||||
extern fn LLVMInitializeAArch64AsmPrinter() void;
|
||||
extern fn LLVMInitializeAMDGPUAsmPrinter() void;
|
||||
extern fn LLVMInitializeARMAsmPrinter() void;
|
||||
extern fn LLVMInitializeAVRAsmPrinter() void;
|
||||
extern fn LLVMInitializeBPFAsmPrinter() void;
|
||||
extern fn LLVMInitializeHexagonAsmPrinter() void;
|
||||
extern fn LLVMInitializeLanaiAsmPrinter() void;
|
||||
extern fn LLVMInitializeMipsAsmPrinter() void;
|
||||
extern fn LLVMInitializeMSP430AsmPrinter() void;
|
||||
extern fn LLVMInitializeNVPTXAsmPrinter() void;
|
||||
extern fn LLVMInitializePowerPCAsmPrinter() void;
|
||||
extern fn LLVMInitializeRISCVAsmPrinter() void;
|
||||
extern fn LLVMInitializeSparcAsmPrinter() void;
|
||||
extern fn LLVMInitializeSystemZAsmPrinter() void;
|
||||
extern fn LLVMInitializeWebAssemblyAsmPrinter() void;
|
||||
extern fn LLVMInitializeX86AsmPrinter() void;
|
||||
extern fn LLVMInitializeXCoreAsmPrinter() void;
|
||||
extern fn LLVMInitializeAArch64AsmParser() void;
|
||||
extern fn LLVMInitializeAMDGPUAsmParser() void;
|
||||
extern fn LLVMInitializeARMAsmParser() void;
|
||||
extern fn LLVMInitializeAVRAsmParser() void;
|
||||
extern fn LLVMInitializeBPFAsmParser() void;
|
||||
extern fn LLVMInitializeHexagonAsmParser() void;
|
||||
extern fn LLVMInitializeLanaiAsmParser() void;
|
||||
extern fn LLVMInitializeMipsAsmParser() void;
|
||||
extern fn LLVMInitializeMSP430AsmParser() void;
|
||||
extern fn LLVMInitializePowerPCAsmParser() void;
|
||||
extern fn LLVMInitializeRISCVAsmParser() void;
|
||||
extern fn LLVMInitializeSparcAsmParser() void;
|
||||
extern fn LLVMInitializeSystemZAsmParser() void;
|
||||
extern fn LLVMInitializeWebAssemblyAsmParser() void;
|
||||
extern fn LLVMInitializeX86AsmParser() void;
|
||||
|
||||
pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos;
|
||||
fn LLVMInitializeAllTargetInfos() callconv(.C) void {
|
||||
LLVMInitializeAArch64TargetInfo();
|
||||
LLVMInitializeAMDGPUTargetInfo();
|
||||
LLVMInitializeARMTargetInfo();
|
||||
LLVMInitializeAVRTargetInfo();
|
||||
LLVMInitializeBPFTargetInfo();
|
||||
LLVMInitializeHexagonTargetInfo();
|
||||
LLVMInitializeLanaiTargetInfo();
|
||||
LLVMInitializeMipsTargetInfo();
|
||||
LLVMInitializeMSP430TargetInfo();
|
||||
LLVMInitializeNVPTXTargetInfo();
|
||||
LLVMInitializePowerPCTargetInfo();
|
||||
LLVMInitializeRISCVTargetInfo();
|
||||
LLVMInitializeSparcTargetInfo();
|
||||
LLVMInitializeSystemZTargetInfo();
|
||||
LLVMInitializeWebAssemblyTargetInfo();
|
||||
LLVMInitializeX86TargetInfo();
|
||||
LLVMInitializeXCoreTargetInfo();
|
||||
}
|
||||
pub const initializeAllTargets = LLVMInitializeAllTargets;
|
||||
fn LLVMInitializeAllTargets() callconv(.C) void {
|
||||
LLVMInitializeAArch64Target();
|
||||
LLVMInitializeAMDGPUTarget();
|
||||
LLVMInitializeARMTarget();
|
||||
LLVMInitializeAVRTarget();
|
||||
LLVMInitializeBPFTarget();
|
||||
LLVMInitializeHexagonTarget();
|
||||
LLVMInitializeLanaiTarget();
|
||||
LLVMInitializeMipsTarget();
|
||||
LLVMInitializeMSP430Target();
|
||||
LLVMInitializeNVPTXTarget();
|
||||
LLVMInitializePowerPCTarget();
|
||||
LLVMInitializeRISCVTarget();
|
||||
LLVMInitializeSparcTarget();
|
||||
LLVMInitializeSystemZTarget();
|
||||
LLVMInitializeWebAssemblyTarget();
|
||||
LLVMInitializeX86Target();
|
||||
LLVMInitializeXCoreTarget();
|
||||
}
|
||||
pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs;
|
||||
fn LLVMInitializeAllTargetMCs() callconv(.C) void {
|
||||
LLVMInitializeAArch64TargetMC();
|
||||
LLVMInitializeAMDGPUTargetMC();
|
||||
LLVMInitializeARMTargetMC();
|
||||
LLVMInitializeAVRTargetMC();
|
||||
LLVMInitializeBPFTargetMC();
|
||||
LLVMInitializeHexagonTargetMC();
|
||||
LLVMInitializeLanaiTargetMC();
|
||||
LLVMInitializeMipsTargetMC();
|
||||
LLVMInitializeMSP430TargetMC();
|
||||
LLVMInitializeNVPTXTargetMC();
|
||||
LLVMInitializePowerPCTargetMC();
|
||||
LLVMInitializeRISCVTargetMC();
|
||||
LLVMInitializeSparcTargetMC();
|
||||
LLVMInitializeSystemZTargetMC();
|
||||
LLVMInitializeWebAssemblyTargetMC();
|
||||
LLVMInitializeX86TargetMC();
|
||||
LLVMInitializeXCoreTargetMC();
|
||||
}
|
||||
pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters;
|
||||
fn LLVMInitializeAllAsmPrinters() callconv(.C) void {
|
||||
LLVMInitializeAArch64AsmPrinter();
|
||||
LLVMInitializeAMDGPUAsmPrinter();
|
||||
LLVMInitializeARMAsmPrinter();
|
||||
LLVMInitializeAVRAsmPrinter();
|
||||
LLVMInitializeBPFAsmPrinter();
|
||||
LLVMInitializeHexagonAsmPrinter();
|
||||
LLVMInitializeLanaiAsmPrinter();
|
||||
LLVMInitializeMipsAsmPrinter();
|
||||
LLVMInitializeMSP430AsmPrinter();
|
||||
LLVMInitializeNVPTXAsmPrinter();
|
||||
LLVMInitializePowerPCAsmPrinter();
|
||||
LLVMInitializeRISCVAsmPrinter();
|
||||
LLVMInitializeSparcAsmPrinter();
|
||||
LLVMInitializeSystemZAsmPrinter();
|
||||
LLVMInitializeWebAssemblyAsmPrinter();
|
||||
LLVMInitializeX86AsmPrinter();
|
||||
LLVMInitializeXCoreAsmPrinter();
|
||||
}
|
||||
pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers;
|
||||
fn LLVMInitializeAllAsmParsers() callconv(.C) void {
|
||||
LLVMInitializeAArch64AsmParser();
|
||||
LLVMInitializeAMDGPUAsmParser();
|
||||
LLVMInitializeARMAsmParser();
|
||||
LLVMInitializeAVRAsmParser();
|
||||
LLVMInitializeBPFAsmParser();
|
||||
LLVMInitializeHexagonAsmParser();
|
||||
LLVMInitializeLanaiAsmParser();
|
||||
LLVMInitializeMipsAsmParser();
|
||||
LLVMInitializeMSP430AsmParser();
|
||||
LLVMInitializePowerPCAsmParser();
|
||||
LLVMInitializeRISCVAsmParser();
|
||||
LLVMInitializeSparcAsmParser();
|
||||
LLVMInitializeSystemZAsmParser();
|
||||
LLVMInitializeWebAssemblyAsmParser();
|
||||
LLVMInitializeX86AsmParser();
|
||||
}
|
||||
|
||||
extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
|
||||
|
||||
pub const LinkCOFF = ZigLLDLinkCOFF;
|
||||
pub const LinkELF = ZigLLDLinkELF;
|
||||
pub const LinkMachO = ZigLLDLinkMachO;
|
||||
pub const LinkWasm = ZigLLDLinkWasm;
|
||||
|
||||
pub const ObjectFormatType = extern enum(c_int) {
|
||||
Unknown,
|
||||
COFF,
|
||||
ELF,
|
||||
MachO,
|
||||
Wasm,
|
||||
XCOFF,
|
||||
};
|
||||
|
||||
pub const GetHostCPUName = LLVMGetHostCPUName;
|
||||
extern fn LLVMGetHostCPUName() ?[*:0]u8;
|
||||
|
||||
pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
|
||||
extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
|
||||
|
||||
pub const WriteArchive = ZigLLVMWriteArchive;
|
||||
extern fn ZigLLVMWriteArchive(
|
||||
archive_name: [*:0]const u8,
|
||||
file_names_ptr: [*]const [*:0]const u8,
|
||||
file_names_len: usize,
|
||||
os_type: OSType,
|
||||
) bool;
|
||||
|
||||
pub const OSType = extern enum(c_int) {
|
||||
UnknownOS = 0,
|
||||
Ananas = 1,
|
||||
CloudABI = 2,
|
||||
Darwin = 3,
|
||||
DragonFly = 4,
|
||||
FreeBSD = 5,
|
||||
Fuchsia = 6,
|
||||
IOS = 7,
|
||||
KFreeBSD = 8,
|
||||
Linux = 9,
|
||||
Lv2 = 10,
|
||||
MacOSX = 11,
|
||||
NetBSD = 12,
|
||||
OpenBSD = 13,
|
||||
Solaris = 14,
|
||||
Win32 = 15,
|
||||
Haiku = 16,
|
||||
Minix = 17,
|
||||
RTEMS = 18,
|
||||
NaCl = 19,
|
||||
CNK = 20,
|
||||
AIX = 21,
|
||||
CUDA = 22,
|
||||
NVCL = 23,
|
||||
AMDHSA = 24,
|
||||
PS4 = 25,
|
||||
ELFIAMCU = 26,
|
||||
TvOS = 27,
|
||||
WatchOS = 28,
|
||||
Mesa3D = 29,
|
||||
Contiki = 30,
|
||||
AMDPAL = 31,
|
||||
HermitCore = 32,
|
||||
Hurd = 33,
|
||||
WASI = 34,
|
||||
Emscripten = 35,
|
||||
};
|
||||
|
||||
pub const ArchType = extern enum(c_int) {
|
||||
UnknownArch = 0,
|
||||
arm = 1,
|
||||
armeb = 2,
|
||||
aarch64 = 3,
|
||||
aarch64_be = 4,
|
||||
aarch64_32 = 5,
|
||||
arc = 6,
|
||||
avr = 7,
|
||||
bpfel = 8,
|
||||
bpfeb = 9,
|
||||
hexagon = 10,
|
||||
mips = 11,
|
||||
mipsel = 12,
|
||||
mips64 = 13,
|
||||
mips64el = 14,
|
||||
msp430 = 15,
|
||||
ppc = 16,
|
||||
ppc64 = 17,
|
||||
ppc64le = 18,
|
||||
r600 = 19,
|
||||
amdgcn = 20,
|
||||
riscv32 = 21,
|
||||
riscv64 = 22,
|
||||
sparc = 23,
|
||||
sparcv9 = 24,
|
||||
sparcel = 25,
|
||||
systemz = 26,
|
||||
tce = 27,
|
||||
tcele = 28,
|
||||
thumb = 29,
|
||||
thumbeb = 30,
|
||||
x86 = 31,
|
||||
x86_64 = 32,
|
||||
xcore = 33,
|
||||
nvptx = 34,
|
||||
nvptx64 = 35,
|
||||
le32 = 36,
|
||||
le64 = 37,
|
||||
amdil = 38,
|
||||
amdil64 = 39,
|
||||
hsail = 40,
|
||||
hsail64 = 41,
|
||||
spir = 42,
|
||||
spir64 = 43,
|
||||
kalimba = 44,
|
||||
shave = 45,
|
||||
lanai = 46,
|
||||
wasm32 = 47,
|
||||
wasm64 = 48,
|
||||
renderscript32 = 49,
|
||||
renderscript64 = 50,
|
||||
ve = 51,
|
||||
};
|
||||
|
||||
pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
|
||||
extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
|
||||
|
||||
pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
|
||||
extern fn ZigLLVMWriteImportLibrary(
|
||||
def_path: [*:0]const u8,
|
||||
arch: ArchType,
|
||||
output_lib_path: [*c]const u8,
|
||||
kill_at: bool,
|
||||
) bool;
|
||||
@ -1676,7 +1676,7 @@ fn buildOutputType(
|
||||
if (build_options.have_llvm and emit_asm != .no) {
|
||||
// LLVM has no way to set this non-globally.
|
||||
const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };
|
||||
@import("llvm.zig").ParseCommandLineOptions(argv.len, &argv);
|
||||
@import("llvm_bindings.zig").ParseCommandLineOptions(argv.len, &argv);
|
||||
}
|
||||
|
||||
gimmeMoreOfThoseSweetSweetFileDescriptors();
|
||||
@ -2839,7 +2839,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor
|
||||
argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.
|
||||
}
|
||||
const exit_code = rc: {
|
||||
const llvm = @import("llvm.zig");
|
||||
const llvm = @import("llvm_bindings.zig");
|
||||
const argc = @intCast(c_int, argv.len);
|
||||
if (mem.eql(u8, args[1], "ld.lld")) {
|
||||
break :rc llvm.LinkELF(argc, argv.ptr, true);
|
||||
@ -3224,7 +3224,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s
|
||||
if (!build_options.have_llvm)
|
||||
fatal("CPU features detection is not yet available for {} without LLVM extensions", .{@tagName(arch)});
|
||||
|
||||
const llvm = @import("llvm.zig");
|
||||
const llvm = @import("llvm_bindings.zig");
|
||||
const llvm_cpu_name = llvm.GetHostCPUName();
|
||||
const llvm_cpu_features = llvm.GetNativeFeatures();
|
||||
info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
|
||||
|
||||
@ -405,7 +405,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
||||
});
|
||||
errdefer comp.gpa.free(lib_final_path);
|
||||
|
||||
const llvm = @import("llvm.zig");
|
||||
const llvm = @import("llvm_bindings.zig");
|
||||
const arch_type = @import("target.zig").archToLLVM(target.cpu.arch);
|
||||
const def_final_path_z = try arena.dupeZ(u8, def_final_path);
|
||||
const lib_final_path_z = try arena.dupeZ(u8, lib_final_path);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const llvm = @import("llvm.zig");
|
||||
const llvm = @import("llvm_bindings.zig");
|
||||
|
||||
pub const ArchOsAbi = struct {
|
||||
arch: std.Target.Cpu.Arch,
|
||||
|
||||
@ -8,14 +8,32 @@
|
||||
#ifndef ZIG_ZIG_CLANG_H
|
||||
#define ZIG_ZIG_CLANG_H
|
||||
|
||||
#include "stage1/stage2.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define ZIG_EXTERN_C extern "C"
|
||||
#else
|
||||
#define ZIG_EXTERN_C
|
||||
#endif
|
||||
|
||||
// ATTENTION: If you modify this file, be sure to update the corresponding
|
||||
// extern function declarations in the self-hosted compiler file
|
||||
// src/clang.zig.
|
||||
|
||||
// ABI warning
|
||||
struct Stage2ErrorMsg {
|
||||
const char *filename_ptr; // can be null
|
||||
size_t filename_len;
|
||||
const char *msg_ptr;
|
||||
size_t msg_len;
|
||||
const char *source; // valid until the ASTUnit is freed. can be null
|
||||
unsigned line; // 0 based
|
||||
unsigned column; // 0 based
|
||||
unsigned offset; // byte offset into source
|
||||
};
|
||||
|
||||
struct ZigClangSourceLocation {
|
||||
unsigned ID;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user