mirror of
https://github.com/ziglang/zig.git
synced 2024-11-17 01:23:54 +00:00
stage2: finish debug info for unions in the LLVM backend
Sema: * queue full resolution of std.builtin.Type.Error when doing `@typeInfo` for error sets. LLVM backend: * change a TODO comment to a proper explanation of why debug info for structs is left as a fwd decl sometimes. * remove handling of packed unions which does not match the type information or constant generation code. * remove copy+pasted code * fix union debug info not matching the memory layout * remove unnecessary error checks and type casting
This commit is contained in:
parent
c546608fca
commit
f4a357d720
@ -11091,6 +11091,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
|
||||
};
|
||||
|
||||
try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));
|
||||
|
||||
// If the error set is inferred it has to be resolved at this point
|
||||
try sema.resolveInferredErrorSetTy(block, src, ty);
|
||||
|
||||
|
@ -1388,8 +1388,13 @@ pub const Object = struct {
|
||||
if (ty.castTag(.@"struct")) |payload| {
|
||||
const struct_obj = payload.data;
|
||||
if (!struct_obj.haveFieldTypes()) {
|
||||
// TODO: improve the frontend to populate this struct.
|
||||
// For now we treat it as a zero bit type.
|
||||
// This can happen if a struct type makes it all the way to
|
||||
// flush() without ever being instantiated or referenced (even
|
||||
// via pointer). The only reason we are hearing about it now is
|
||||
// that it is being used as a namespace to put other debug types
|
||||
// into. Therefore we can satisfy this by making an empty namespace,
|
||||
// rather than changing the frontend to unnecessarily resolve the
|
||||
// struct field types.
|
||||
const owner_decl = ty.getOwnerDecl();
|
||||
const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
|
||||
dib.replaceTemporary(fwd_decl, struct_di_ty);
|
||||
@ -1471,16 +1476,6 @@ pub const Object = struct {
|
||||
const name = try ty.nameAlloc(gpa, target);
|
||||
defer gpa.free(name);
|
||||
|
||||
if (ty.cast(Type.Payload.Union)) |payload| {
|
||||
const union_obj = payload.data;
|
||||
if (union_obj.layout == .Packed) {
|
||||
const bit_size = ty.bitSize(target);
|
||||
const di_ty = dib.createBasicType(name, bit_size, DW.ATE.unsigned);
|
||||
gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
|
||||
return di_ty;
|
||||
}
|
||||
}
|
||||
|
||||
const fwd_decl = opt_fwd_decl orelse blk: {
|
||||
const fwd_decl = dib.createReplaceableCompositeType(
|
||||
DW.TAG.structure_type,
|
||||
@ -1494,21 +1489,6 @@ pub const Object = struct {
|
||||
break :blk fwd_decl;
|
||||
};
|
||||
|
||||
const union_obj = ty.cast(Type.Payload.Union).?.data;
|
||||
|
||||
// TODO COPYPASTE >>>
|
||||
if (!union_obj.haveFieldTypes()) {
|
||||
// TODO: improve the frontend to populate this union.
|
||||
// For now we treat it as a zero bit type.
|
||||
const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
|
||||
dib.replaceTemporary(fwd_decl, union_di_ty);
|
||||
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
|
||||
// means we can't use `gop` anymore.
|
||||
try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target });
|
||||
return union_di_ty;
|
||||
}
|
||||
// TODO <<<
|
||||
|
||||
if (!ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
|
||||
dib.replaceTemporary(fwd_decl, union_di_ty);
|
||||
@ -1518,13 +1498,41 @@ pub const Object = struct {
|
||||
return union_di_ty;
|
||||
}
|
||||
|
||||
const layout = ty.unionGetLayout(target);
|
||||
const union_obj = ty.cast(Type.Payload.Union).?.data;
|
||||
|
||||
if (layout.payload_size == 0) {
|
||||
const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
|
||||
const di_fields = [_]*llvm.DIType{tag_di_ty};
|
||||
const full_di_ty = dib.createStructType(
|
||||
compile_unit_scope,
|
||||
name.ptr,
|
||||
null, // file
|
||||
0, // line
|
||||
ty.abiSize(target) * 8, // size in bits
|
||||
ty.abiAlignment(target) * 8, // align in bits
|
||||
0, // flags
|
||||
null, // derived from
|
||||
&di_fields,
|
||||
di_fields.len,
|
||||
0, // run time lang
|
||||
null, // vtable holder
|
||||
"", // unique id
|
||||
);
|
||||
dib.replaceTemporary(fwd_decl, full_di_ty);
|
||||
// The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
|
||||
// means we can't use `gop` anymore.
|
||||
try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
|
||||
return full_di_ty;
|
||||
}
|
||||
|
||||
var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
|
||||
defer di_fields.deinit(gpa);
|
||||
|
||||
try di_fields.ensureUnusedCapacity(gpa, union_obj.fields.count());
|
||||
|
||||
var field_iterator = union_obj.fields.iterator();
|
||||
while (field_iterator.next()) |kv| {
|
||||
var it = union_obj.fields.iterator();
|
||||
while (it.next()) |kv| {
|
||||
const field_name = kv.key_ptr.*;
|
||||
const field = kv.value_ptr.*;
|
||||
|
||||
@ -1536,7 +1544,7 @@ pub const Object = struct {
|
||||
const field_name_copy = try gpa.dupeZ(u8, field_name);
|
||||
defer gpa.free(field_name_copy);
|
||||
|
||||
try di_fields.append(gpa, dib.createMemberType(
|
||||
di_fields.appendAssumeCapacity(dib.createMemberType(
|
||||
fwd_decl.toScope(),
|
||||
field_name_copy,
|
||||
null, // file
|
||||
@ -1549,31 +1557,11 @@ pub const Object = struct {
|
||||
));
|
||||
}
|
||||
|
||||
const tag_ty = union_obj.tag_ty;
|
||||
if (!tag_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
const union_di_ty = dib.createUnionType(
|
||||
compile_unit_scope,
|
||||
name.ptr,
|
||||
null, // file
|
||||
0, // line
|
||||
ty.abiSize(target) * 8, // size in bits
|
||||
ty.abiAlignment(target) * 8, // align in bits
|
||||
0, // flags
|
||||
di_fields.items.ptr,
|
||||
@intCast(c_int, di_fields.items.len),
|
||||
0, // run time lang
|
||||
"", // unique id
|
||||
);
|
||||
|
||||
dib.replaceTemporary(fwd_decl, union_di_ty);
|
||||
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
|
||||
try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target });
|
||||
return union_di_ty;
|
||||
}
|
||||
const union_name = if (layout.tag_size == 0) "AnonUnion" else name.ptr;
|
||||
|
||||
const union_di_ty = dib.createUnionType(
|
||||
fwd_decl.toScope(),
|
||||
"AnonUnion",
|
||||
compile_unit_scope,
|
||||
union_name,
|
||||
null, // file
|
||||
0, // line
|
||||
ty.abiSize(target) * 8, // size in bits
|
||||
@ -1585,47 +1573,50 @@ pub const Object = struct {
|
||||
"", // unique id
|
||||
);
|
||||
|
||||
const payload_size = ty.abiSize(target);
|
||||
const payload_align = ty.abiAlignment(target);
|
||||
const tag_size = tag_ty.abiSize(target);
|
||||
const tag_align = tag_ty.abiAlignment(target);
|
||||
if (layout.tag_size == 0) {
|
||||
dib.replaceTemporary(fwd_decl, union_di_ty);
|
||||
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
|
||||
try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target });
|
||||
return union_di_ty;
|
||||
}
|
||||
|
||||
assert(tag_size > 0);
|
||||
assert(tag_align > 0);
|
||||
|
||||
var offset: u64 = 0;
|
||||
offset += payload_size;
|
||||
offset = std.mem.alignForwardGeneric(u64, offset, tag_align);
|
||||
const tag_offset = offset;
|
||||
|
||||
const payload_di = dib.createMemberType(
|
||||
fwd_decl.toScope(),
|
||||
"payload",
|
||||
null, // file
|
||||
0, // line
|
||||
payload_size * 8, // size in bits
|
||||
payload_align * 8, // align in bits
|
||||
0, // field_offset * 8, // offset in bits
|
||||
0, // flags
|
||||
union_di_ty,
|
||||
);
|
||||
var tag_offset: u64 = undefined;
|
||||
var payload_offset: u64 = undefined;
|
||||
if (layout.tag_align >= layout.payload_align) {
|
||||
tag_offset = 0;
|
||||
payload_offset = std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
|
||||
} else {
|
||||
payload_offset = 0;
|
||||
tag_offset = std.mem.alignForwardGeneric(u64, layout.payload_size, layout.tag_align);
|
||||
}
|
||||
|
||||
const tag_di = dib.createMemberType(
|
||||
fwd_decl.toScope(),
|
||||
"tag",
|
||||
null, // file
|
||||
0, // line
|
||||
tag_size * 8, // TODO: should this be multiplied by 8??? analyze.cpp:9237
|
||||
tag_align * 8, // align in bits
|
||||
layout.tag_size * 8,
|
||||
layout.tag_align * 8, // align in bits
|
||||
tag_offset * 8, // offset in bits
|
||||
0, // flags
|
||||
try o.lowerDebugType(tag_ty, .full),
|
||||
try o.lowerDebugType(union_obj.tag_ty, .full),
|
||||
);
|
||||
|
||||
const full_di_fields = [_]*llvm.DIType {
|
||||
payload_di,
|
||||
tag_di,
|
||||
};
|
||||
const payload_di = dib.createMemberType(
|
||||
fwd_decl.toScope(),
|
||||
"payload",
|
||||
null, // file
|
||||
0, // line
|
||||
layout.payload_size * 8, // size in bits
|
||||
layout.payload_align * 8, // align in bits
|
||||
payload_offset * 8, // offset in bits
|
||||
0, // flags
|
||||
union_di_ty,
|
||||
);
|
||||
|
||||
const full_di_fields: [2]*llvm.DIType =
|
||||
if (layout.tag_align >= layout.payload_align)
|
||||
.{ tag_di, payload_di } else .{ payload_di, tag_di };
|
||||
|
||||
const full_di_ty = dib.createStructType(
|
||||
compile_unit_scope,
|
||||
@ -1637,7 +1628,7 @@ pub const Object = struct {
|
||||
0, // flags
|
||||
null, // derived from
|
||||
&full_di_fields,
|
||||
@intCast(c_int, full_di_fields.len),
|
||||
full_di_fields.len,
|
||||
0, // run time lang
|
||||
null, // vtable holder
|
||||
"", // unique id
|
||||
@ -1646,60 +1637,6 @@ pub const Object = struct {
|
||||
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
|
||||
try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
|
||||
return full_di_ty;
|
||||
|
||||
//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();
|
||||
|
Loading…
Reference in New Issue
Block a user