Commit c6160fa3a5
Changed files (4)
src
src/codegen/llvm/bindings.zig
@@ -184,6 +184,9 @@ pub const Value = opaque {
pub const setFunctionCallConv = LLVMSetFunctionCallConv;
extern fn LLVMSetFunctionCallConv(Fn: *const Value, CC: CallConv) void;
+ pub const fnSetSubprogram = ZigLLVMFnSetSubprogram;
+ extern fn ZigLLVMFnSetSubprogram(f: *const Value, subprogram: *DISubprogram) void;
+
pub const setValueName = LLVMSetValueName;
extern fn LLVMSetValueName(Val: *const Value, Name: [*:0]const u8) void;
@@ -354,6 +357,18 @@ pub const Module = opaque {
Name: [*:0]const u8,
NameLen: usize,
) ?*const Value;
+
+ pub const setTarget = LLVMSetTarget;
+ extern fn LLVMSetTarget(M: *const Module, Triple: [*:0]const u8) void;
+
+ pub const addModuleDebugInfoFlag = ZigLLVMAddModuleDebugInfoFlag;
+ extern fn ZigLLVMAddModuleDebugInfoFlag(module: *const Module) void;
+
+ pub const addModuleCodeViewFlag = ZigLLVMAddModuleCodeViewFlag;
+ extern fn ZigLLVMAddModuleCodeViewFlag(module: *const Module) void;
+
+ pub const createDIBuilder = ZigLLVMCreateDIBuilder;
+ extern fn ZigLLVMCreateDIBuilder(module: *const Module, allow_unresolved: bool) *DIBuilder;
};
pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
@@ -1203,7 +1218,7 @@ pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
extern fn ZigLLVMWriteImportLibrary(
def_path: [*:0]const u8,
arch: ArchType,
- output_lib_path: [*c]const u8,
+ output_lib_path: [*:0]const u8,
kill_at: bool,
) bool;
@@ -1400,3 +1415,286 @@ pub const address_space = struct {
pub const constant_buffer_15: c_uint = 23;
};
};
+
+pub const DIEnumerator = opaque {};
+pub const DILocalVariable = opaque {};
+pub const DIGlobalVariable = opaque {};
+pub const DILocation = opaque {};
+
+pub const DIType = opaque {
+ pub const toScope = ZigLLVMTypeToScope;
+ extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;
+};
+pub const DIFile = opaque {
+ pub const toScope = ZigLLVMFileToScope;
+ extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;
+};
+pub const DILexicalBlock = opaque {
+ pub const toScope = ZigLLVMLexicalBlockToScope;
+ extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;
+};
+pub const DICompileUnit = opaque {
+ pub const toScope = ZigLLVMCompileUnitToScope;
+ extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;
+};
+pub const DISubprogram = opaque {
+ pub const toScope = ZigLLVMSubprogramToScope;
+ extern fn ZigLLVMSubprogramToScope(subprogram: *DISubprogram) *DIScope;
+};
+
+pub const getDebugLoc = ZigLLVMGetDebugLoc;
+extern fn ZigLLVMGetDebugLoc(line: c_uint, col: c_uint, scope: *DIScope) *DILocation;
+
+pub const DIBuilder = opaque {
+ pub const dispose = ZigLLVMDisposeDIBuilder;
+ extern fn ZigLLVMDisposeDIBuilder(dib: *DIBuilder) void;
+
+ pub const finalize = ZigLLVMDIBuilderFinalize;
+ extern fn ZigLLVMDIBuilderFinalize(dib: *DIBuilder) void;
+
+ pub const createPointerType = ZigLLVMCreateDebugPointerType;
+ extern fn ZigLLVMCreateDebugPointerType(
+ dib: *DIBuilder,
+ pointee_type: *DIType,
+ size_in_bits: u64,
+ align_in_bits: u64,
+ name: [*:0]const u8,
+ ) *DIType;
+
+ pub const createBasicType = ZigLLVMCreateDebugBasicType;
+ extern fn ZigLLVMCreateDebugBasicType(
+ dib: *DIBuilder,
+ name: [*:0]const u8,
+ size_in_bits: u64,
+ encoding: c_uint,
+ ) *DIType;
+
+ pub const createArrayType = ZigLLVMCreateDebugArrayType;
+ extern fn ZigLLVMCreateDebugArrayType(
+ dib: *DIBuilder,
+ size_in_bits: u64,
+ align_in_bits: u64,
+ elem_type: *DIType,
+ elem_count: c_int,
+ ) *DIType;
+
+ pub const createEnumerator = ZigLLVMCreateDebugEnumerator;
+ extern fn ZigLLVMCreateDebugEnumerator(
+ dib: *DIBuilder,
+ name: [*:0]const u8,
+ val: i64,
+ ) *DIEnumerator;
+
+ pub const createEnumerationType = ZigLLVMCreateDebugEnumerationType;
+ extern fn ZigLLVMCreateDebugEnumerationType(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ file: *DIFile,
+ line_number: c_uint,
+ size_in_bits: u64,
+ align_in_bits: u64,
+ enumerator_array: [*]const *DIEnumerator,
+ enumerator_array_len: c_int,
+ underlying_type: *DIType,
+ unique_id: [*:0]const u8,
+ ) *DIType;
+
+ pub const createStructType = ZigLLVMCreateDebugStructType;
+ extern fn ZigLLVMCreateDebugStructType(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ file: *DIFile,
+ line_number: c_uint,
+ size_in_bits: u64,
+ align_in_bits: u64,
+ flags: c_uint,
+ derived_from: *DIType,
+ types_array: [*]const *DIType,
+ types_array_len: c_int,
+ run_time_lang: c_uint,
+ vtable_holder: *DIType,
+ unique_id: [*:0]const u8,
+ ) *DIType;
+
+ pub const createUnionType = ZigLLVMCreateDebugUnionType;
+ extern fn ZigLLVMCreateDebugUnionType(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ file: *DIFile,
+ line_number: c_uint,
+ size_in_bits: u64,
+ align_in_bits: u64,
+ flags: c_uint,
+ types_array: [*]const *DIType,
+ types_array_len: c_int,
+ run_time_lang: c_uint,
+ unique_id: [*:0]const u8,
+ ) *DIType;
+
+ pub const createMemberType = ZigLLVMCreateDebugMemberType;
+ extern fn ZigLLVMCreateDebugMemberType(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ file: *DIFile,
+ line: c_uint,
+ size_in_bits: u64,
+ align_in_bits: u64,
+ offset_in_bits: u64,
+ flags: c_uint,
+ ty: *DIType,
+ ) *DIType;
+
+ pub const createReplaceableCompositeType = ZigLLVMCreateReplaceableCompositeType;
+ extern fn ZigLLVMCreateReplaceableCompositeType(
+ dib: *DIBuilder,
+ tag: c_uint,
+ name: [*:0]const u8,
+ scope: *DIScope,
+ file: *DIFile,
+ line: c_uint,
+ ) *DIType;
+
+ pub const createForwardDeclType = ZigLLVMCreateDebugForwardDeclType;
+ extern fn ZigLLVMCreateDebugForwardDeclType(
+ dib: *DIBuilder,
+ tag: c_uint,
+ name: [*:0]const u8,
+ scope: *DIScope,
+ file: *DIFile,
+ line: c_uint,
+ ) *DIType;
+
+ pub const replaceTemporary = ZigLLVMReplaceTemporary;
+ extern fn ZigLLVMReplaceTemporary(dib: *DIBuilder, ty: *DIType, replacement: *DIType) void;
+
+ pub const replaceDebugArrays = ZigLLVMReplaceDebugArrays;
+ extern fn ZigLLVMReplaceDebugArrays(
+ dib: *DIBuilder,
+ ty: *DIType,
+ types_array: [*]const *DIType,
+ types_array_len: c_int,
+ ) void;
+
+ pub const createSubroutineType = ZigLLVMCreateSubroutineType;
+ extern fn ZigLLVMCreateSubroutineType(
+ dib: *DIBuilder,
+ types_array: [*]const *DIType,
+ types_array_len: c_int,
+ flags: c_uint,
+ ) *DIType;
+
+ pub const createAutoVariable = ZigLLVMCreateAutoVariable;
+ extern fn ZigLLVMCreateAutoVariable(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ file: *DIFile,
+ line_no: c_uint,
+ ty: *DIType,
+ always_preserve: bool,
+ flags: c_uint,
+ ) *DILocalVariable;
+
+ pub const createGlobalVariable = ZigLLVMCreateGlobalVariable;
+ extern fn ZigLLVMCreateGlobalVariable(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ linkage_name: [*:0]const u8,
+ file: *DIFile,
+ line_no: c_uint,
+ di_type: *DIType,
+ is_local_to_unit: bool,
+ ) *DIGlobalVariable;
+
+ pub const createParameterVariable = ZigLLVMCreateParameterVariable;
+ extern fn ZigLLVMCreateParameterVariable(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ file: *DIFile,
+ line_no: c_uint,
+ ty: *DIType,
+ always_preserve: bool,
+ flags: c_uint,
+ arg_no: c_uint,
+ ) *DILocalVariable;
+
+ pub const createLexicalBlock = ZigLLVMCreateLexicalBlock;
+ extern fn ZigLLVMCreateLexicalBlock(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ file: *DIFile,
+ line: c_uint,
+ col: c_uint,
+ ) *DILexicalBlock;
+
+ pub const createCompileUnit = ZigLLVMCreateCompileUnit;
+ extern fn ZigLLVMCreateCompileUnit(
+ dib: *DIBuilder,
+ lang: c_uint,
+ difile: *DIFile,
+ producer: [*:0]const u8,
+ is_optimized: bool,
+ flags: [*:0]const u8,
+ runtime_version: c_uint,
+ split_name: [*:0]const u8,
+ dwo_id: u64,
+ emit_debug_info: bool,
+ ) *DICompileUnit;
+
+ pub const createFile = ZigLLVMCreateFile;
+ extern fn ZigLLVMCreateFile(
+ dib: *DIBuilder,
+ filename: [*:0]const u8,
+ directory: [*:0]const u8,
+ ) *DIFile;
+
+ pub const createFunction = ZigLLVMCreateFunction;
+ extern fn ZigLLVMCreateFunction(
+ dib: *DIBuilder,
+ scope: *DIScope,
+ name: [*:0]const u8,
+ linkage_name: [*:0]const u8,
+ file: *DIFile,
+ lineno: c_uint,
+ fn_di_type: *DIType,
+ is_local_to_unit: bool,
+ is_definition: bool,
+ scope_line: c_uint,
+ flags: c_uint,
+ is_optimized: bool,
+ decl_subprogram: *DISubprogram,
+ ) *DISubprogram;
+
+ pub const createVectorType = ZigLLVMDIBuilderCreateVectorType;
+ extern fn ZigLLVMDIBuilderCreateVectorType(
+ dib: *DIBuilder,
+ SizeInBits: u64,
+ AlignInBits: u32,
+ Ty: *DIType,
+ elem_count: u32,
+ ) *DIType;
+
+ pub const insertDeclareAtEnd = ZigLLVMInsertDeclareAtEnd;
+ extern fn ZigLLVMInsertDeclareAtEnd(
+ dib: *DIBuilder,
+ storage: *const Value,
+ var_info: *DILocalVariable,
+ debug_loc: *DILocation,
+ basic_block_ref: *const BasicBlock,
+ ) *const Value;
+
+ pub const insertDeclare = ZigLLVMInsertDeclare;
+ extern fn ZigLLVMInsertDeclare(
+ dib: *DIBuilder,
+ storage: *const Value,
+ var_info: *DILocalVariable,
+ debug_loc: *DILocation,
+ insert_before_instr: *const Value,
+ ) *const Value;
+};
src/codegen/llvm.zig
@@ -5,12 +5,14 @@ const Allocator = std.mem.Allocator;
const log = std.log.scoped(.codegen);
const math = std.math;
const native_endian = builtin.cpu.arch.endian();
+const DW = std.dwarf;
const llvm = @import("llvm/bindings.zig");
const link = @import("../link.zig");
const Compilation = @import("../Compilation.zig");
const build_options = @import("build_options");
const Module = @import("../Module.zig");
+const Package = @import("../Package.zig");
const TypedValue = @import("../TypedValue.zig");
const Air = @import("../Air.zig");
const Liveness = @import("../Liveness.zig");
@@ -159,6 +161,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 {
pub const Object = struct {
llvm_module: *const llvm.Module,
+ dibuilder: ?*llvm.DIBuilder,
context: *const llvm.Context,
target_machine: *const llvm.TargetMachine,
target_data: *const llvm.TargetData,
@@ -180,8 +183,9 @@ pub const Object = struct {
/// The backing memory for `type_map`. Periodically garbage collected after flush().
/// The code for doing the periodical GC is not yet implemented.
type_map_arena: std.heap.ArenaAllocator,
- /// The LLVM global table which holds the names corresponding to Zig errors. Note that the values
- /// are not added until flushModule, when all errors in the compilation are known.
+ /// The LLVM global table which holds the names corresponding to Zig errors.
+ /// Note that the values are not added until flushModule, when all errors in
+ /// the compilation are known.
error_name_table: ?*const llvm.Value,
pub const TypeMap = std.HashMapUnmanaged(
@@ -204,9 +208,7 @@ pub const Object = struct {
initializeLLVMTarget(options.target.cpu.arch);
- const root_nameZ = try gpa.dupeZ(u8, options.root_name);
- defer gpa.free(root_nameZ);
- const llvm_module = llvm.Module.createWithName(root_nameZ.ptr, context);
+ const llvm_module = llvm.Module.createWithName(options.root_name.ptr, context);
errdefer llvm_module.dispose();
const llvm_target_triple = try targetTriple(gpa, options.target);
@@ -221,6 +223,58 @@ pub const Object = struct {
return error.InvalidLlvmTriple;
}
+ llvm_module.setTarget(llvm_target_triple.ptr);
+ var opt_dbuilder: ?*llvm.DIBuilder = null;
+ errdefer if (opt_dbuilder) |dibuilder| dibuilder.dispose();
+
+ if (!options.strip) {
+ switch (options.object_format) {
+ .coff => llvm_module.addModuleCodeViewFlag(),
+ else => llvm_module.addModuleDebugInfoFlag(),
+ }
+ const dibuilder = llvm_module.createDIBuilder(true);
+ opt_dbuilder = dibuilder;
+
+ // Don't use the version string here; LLVM misparses it when it
+ // includes the git revision.
+ const producer = try std.fmt.allocPrintZ(gpa, "zig {d}.{d}.{d}", .{
+ build_options.semver.major,
+ build_options.semver.minor,
+ build_options.semver.patch,
+ });
+ defer gpa.free(producer);
+
+ // For macOS stack traces, we want to avoid having to parse the compilation unit debug
+ // info. As long as each debug info file has a path independent of the compilation unit
+ // directory (DW_AT_comp_dir), then we never have to look at the compilation unit debug
+ // info. If we provide an absolute path to LLVM here for the compilation unit debug
+ // info, LLVM will emit DWARF info that depends on DW_AT_comp_dir. To avoid this, we
+ // pass "." for the compilation unit directory. This forces each debug file to have a
+ // directory rather than be relative to DW_AT_comp_dir. According to DWARF 5, debug
+ // files will no longer reference DW_AT_comp_dir, for the purpose of being able to
+ // support the common practice of stripping all but the line number sections from an
+ // executable.
+ const compile_unit_dir = d: {
+ if (options.target.isDarwin()) break :d ".";
+ const mod = options.module orelse break :d ".";
+ break :d mod.root_pkg.root_src_directory.path orelse ".";
+ };
+ const compile_unit_dir_z = try gpa.dupeZ(u8, compile_unit_dir);
+ defer gpa.free(compile_unit_dir_z);
+
+ _ = dibuilder.createCompileUnit(
+ DW.LANG.C99,
+ dibuilder.createFile(options.root_name, compile_unit_dir_z),
+ producer,
+ options.optimize_mode != .Debug,
+ "", // flags
+ 0, // runtime version
+ "", // split name
+ 0, // dwo id
+ true, // emit debug info
+ );
+ }
+
const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug)
.None
else
@@ -266,6 +320,7 @@ pub const Object = struct {
return Object{
.llvm_module = llvm_module,
+ .dibuilder = opt_dbuilder,
.context = context,
.target_machine = target_machine,
.target_data = target_data,
@@ -277,6 +332,7 @@ pub const Object = struct {
}
pub fn deinit(self: *Object, gpa: Allocator) void {
+ if (self.dibuilder) |dib| dib.dispose();
self.target_data.dispose();
self.target_machine.dispose();
self.llvm_module.dispose();
src/Compilation.zig
@@ -898,7 +898,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
// We put the `Compilation` itself in the arena. Freeing the arena will free the module.
// It's initialized later after we prepare the initialization options.
const comp = try arena.create(Compilation);
- const root_name = try arena.dupe(u8, options.root_name);
+ const root_name = try arena.dupeZ(u8, options.root_name);
const ofmt = options.object_format orelse options.target.getObjectFormat();
src/link.zig
@@ -72,7 +72,7 @@ pub const Options = struct {
object_format: std.Target.ObjectFormat,
optimize_mode: std.builtin.Mode,
machine_code_model: std.builtin.CodeModel,
- root_name: []const u8,
+ root_name: [:0]const u8,
/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
module: ?*Module,
dynamic_linker: ?[]const u8,