diff options
| -rw-r--r-- | lib/std/dwarf.zig | 15 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 551 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 55 |
3 files changed, 589 insertions, 32 deletions
diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index eb204d15ee..12ec357849 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -226,6 +226,21 @@ pub const LNCT = struct { pub const hi_user = 0x3fff; }; +pub const CC = enum(u8) { + normal = 0x1, + program = 0x2, + nocall = 0x3, + + pass_by_reference = 0x4, + pass_by_value = 0x5, + + lo_user = 0x40, + hi_user = 0xff, + + GNU_renesas_sh = 0x40, + GNU_borland_fastcall_i386 = 0x41, +}; + const PcRange = struct { start: u64, end: u64, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c6ada88aa4..30b87ceed9 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -161,7 +161,12 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { pub const Object = struct { llvm_module: *const llvm.Module, - dibuilder: ?*llvm.DIBuilder, + di_builder: ?*llvm.DIBuilder, + /// One of these mappings: + /// - *Module.File => *DIFile + /// - *Module.Decl => *DISubprogram + di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DIScope), + di_compile_unit: ?*llvm.DICompileUnit, context: *const llvm.Context, target_machine: *const llvm.TargetMachine, target_data: *const llvm.TargetData, @@ -224,16 +229,18 @@ pub const Object = struct { } llvm_module.setTarget(llvm_target_triple.ptr); - var opt_dbuilder: ?*llvm.DIBuilder = null; - errdefer if (opt_dbuilder) |dibuilder| dibuilder.dispose(); + var opt_di_builder: ?*llvm.DIBuilder = null; + errdefer if (opt_di_builder) |di_builder| di_builder.dispose(); + + var di_compile_unit: ?*llvm.DICompileUnit = null; if (!options.strip) { switch (options.object_format) { .coff => llvm_module.addModuleCodeViewFlag(), else => llvm_module.addModuleDebugInfoFlag(), } - const dibuilder = llvm_module.createDIBuilder(true); - opt_dbuilder = dibuilder; + const di_builder = llvm_module.createDIBuilder(true); + opt_di_builder = di_builder; // Don't use the version string here; LLVM misparses it when it // includes the git revision. @@ -262,9 +269,9 @@ pub const Object = struct { const compile_unit_dir_z = try gpa.dupeZ(u8, compile_unit_dir); defer gpa.free(compile_unit_dir_z); - _ = dibuilder.createCompileUnit( + di_compile_unit = di_builder.createCompileUnit( DW.LANG.C99, - dibuilder.createFile(options.root_name, compile_unit_dir_z), + di_builder.createFile(options.root_name, compile_unit_dir_z), producer, options.optimize_mode != .Debug, "", // flags @@ -320,7 +327,9 @@ pub const Object = struct { return Object{ .llvm_module = llvm_module, - .dibuilder = opt_dbuilder, + .di_map = .{}, + .di_builder = opt_di_builder, + .di_compile_unit = di_compile_unit, .context = context, .target_machine = target_machine, .target_data = target_data, @@ -332,7 +341,10 @@ pub const Object = struct { } pub fn deinit(self: *Object, gpa: Allocator) void { - if (self.dibuilder) |dib| dib.dispose(); + if (self.di_builder) |dib| { + dib.dispose(); + self.di_map.deinit(gpa); + } self.target_data.dispose(); self.target_machine.dispose(); self.llvm_module.dispose(); @@ -413,6 +425,9 @@ pub const Object = struct { pub fn flushModule(self: *Object, comp: *Compilation) !void { try self.genErrorNameTable(comp); + + if (self.di_builder) |dib| dib.finalize(); + if (comp.verbose_llvm_ir) { self.llvm_module.dump(); } @@ -526,8 +541,9 @@ pub const Object = struct { const target = dg.module.getTarget(); const sret = firstParamSRet(fn_info, target); const ret_ptr = if (sret) llvm_func.getParam(0) else null; + const gpa = dg.gpa; - var args = std.ArrayList(*const llvm.Value).init(dg.gpa); + var args = std.ArrayList(*const llvm.Value).init(gpa); defer args.deinit(); const param_offset: c_uint = @boolToInt(ret_ptr != null); @@ -538,8 +554,53 @@ pub const Object = struct { try args.append(llvm_func.getParam(llvm_arg_i)); } + var di_file: ?*llvm.DIFile = null; + var di_scope: ?*llvm.DIScope = null; + + if (dg.object.di_builder) |dib| { + di_file = s: { + const file = decl.src_namespace.file_scope; + const gop = try dg.object.di_map.getOrPut(gpa, file); + if (!gop.found_existing) { + const dir_path = file.pkg.root_src_directory.path orelse "."; + const sub_file_path_z = try gpa.dupeZ(u8, file.sub_file_path); + defer gpa.free(sub_file_path_z); + const dir_path_z = try gpa.dupeZ(u8, dir_path); + defer gpa.free(dir_path_z); + gop.value_ptr.* = dib.createFile(sub_file_path_z, dir_path_z).toScope(); + } + break :s @ptrCast(*llvm.DIFile, gop.value_ptr.*); + }; + + const line_number = decl.src_line + 1; + const is_internal_linkage = decl.val.tag() != .extern_fn and + !dg.module.decl_exports.contains(decl); + const noret_bit: c_uint = if (fn_info.return_type.isNoReturn()) + llvm.DIFlags.NoReturn + else + 0; + const subprogram = dib.createFunction( + di_file.?.toScope(), + decl.name, + llvm_func.getValueName(), + di_file.?, + line_number, + try dg.lowerDebugType(decl.ty), + is_internal_linkage, + true, // is definition + line_number + func.lbrace_line, // scope line + llvm.DIFlags.StaticMember | noret_bit, + dg.module.comp.bin_file.options.optimize_mode != .Debug, + null, // decl_subprogram + ); + + llvm_func.fnSetSubprogram(subprogram); + + di_scope = subprogram.toScope(); + } + var fg: FuncGen = .{ - .gpa = dg.gpa, + .gpa = gpa, .air = air, .liveness = liveness, .context = dg.context, @@ -552,6 +613,8 @@ pub const Object = struct { .llvm_func = llvm_func, .blocks = .{}, .single_threaded = module.comp.bin_file.options.single_threaded, + .di_scope = di_scope, + .di_file = di_file, }; defer fg.deinit(); @@ -1827,6 +1890,418 @@ pub const DeclGen = struct { } } + fn lowerDebugType(dg: *DeclGen, ty: Type) Allocator.Error!*llvm.DIType { + const gpa = dg.gpa; + const target = dg.module.getTarget(); + const dib = dg.object.di_builder.?; + switch (ty.zigTypeTag()) { + .Void, .NoReturn => return dib.createBasicType("void", 0, DW.ATE.signed), + .Int => { + const info = ty.intInfo(target); + assert(info.bits != 0); + const name = try ty.nameAlloc(gpa); // TODO this is a leak + const dwarf_encoding: c_uint = switch (info.signedness) { + .signed => DW.ATE.signed, + .unsigned => DW.ATE.unsigned, + }; + return dib.createBasicType(name, info.bits, dwarf_encoding); + }, + .Enum => { + @panic("TODO debug info type for enums"); + //var buffer: Type.Payload.Bits = undefined; + //const int_ty = ty.intTagType(&buffer); + //const bit_count = int_ty.intInfo(target).bits; + //assert(bit_count != 0); + //return dg.context.intType(bit_count); + }, + .Float => { + const bits = ty.floatBits(target); + const name = try ty.nameAlloc(gpa); // TODO this is a leak + return dib.createBasicType(name, bits, DW.ATE.float); + }, + .Bool => return dib.createBasicType("bool", 1, DW.ATE.boolean), + .Pointer => { + if (ty.isSlice()) { + @panic("TODO debug info type for slices"); + //var buf: Type.SlicePtrFieldTypeBuffer = undefined; + //const ptr_type = ty.slicePtrFieldType(&buf); + + //const fields: [2]*const llvm.Type = .{ + // try dg.llvmType(ptr_type), + // try dg.llvmType(Type.usize), + //}; + //return dg.context.structType(&fields, fields.len, .False); + } + + const ptr_info = ty.ptrInfo().data; + const elem_di_ty = try lowerDebugType(dg, ptr_info.pointee_type); + const name = try ty.nameAlloc(gpa); // TODO this is a leak + return dib.createPointerType( + elem_di_ty, + target.cpu.arch.ptrBitWidth(), + ty.ptrAlignment(target) * 8, + name, + ); + }, + .Opaque => { + @panic("TODO debug info type for opaque"); + }, + .Array => { + const elem_di_ty = try lowerDebugType(dg, ty.childType()); + return dib.createArrayType( + ty.abiSize(target) * 8, + ty.abiAlignment(target) * 8, + elem_di_ty, + @intCast(c_int, ty.arrayLen()), + ); + }, + .Vector => { + @panic("TODO debug info type for vector"); + }, + .Optional => { + @panic("TODO debug info type for optional"); + //var buf: Type.Payload.ElemType = undefined; + //const child_type = ty.optionalChild(&buf); + //if (!child_type.hasRuntimeBits()) { + // return dg.context.intType(1); + //} + //const payload_llvm_ty = try dg.llvmType(child_type); + //if (ty.isPtrLikeOptional()) { + // return payload_llvm_ty; + //} else if (!child_type.hasRuntimeBits()) { + // return dg.context.intType(1); + //} + + //const fields: [2]*const llvm.Type = .{ + // payload_llvm_ty, dg.context.intType(1), + //}; + //return dg.context.structType(&fields, fields.len, .False); + }, + .ErrorUnion => { + const err_set_ty = ty.errorUnionSet(); + const err_set_di_ty = try dg.lowerDebugType(err_set_ty); + const payload_ty = ty.errorUnionPayload(); + if (!payload_ty.hasRuntimeBits()) { + return err_set_di_ty; + } + const payload_di_ty = try dg.lowerDebugType(payload_ty); + + const name = try ty.nameAlloc(gpa); // TODO this is a leak + const di_file: ?*llvm.DIFile = null; + const line = 0; + const compile_unit_scope = dg.object.di_compile_unit.?.toScope(); + const fwd_decl = dib.createReplaceableCompositeType( + DW.TAG.structure_type, + name.ptr, + compile_unit_scope, + di_file, + line, + ); + + const err_set_size = err_set_ty.abiSize(target); + const err_set_align = err_set_ty.abiAlignment(target); + const payload_size = payload_ty.abiSize(target); + const payload_align = payload_ty.abiAlignment(target); + + var offset: u64 = 0; + offset += err_set_size; + offset = std.mem.alignForwardGeneric(u64, offset, payload_align); + const payload_offset = offset; + + const fields: [2]*llvm.DIType = .{ + dib.createMemberType( + fwd_decl.toScope(), + "tag", + di_file, + line, + err_set_size * 8, // size in bits + err_set_align * 8, // align in bits + 0, // offset in bits + 0, // flags + err_set_di_ty, + ), + dib.createMemberType( + fwd_decl.toScope(), + "value", + di_file, + line, + payload_size * 8, // size in bits + payload_align * 8, // align in bits + payload_offset * 8, // offset in bits + 0, // flags + payload_di_ty, + ), + }; + + const replacement_di_type = dib.createStructType( + compile_unit_scope, + name.ptr, + di_file, + line, + ty.abiSize(target) * 8, // size in bits + ty.abiAlignment(target) * 8, // align in bits + 0, // flags + null, // derived from + &fields, + fields.len, + 0, // run time lang + null, // vtable holder + "", // unique id + ); + dib.replaceTemporary(fwd_decl, replacement_di_type); + + return replacement_di_type; + }, + .ErrorSet => { + // TODO make this a proper enum with all the error codes in it. + // will need to consider how to take incremental compilation into account. + return dib.createBasicType("anyerror", 16, DW.ATE.unsigned); + }, + .Struct => { + @panic("TODO debug info type for struct"); + //const gop = try dg.object.type_map.getOrPut(gpa, ty); + //if (gop.found_existing) return gop.value_ptr.*; + + //// The Type memory is ephemeral; since we want to store a longer-lived + //// reference, we need to copy it here. + //gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator()); + + //if (ty.isTupleOrAnonStruct()) { + // const tuple = ty.tupleFields(); + // const llvm_struct_ty = dg.context.structCreateNamed(""); + // gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls + + // var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{}; + // defer llvm_field_types.deinit(gpa); + + // try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len); + + // comptime assert(struct_layout_version == 2); + // var offset: u64 = 0; + // var big_align: u32 = 0; + + // for (tuple.types) |field_ty, i| { + // const field_val = tuple.values[i]; + // if (field_val.tag() != .unreachable_value) continue; + + // const field_align = field_ty.abiAlignment(target); + // big_align = @maximum(big_align, field_align); + // const prev_offset = offset; + // offset = std.mem.alignForwardGeneric(u64, offset, field_align); + + // const padding_len = offset - prev_offset; + // if (padding_len > 0) { + // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + // try llvm_field_types.append(gpa, llvm_array_ty); + // } + // const field_llvm_ty = try dg.llvmType(field_ty); + // try llvm_field_types.append(gpa, field_llvm_ty); + + // offset += field_ty.abiSize(target); + // } + // { + // const prev_offset = offset; + // offset = std.mem.alignForwardGeneric(u64, offset, big_align); + // const padding_len = offset - prev_offset; + // if (padding_len > 0) { + // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + // try llvm_field_types.append(gpa, llvm_array_ty); + // } + // } + + // llvm_struct_ty.structSetBody( + // llvm_field_types.items.ptr, + // @intCast(c_uint, llvm_field_types.items.len), + // .False, + // ); + + // return llvm_struct_ty; + //} + + //const struct_obj = ty.castTag(.@"struct").?.data; + + //if (struct_obj.layout == .Packed) { + // var buf: Type.Payload.Bits = undefined; + // const int_ty = struct_obj.packedIntegerType(target, &buf); + // const int_llvm_ty = try dg.llvmType(int_ty); + // gop.value_ptr.* = int_llvm_ty; + // return int_llvm_ty; + //} + + //const name = try struct_obj.getFullyQualifiedName(gpa); + //defer gpa.free(name); + + //const llvm_struct_ty = dg.context.structCreateNamed(name); + //gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls + + //assert(struct_obj.haveFieldTypes()); + + //var llvm_field_types: std.ArrayListUnmanaged(*const llvm.Type) = .{}; + //defer llvm_field_types.deinit(gpa); + + //try llvm_field_types.ensureUnusedCapacity(gpa, struct_obj.fields.count()); + + //comptime assert(struct_layout_version == 2); + //var offset: u64 = 0; + //var big_align: u32 = 0; + + //for (struct_obj.fields.values()) |field| { + // if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; + + // const field_align = field.normalAlignment(target); + // big_align = @maximum(big_align, field_align); + // const prev_offset = offset; + // offset = std.mem.alignForwardGeneric(u64, offset, field_align); + + // const padding_len = offset - prev_offset; + // if (padding_len > 0) { + // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + // try llvm_field_types.append(gpa, llvm_array_ty); + // } + // const field_llvm_ty = try dg.llvmType(field.ty); + // try llvm_field_types.append(gpa, field_llvm_ty); + + // offset += field.ty.abiSize(target); + //} + //{ + // const prev_offset = offset; + // offset = std.mem.alignForwardGeneric(u64, offset, big_align); + // const padding_len = offset - prev_offset; + // if (padding_len > 0) { + // const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len)); + // try llvm_field_types.append(gpa, llvm_array_ty); + // } + //} + + //llvm_struct_ty.structSetBody( + // llvm_field_types.items.ptr, + // @intCast(c_uint, llvm_field_types.items.len), + // .False, + //); + + //return llvm_struct_ty; + }, + .Union => { + @panic("TODO debug info type for union"); + //const gop = try dg.object.type_map.getOrPut(gpa, ty); + //if (gop.found_existing) return gop.value_ptr.*; + + //// The Type memory is ephemeral; since we want to store a longer-lived + //// reference, we need to copy it here. + //gop.key_ptr.* = try ty.copy(dg.object.type_map_arena.allocator()); + + //const layout = ty.unionGetLayout(target); + //const union_obj = ty.cast(Type.Payload.Union).?.data; + + //if (layout.payload_size == 0) { + // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty); + // gop.value_ptr.* = enum_tag_llvm_ty; + // return enum_tag_llvm_ty; + //} + + //const name = try union_obj.getFullyQualifiedName(gpa); + //defer gpa.free(name); + + //const llvm_union_ty = dg.context.structCreateNamed(name); + //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls + + //const aligned_field = union_obj.fields.values()[layout.most_aligned_field]; + //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty); + + //const llvm_payload_ty = ty: { + // if (layout.most_aligned_field_size == layout.payload_size) { + // break :ty llvm_aligned_field_ty; + // } + // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size); + // const fields: [2]*const llvm.Type = .{ + // llvm_aligned_field_ty, + // dg.context.intType(8).arrayType(padding_len), + // }; + // break :ty dg.context.structType(&fields, fields.len, .True); + //}; + + //if (layout.tag_size == 0) { + // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty}; + // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); + // return llvm_union_ty; + //} + //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty); + + //// Put the tag before or after the payload depending on which one's + //// alignment is greater. + //var llvm_fields: [3]*const llvm.Type = undefined; + //var llvm_fields_len: c_uint = 2; + + //if (layout.tag_align >= layout.payload_align) { + // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined }; + //} else { + // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined }; + //} + + //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size. + //if (layout.padding != 0) { + // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding); + // llvm_fields_len = 3; + //} + + //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False); + //return llvm_union_ty; + }, + .Fn => { + const fn_info = ty.fnInfo(); + const sret = firstParamSRet(fn_info, target); + + var param_di_types = std.ArrayList(*llvm.DIType).init(dg.gpa); + defer param_di_types.deinit(); + + // Return type goes first. + const di_ret_ty = if (sret) Type.void else fn_info.return_type; + try param_di_types.append(try dg.lowerDebugType(di_ret_ty)); + + if (sret) { + var ptr_ty_payload: Type.Payload.ElemType = .{ + .base = .{ .tag = .single_mut_pointer }, + .data = fn_info.return_type, + }; + const ptr_ty = Type.initPayload(&ptr_ty_payload.base); + try param_di_types.append(try dg.lowerDebugType(ptr_ty)); + } + + for (fn_info.param_types) |param_ty| { + if (!param_ty.hasRuntimeBits()) continue; + + if (isByRef(param_ty)) { + var ptr_ty_payload: Type.Payload.ElemType = .{ + .base = .{ .tag = .single_mut_pointer }, + .data = param_ty, + }; + const ptr_ty = Type.initPayload(&ptr_ty_payload.base); + try param_di_types.append(try dg.lowerDebugType(ptr_ty)); + } else { + try param_di_types.append(try dg.lowerDebugType(param_ty)); + } + } + + return dib.createSubroutineType( + param_di_types.items.ptr, + @intCast(c_int, param_di_types.items.len), + 0, + ); + }, + .ComptimeInt => unreachable, + .ComptimeFloat => unreachable, + .Type => unreachable, + .Undefined => unreachable, + .Null => unreachable, + .EnumLiteral => unreachable, + + .BoundFn => @panic("TODO remove BoundFn from the language"), + + .Frame => @panic("TODO implement lowerDebugType for Frame types"), + .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"), + } + } + const ParentPtr = struct { ty: Type, llvm_ptr: *const llvm.Value, @@ -2141,6 +2616,8 @@ pub const FuncGen = struct { liveness: Liveness, context: *const llvm.Context, builder: *const llvm.Builder, + di_scope: ?*llvm.DIScope, + di_file: ?*llvm.DIFile, /// This stores the LLVM values used in a function, such that they can be referred to /// in other instructions. This table is cleared before every function is generated. @@ -2156,7 +2633,7 @@ pub const FuncGen = struct { /// it omits 0-bit types. If the function uses sret as the first parameter, /// this slice does not include it. args: []const *const llvm.Value, - arg_index: usize, + arg_index: c_uint, llvm_func: *const llvm.Value, @@ -2386,10 +2863,7 @@ pub const FuncGen = struct { .constant => unreachable, .const_ty => unreachable, .unreach => self.airUnreach(inst), - .dbg_stmt => blk: { - // TODO: implement debug info - break :blk null; - }, + .dbg_stmt => self.airDbgStmt(inst), // zig fmt: on }; if (opt_value) |val| { @@ -3099,6 +3573,17 @@ pub const FuncGen = struct { return null; } + fn airDbgStmt(self: *FuncGen, inst: Air.Inst.Index) ?*const llvm.Value { + const di_scope = self.di_scope orelse return null; + const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt; + self.builder.setCurrentDebugLocation( + @intCast(c_int, dbg_stmt.line + 1), + @intCast(c_int, dbg_stmt.column + 1), + di_scope, + ); + return null; + } + fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { // Eventually, the Zig compiler needs to be reworked to have inline assembly go // through the same parsing code regardless of backend, and have LLVM-flavored @@ -4299,15 +4784,31 @@ pub const FuncGen = struct { self.arg_index += 1; const inst_ty = self.air.typeOfIndex(inst); - if (isByRef(inst_ty)) { - // TODO declare debug variable - return arg_val; - } else { - const ptr_val = self.buildAlloca(try self.dg.llvmType(inst_ty)); - _ = self.builder.buildStore(arg_val, ptr_val); - // TODO declare debug variable - return arg_val; + const result = r: { + if (isByRef(inst_ty)) { + break :r arg_val; + } else { + const ptr_val = self.buildAlloca(try self.dg.llvmType(inst_ty)); + _ = self.builder.buildStore(arg_val, ptr_val); + break :r arg_val; + } + }; + + if (self.dg.object.di_builder) |dib| { + const func = self.dg.decl.getFunction().?; + _ = dib.createParameterVariable( + self.di_scope.?, + func.getParamName(self.arg_index - 1).ptr, // TODO test 0 bit args + self.di_file.?, + func.owner_decl.src_line + func.lbrace_line + 1, + try self.dg.lowerDebugType(inst_ty), + true, // always preserve + 0, // flags + self.arg_index, // includes +1 because 0 is return type + ); } + + return result; } fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -4830,7 +5331,7 @@ pub const FuncGen = struct { const prev_debug_location = self.builder.getCurrentDebugLocation2(); defer { self.builder.positionBuilderAtEnd(prev_block); - if (!self.dg.module.comp.bin_file.options.strip) { + if (self.di_scope != null) { self.builder.setCurrentDebugLocation2(prev_debug_location); } } diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 35fd95feef..f20fe86a38 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -193,6 +193,9 @@ pub const Value = opaque { pub const setValueName2 = LLVMSetValueName2; extern fn LLVMSetValueName2(Val: *const Value, Name: [*]const u8, NameLen: usize) void; + pub const getValueName = LLVMGetValueName; + extern fn LLVMGetValueName(Val: *const Value) [*:0]const u8; + pub const takeName = ZigLLVMTakeName; extern fn ZigLLVMTakeName(new_owner: *const Value, victim: *const Value) void; @@ -836,7 +839,7 @@ pub const Builder = opaque { pub const buildExactSDiv = LLVMBuildExactSDiv; extern fn LLVMBuildExactSDiv(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value; - pub const zigSetCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation; + pub const setCurrentDebugLocation = ZigLLVMSetCurrentDebugLocation; extern fn ZigLLVMSetCurrentDebugLocation(builder: *const Builder, line: c_int, column: c_int, scope: *DIScope) void; pub const clearCurrentDebugLocation = ZigLLVMClearCurrentDebugLocation; @@ -1505,16 +1508,16 @@ pub const DIBuilder = opaque { dib: *DIBuilder, scope: *DIScope, name: [*:0]const u8, - file: *DIFile, + file: ?*DIFile, line_number: c_uint, size_in_bits: u64, align_in_bits: u64, flags: c_uint, - derived_from: *DIType, + derived_from: ?*DIType, types_array: [*]const *DIType, types_array_len: c_int, run_time_lang: c_uint, - vtable_holder: *DIType, + vtable_holder: ?*DIType, unique_id: [*:0]const u8, ) *DIType; @@ -1539,7 +1542,7 @@ pub const DIBuilder = opaque { dib: *DIBuilder, scope: *DIScope, name: [*:0]const u8, - file: *DIFile, + file: ?*DIFile, line: c_uint, size_in_bits: u64, align_in_bits: u64, @@ -1554,7 +1557,7 @@ pub const DIBuilder = opaque { tag: c_uint, name: [*:0]const u8, scope: *DIScope, - file: *DIFile, + file: ?*DIFile, line: c_uint, ) *DIType; @@ -1668,7 +1671,7 @@ pub const DIBuilder = opaque { scope_line: c_uint, flags: c_uint, is_optimized: bool, - decl_subprogram: *DISubprogram, + decl_subprogram: ?*DISubprogram, ) *DISubprogram; pub const createVectorType = ZigLLVMDIBuilderCreateVectorType; @@ -1698,3 +1701,41 @@ pub const DIBuilder = opaque { insert_before_instr: *const Value, ) *const Value; }; + +pub const DIFlags = opaque { + pub const Zero = 0; + pub const Private = 1; + pub const Protected = 2; + pub const Public = 3; + + pub const FwdDecl = 1 << 2; + pub const AppleBlock = 1 << 3; + pub const BlockByrefStruct = 1 << 4; + pub const Virtual = 1 << 5; + pub const Artificial = 1 << 6; + pub const Explicit = 1 << 7; + pub const Prototyped = 1 << 8; + pub const ObjcClassComplete = 1 << 9; + pub const ObjectPointer = 1 << 10; + pub const Vector = 1 << 11; + pub const StaticMember = 1 << 12; + pub const LValueReference = 1 << 13; + pub const RValueReference = 1 << 14; + pub const Reserved = 1 << 15; + + pub const SingleInheritance = 1 << 16; + pub const MultipleInheritance = 2 << 16; + pub const VirtualInheritance = 3 << 16; + + pub const IntroducedVirtual = 1 << 18; + pub const BitField = 1 << 19; + pub const NoReturn = 1 << 20; + pub const TypePassByValue = 1 << 22; + pub const TypePassByReference = 1 << 23; + pub const EnumClass = 1 << 24; + pub const Thunk = 1 << 25; + pub const NonTrivial = 1 << 26; + pub const BigEndian = 1 << 27; + pub const LittleEndian = 1 << 28; + pub const AllCallsDescribed = 1 << 29; +}; |
