authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-28 16:43:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-28 16:43:24-07:00
log857743473ced48a493a713c0b86340ee110ce909
tree4cca3c0a134ceda850bcc23309cda5352774185a
parentb6ccde47adeb0dbd7b39150c36498100e0d98075
parentf4a357d7209db61acdfcb24ecec316da66eb318d

Merge @schmee's union debug info branch


4 files changed, 153 insertions(+), 83 deletions(-)

src/Module.zig+2-14
......@@ -1231,13 +1231,7 @@ pub const Union = struct {
12311231 for (u.fields.values()) |field, i| {
12321232 if (!field.ty.hasRuntimeBits()) continue;
12331233
1234 const field_align = a: {
1235 if (field.abi_align == 0) {
1236 break :a field.ty.abiAlignment(target);
1237 } else {
1238 break :a field.abi_align;
1239 }
1240 };
1234 const field_align = field.normalAlignment(target);
12411235 if (field_align > most_alignment) {
12421236 most_alignment = field_align;
12431237 most_index = i;
......@@ -1253,13 +1247,7 @@ pub const Union = struct {
12531247 for (u.fields.values()) |field| {
12541248 if (!field.ty.hasRuntimeBits()) continue;
12551249
1256 const field_align = a: {
1257 if (field.abi_align == 0) {
1258 break :a field.ty.abiAlignment(target);
1259 } else {
1260 break :a field.abi_align;
1261 }
1262 };
1250 const field_align = field.normalAlignment(target);
12631251 max_align = @maximum(max_align, field_align);
12641252 }
12651253 return max_align;
src/Sema.zig+2
......@@ -11091,6 +11091,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1109111091 break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
1109211092 };
1109311093
11094 try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));
11095
1109411096 // If the error set is inferred it has to be resolved at this point
1109511097 try sema.resolveInferredErrorSetTy(block, src, ty);
1109611098
src/codegen/llvm.zig+148-68
......@@ -1388,8 +1388,13 @@ pub const Object = struct {
13881388 if (ty.castTag(.@"struct")) |payload| {
13891389 const struct_obj = payload.data;
13901390 if (!struct_obj.haveFieldTypes()) {
1391 // TODO: improve the frontend to populate this struct.
1392 // For now we treat it as a zero bit type.
1391 // This can happen if a struct type makes it all the way to
1392 // flush() without ever being instantiated or referenced (even
1393 // via pointer). The only reason we are hearing about it now is
1394 // that it is being used as a namespace to put other debug types
1395 // into. Therefore we can satisfy this by making an empty namespace,
1396 // rather than changing the frontend to unnecessarily resolve the
1397 // struct field types.
13931398 const owner_decl = ty.getOwnerDecl();
13941399 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
13951400 dib.replaceTemporary(fwd_decl, struct_di_ty);
......@@ -1465,6 +1470,7 @@ pub const Object = struct {
14651470 return full_di_ty;
14661471 },
14671472 .Union => {
1473 const compile_unit_scope = o.di_compile_unit.?.toScope();
14681474 const owner_decl = ty.getOwnerDecl();
14691475
14701476 const name = try ty.nameAlloc(gpa, target);
......@@ -1483,8 +1489,7 @@ pub const Object = struct {
14831489 break :blk fwd_decl;
14841490 };
14851491
1486 const TODO_implement_this = true; // TODO
1487 if (TODO_implement_this or !ty.hasRuntimeBitsIgnoreComptime()) {
1492 if (!ty.hasRuntimeBitsIgnoreComptime()) {
14881493 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
14891494 dib.replaceTemporary(fwd_decl, union_di_ty);
14901495 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
......@@ -1493,70 +1498,145 @@ pub const Object = struct {
14931498 return union_di_ty;
14941499 }
14951500
1496 @panic("TODO debug info type for union");
1497 //const gop = try o.type_map.getOrPut(gpa, ty);
1498 //if (gop.found_existing) return gop.value_ptr.*;
1499
1500 //// The Type memory is ephemeral; since we want to store a longer-lived
1501 //// reference, we need to copy it here.
1502 //gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());
1503
1504 //const layout = ty.unionGetLayout(target);
1505 //const union_obj = ty.cast(Type.Payload.Union).?.data;
1506
1507 //if (layout.payload_size == 0) {
1508 // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
1509 // gop.value_ptr.* = enum_tag_llvm_ty;
1510 // return enum_tag_llvm_ty;
1511 //}
1512
1513 //const name = try union_obj.getFullyQualifiedName(gpa);
1514 //defer gpa.free(name);
1515
1516 //const llvm_union_ty = dg.context.structCreateNamed(name);
1517 //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
1518
1519 //const aligned_field = union_obj.fields.values()[layout.most_aligned_field];
1520 //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);
1521
1522 //const llvm_payload_ty = ty: {
1523 // if (layout.most_aligned_field_size == layout.payload_size) {
1524 // break :ty llvm_aligned_field_ty;
1525 // }
1526 // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);
1527 // const fields: [2]*const llvm.Type = .{
1528 // llvm_aligned_field_ty,
1529 // dg.context.intType(8).arrayType(padding_len),
1530 // };
1531 // break :ty dg.context.structType(&fields, fields.len, .True);
1532 //};
1533
1534 //if (layout.tag_size == 0) {
1535 // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};
1536 // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);
1537 // return llvm_union_ty;
1538 //}
1539 //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);
1540
1541 //// Put the tag before or after the payload depending on which one's
1542 //// alignment is greater.
1543 //var llvm_fields: [3]*const llvm.Type = undefined;
1544 //var llvm_fields_len: c_uint = 2;
1545
1546 //if (layout.tag_align >= layout.payload_align) {
1547 // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };
1548 //} else {
1549 // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };
1550 //}
1551
1552 //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size.
1553 //if (layout.padding != 0) {
1554 // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);
1555 // llvm_fields_len = 3;
1556 //}
1557
1558 //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);
1559 //return llvm_union_ty;
1501 const layout = ty.unionGetLayout(target);
1502 const union_obj = ty.cast(Type.Payload.Union).?.data;
1503
1504 if (layout.payload_size == 0) {
1505 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
1506 const di_fields = [_]*llvm.DIType{tag_di_ty};
1507 const full_di_ty = dib.createStructType(
1508 compile_unit_scope,
1509 name.ptr,
1510 null, // file
1511 0, // line
1512 ty.abiSize(target) * 8, // size in bits
1513 ty.abiAlignment(target) * 8, // align in bits
1514 0, // flags
1515 null, // derived from
1516 &di_fields,
1517 di_fields.len,
1518 0, // run time lang
1519 null, // vtable holder
1520 "", // unique id
1521 );
1522 dib.replaceTemporary(fwd_decl, full_di_ty);
1523 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1524 // means we can't use `gop` anymore.
1525 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
1526 return full_di_ty;
1527 }
1528
1529 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
1530 defer di_fields.deinit(gpa);
1531
1532 try di_fields.ensureUnusedCapacity(gpa, union_obj.fields.count());
1533
1534 var it = union_obj.fields.iterator();
1535 while (it.next()) |kv| {
1536 const field_name = kv.key_ptr.*;
1537 const field = kv.value_ptr.*;
1538
1539 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
1540
1541 const field_size = field.ty.abiSize(target);
1542 const field_align = field.normalAlignment(target);
1543
1544 const field_name_copy = try gpa.dupeZ(u8, field_name);
1545 defer gpa.free(field_name_copy);
1546
1547 di_fields.appendAssumeCapacity(dib.createMemberType(
1548 fwd_decl.toScope(),
1549 field_name_copy,
1550 null, // file
1551 0, // line
1552 field_size * 8, // size in bits
1553 field_align * 8, // align in bits
1554 0, // offset in bits
1555 0, // flags
1556 try o.lowerDebugType(field.ty, .full),
1557 ));
1558 }
1559
1560 const union_name = if (layout.tag_size == 0) "AnonUnion" else name.ptr;
1561
1562 const union_di_ty = dib.createUnionType(
1563 compile_unit_scope,
1564 union_name,
1565 null, // file
1566 0, // line
1567 ty.abiSize(target) * 8, // size in bits
1568 ty.abiAlignment(target) * 8, // align in bits
1569 0, // flags
1570 di_fields.items.ptr,
1571 @intCast(c_int, di_fields.items.len),
1572 0, // run time lang
1573 "", // unique id
1574 );
1575
1576 if (layout.tag_size == 0) {
1577 dib.replaceTemporary(fwd_decl, union_di_ty);
1578 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1579 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target });
1580 return union_di_ty;
1581 }
1582
1583 var tag_offset: u64 = undefined;
1584 var payload_offset: u64 = undefined;
1585 if (layout.tag_align >= layout.payload_align) {
1586 tag_offset = 0;
1587 payload_offset = std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
1588 } else {
1589 payload_offset = 0;
1590 tag_offset = std.mem.alignForwardGeneric(u64, layout.payload_size, layout.tag_align);
1591 }
1592
1593 const tag_di = dib.createMemberType(
1594 fwd_decl.toScope(),
1595 "tag",
1596 null, // file
1597 0, // line
1598 layout.tag_size * 8,
1599 layout.tag_align * 8, // align in bits
1600 tag_offset * 8, // offset in bits
1601 0, // flags
1602 try o.lowerDebugType(union_obj.tag_ty, .full),
1603 );
1604
1605 const payload_di = dib.createMemberType(
1606 fwd_decl.toScope(),
1607 "payload",
1608 null, // file
1609 0, // line
1610 layout.payload_size * 8, // size in bits
1611 layout.payload_align * 8, // align in bits
1612 payload_offset * 8, // offset in bits
1613 0, // flags
1614 union_di_ty,
1615 );
1616
1617 const full_di_fields: [2]*llvm.DIType =
1618 if (layout.tag_align >= layout.payload_align)
1619 .{ tag_di, payload_di } else .{ payload_di, tag_di };
1620
1621 const full_di_ty = dib.createStructType(
1622 compile_unit_scope,
1623 name.ptr,
1624 null, // file
1625 0, // line
1626 ty.abiSize(target) * 8, // size in bits
1627 ty.abiAlignment(target) * 8, // align in bits
1628 0, // flags
1629 null, // derived from
1630 &full_di_fields,
1631 full_di_fields.len,
1632 0, // run time lang
1633 null, // vtable holder
1634 "", // unique id
1635 );
1636 dib.replaceTemporary(fwd_decl, full_di_ty);
1637 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1638 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
1639 return full_di_ty;
15601640 },
15611641 .Fn => {
15621642 const fn_info = ty.fnInfo();
src/codegen/llvm/bindings.zig+1-1
......@@ -1601,7 +1601,7 @@ pub const DIBuilder = opaque {
16011601 dib: *DIBuilder,
16021602 scope: *DIScope,
16031603 name: [*:0]const u8,
1604 file: *DIFile,
1604 file: ?*DIFile,
16051605 line_number: c_uint,
16061606 size_in_bits: u64,
16071607 align_in_bits: u64,