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 {...@@ -1231,13 +1231,7 @@ pub const Union = struct {
1231 for (u.fields.values()) |field, i| {1231 for (u.fields.values()) |field, i| {
1232 if (!field.ty.hasRuntimeBits()) continue;1232 if (!field.ty.hasRuntimeBits()) continue;
12331233
1234 const field_align = a: {1234 const field_align = field.normalAlignment(target);
1235 if (field.abi_align == 0) {
1236 break :a field.ty.abiAlignment(target);
1237 } else {
1238 break :a field.abi_align;
1239 }
1240 };
1241 if (field_align > most_alignment) {1235 if (field_align > most_alignment) {
1242 most_alignment = field_align;1236 most_alignment = field_align;
1243 most_index = i;1237 most_index = i;
...@@ -1253,13 +1247,7 @@ pub const Union = struct {...@@ -1253,13 +1247,7 @@ pub const Union = struct {
1253 for (u.fields.values()) |field| {1247 for (u.fields.values()) |field| {
1254 if (!field.ty.hasRuntimeBits()) continue;1248 if (!field.ty.hasRuntimeBits()) continue;
12551249
1256 const field_align = a: {1250 const field_align = field.normalAlignment(target);
1257 if (field.abi_align == 0) {
1258 break :a field.ty.abiAlignment(target);
1259 } else {
1260 break :a field.abi_align;
1261 }
1262 };
1263 max_align = @maximum(max_align, field_align);1251 max_align = @maximum(max_align, field_align);
1264 }1252 }
1265 return max_align;1253 return max_align;
src/Sema.zig+2
...@@ -11091,6 +11091,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -11091,6 +11091,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
11091 break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());11091 break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
11092 };11092 };
1109311093
11094 try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));
11095
11094 // If the error set is inferred it has to be resolved at this point11096 // If the error set is inferred it has to be resolved at this point
11095 try sema.resolveInferredErrorSetTy(block, src, ty);11097 try sema.resolveInferredErrorSetTy(block, src, ty);
1109611098
src/codegen/llvm.zig+148-68
...@@ -1388,8 +1388,13 @@ pub const Object = struct {...@@ -1388,8 +1388,13 @@ pub const Object = struct {
1388 if (ty.castTag(.@"struct")) |payload| {1388 if (ty.castTag(.@"struct")) |payload| {
1389 const struct_obj = payload.data;1389 const struct_obj = payload.data;
1390 if (!struct_obj.haveFieldTypes()) {1390 if (!struct_obj.haveFieldTypes()) {
1391 // TODO: improve the frontend to populate this struct.1391 // This can happen if a struct type makes it all the way to
1392 // For now we treat it as a zero bit type.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.
1393 const owner_decl = ty.getOwnerDecl();1398 const owner_decl = ty.getOwnerDecl();
1394 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);1399 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
1395 dib.replaceTemporary(fwd_decl, struct_di_ty);1400 dib.replaceTemporary(fwd_decl, struct_di_ty);
...@@ -1465,6 +1470,7 @@ pub const Object = struct {...@@ -1465,6 +1470,7 @@ pub const Object = struct {
1465 return full_di_ty;1470 return full_di_ty;
1466 },1471 },
1467 .Union => {1472 .Union => {
1473 const compile_unit_scope = o.di_compile_unit.?.toScope();
1468 const owner_decl = ty.getOwnerDecl();1474 const owner_decl = ty.getOwnerDecl();
14691475
1470 const name = try ty.nameAlloc(gpa, target);1476 const name = try ty.nameAlloc(gpa, target);
...@@ -1483,8 +1489,7 @@ pub const Object = struct {...@@ -1483,8 +1489,7 @@ pub const Object = struct {
1483 break :blk fwd_decl;1489 break :blk fwd_decl;
1484 };1490 };
14851491
1486 const TODO_implement_this = true; // TODO1492 if (!ty.hasRuntimeBitsIgnoreComptime()) {
1487 if (TODO_implement_this or !ty.hasRuntimeBitsIgnoreComptime()) {
1488 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);1493 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl);
1489 dib.replaceTemporary(fwd_decl, union_di_ty);1494 dib.replaceTemporary(fwd_decl, union_di_ty);
1490 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`1495 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
...@@ -1493,70 +1498,145 @@ pub const Object = struct {...@@ -1493,70 +1498,145 @@ pub const Object = struct {
1493 return union_di_ty;1498 return union_di_ty;
1494 }1499 }
14951500
1496 @panic("TODO debug info type for union");1501 const layout = ty.unionGetLayout(target);
1497 //const gop = try o.type_map.getOrPut(gpa, ty);1502 const union_obj = ty.cast(Type.Payload.Union).?.data;
1498 //if (gop.found_existing) return gop.value_ptr.*;1503
14991504 if (layout.payload_size == 0) {
1500 //// The Type memory is ephemeral; since we want to store a longer-lived1505 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
1501 //// reference, we need to copy it here.1506 const di_fields = [_]*llvm.DIType{tag_di_ty};
1502 //gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());1507 const full_di_ty = dib.createStructType(
15031508 compile_unit_scope,
1504 //const layout = ty.unionGetLayout(target);1509 name.ptr,
1505 //const union_obj = ty.cast(Type.Payload.Union).?.data;1510 null, // file
15061511 0, // line
1507 //if (layout.payload_size == 0) {1512 ty.abiSize(target) * 8, // size in bits
1508 // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);1513 ty.abiAlignment(target) * 8, // align in bits
1509 // gop.value_ptr.* = enum_tag_llvm_ty;1514 0, // flags
1510 // return enum_tag_llvm_ty;1515 null, // derived from
1511 //}1516 &di_fields,
15121517 di_fields.len,
1513 //const name = try union_obj.getFullyQualifiedName(gpa);1518 0, // run time lang
1514 //defer gpa.free(name);1519 null, // vtable holder
15151520 "", // unique id
1516 //const llvm_union_ty = dg.context.structCreateNamed(name);1521 );
1517 //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls1522 dib.replaceTemporary(fwd_decl, full_di_ty);
15181523 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
1519 //const aligned_field = union_obj.fields.values()[layout.most_aligned_field];1524 // means we can't use `gop` anymore.
1520 //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty);1525 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target });
15211526 return full_di_ty;
1522 //const llvm_payload_ty = ty: {1527 }
1523 // if (layout.most_aligned_field_size == layout.payload_size) {1528
1524 // break :ty llvm_aligned_field_ty;1529 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
1525 // }1530 defer di_fields.deinit(gpa);
1526 // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size);1531
1527 // const fields: [2]*const llvm.Type = .{1532 try di_fields.ensureUnusedCapacity(gpa, union_obj.fields.count());
1528 // llvm_aligned_field_ty,1533
1529 // dg.context.intType(8).arrayType(padding_len),1534 var it = union_obj.fields.iterator();
1530 // };1535 while (it.next()) |kv| {
1531 // break :ty dg.context.structType(&fields, fields.len, .True);1536 const field_name = kv.key_ptr.*;
1532 //};1537 const field = kv.value_ptr.*;
15331538
1534 //if (layout.tag_size == 0) {1539 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
1535 // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty};1540
1536 // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False);1541 const field_size = field.ty.abiSize(target);
1537 // return llvm_union_ty;1542 const field_align = field.normalAlignment(target);
1538 //}1543
1539 //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty);1544 const field_name_copy = try gpa.dupeZ(u8, field_name);
15401545 defer gpa.free(field_name_copy);
1541 //// Put the tag before or after the payload depending on which one's1546
1542 //// alignment is greater.1547 di_fields.appendAssumeCapacity(dib.createMemberType(
1543 //var llvm_fields: [3]*const llvm.Type = undefined;1548 fwd_decl.toScope(),
1544 //var llvm_fields_len: c_uint = 2;1549 field_name_copy,
15451550 null, // file
1546 //if (layout.tag_align >= layout.payload_align) {1551 0, // line
1547 // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined };1552 field_size * 8, // size in bits
1548 //} else {1553 field_align * 8, // align in bits
1549 // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined };1554 0, // offset in bits
1550 //}1555 0, // flags
15511556 try o.lowerDebugType(field.ty, .full),
1552 //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size.1557 ));
1553 //if (layout.padding != 0) {1558 }
1554 // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding);1559
1555 // llvm_fields_len = 3;1560 const union_name = if (layout.tag_size == 0) "AnonUnion" else name.ptr;
1556 //}1561
15571562 const union_di_ty = dib.createUnionType(
1558 //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False);1563 compile_unit_scope,
1559 //return llvm_union_ty;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;
1560 },1640 },
1561 .Fn => {1641 .Fn => {
1562 const fn_info = ty.fnInfo();1642 const fn_info = ty.fnInfo();
src/codegen/llvm/bindings.zig+1-1
...@@ -1601,7 +1601,7 @@ pub const DIBuilder = opaque {...@@ -1601,7 +1601,7 @@ pub const DIBuilder = opaque {
1601 dib: *DIBuilder,1601 dib: *DIBuilder,
1602 scope: *DIScope,1602 scope: *DIScope,
1603 name: [*:0]const u8,1603 name: [*:0]const u8,
1604 file: *DIFile,1604 file: ?*DIFile,
1605 line_number: c_uint,1605 line_number: c_uint,
1606 size_in_bits: u64,1606 size_in_bits: u64,
1607 align_in_bits: u64,1607 align_in_bits: u64,