mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
LLVM: add compile unit to debug info
This commit also adds a bunch of bindings for debug info.
This commit is contained in:
parent
95fc41b2b4
commit
c6160fa3a5
@ -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();
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user