| ... | @@ -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); |
| ... | @@ -1471,16 +1476,6 @@ pub const Object = struct { | ... | @@ -1471,16 +1476,6 @@ pub const Object = struct { |
| 1471 | const name = try ty.nameAlloc(gpa, target); | 1476 | const name = try ty.nameAlloc(gpa, target); |
| 1472 | defer gpa.free(name); | 1477 | defer gpa.free(name); |
| 1473 | | 1478 | |
| 1474 | if (ty.cast(Type.Payload.Union)) |payload| { | | |
| 1475 | const union_obj = payload.data; | | |
| 1476 | if (union_obj.layout == .Packed) { | | |
| 1477 | const bit_size = ty.bitSize(target); | | |
| 1478 | const di_ty = dib.createBasicType(name, bit_size, DW.ATE.unsigned); | | |
| 1479 | gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty); | | |
| 1480 | return di_ty; | | |
| 1481 | } | | |
| 1482 | } | | |
| 1483 | | | |
| 1484 | const fwd_decl = opt_fwd_decl orelse blk: { | 1479 | const fwd_decl = opt_fwd_decl orelse blk: { |
| 1485 | const fwd_decl = dib.createReplaceableCompositeType( | 1480 | const fwd_decl = dib.createReplaceableCompositeType( |
| 1486 | DW.TAG.structure_type, | 1481 | DW.TAG.structure_type, |
| ... | @@ -1494,12 +1489,7 @@ pub const Object = struct { | ... | @@ -1494,12 +1489,7 @@ pub const Object = struct { |
| 1494 | break :blk fwd_decl; | 1489 | break :blk fwd_decl; |
| 1495 | }; | 1490 | }; |
| 1496 | | 1491 | |
| 1497 | const union_obj = ty.cast(Type.Payload.Union).?.data; | 1492 | if (!ty.hasRuntimeBitsIgnoreComptime()) { |
| 1498 | | | |
| 1499 | // TODO COPYPASTE >>> | | |
| 1500 | if (!union_obj.haveFieldTypes()) { | | |
| 1501 | // TODO: improve the frontend to populate this union. | | |
| 1502 | // For now we treat it as a zero bit type. | | |
| 1503 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); | 1493 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); |
| 1504 | dib.replaceTemporary(fwd_decl, union_di_ty); | 1494 | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 1505 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` | 1495 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| ... | @@ -1507,15 +1497,33 @@ pub const Object = struct { | ... | @@ -1507,15 +1497,33 @@ pub const Object = struct { |
| 1507 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); | 1497 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); |
| 1508 | return union_di_ty; | 1498 | return union_di_ty; |
| 1509 | } | 1499 | } |
| 1510 | // TODO <<< | | |
| 1511 | | 1500 | |
| 1512 | if (!ty.hasRuntimeBitsIgnoreComptime()) { | 1501 | const layout = ty.unionGetLayout(target); |
| 1513 | const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl); | 1502 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| 1514 | dib.replaceTemporary(fwd_decl, union_di_ty); | 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); |
| 1515 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` | 1523 | // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` |
| 1516 | // means we can't use `gop` anymore. | 1524 | // means we can't use `gop` anymore. |
| 1517 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); | 1525 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); |
| 1518 | return union_di_ty; | 1526 | return full_di_ty; |
| 1519 | } | 1527 | } |
| 1520 | | 1528 | |
| 1521 | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; | 1529 | var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{}; |
| ... | @@ -1523,8 +1531,8 @@ pub const Object = struct { | ... | @@ -1523,8 +1531,8 @@ pub const Object = struct { |
| 1523 | | 1531 | |
| 1524 | try di_fields.ensureUnusedCapacity(gpa, union_obj.fields.count()); | 1532 | try di_fields.ensureUnusedCapacity(gpa, union_obj.fields.count()); |
| 1525 | | 1533 | |
| 1526 | var field_iterator = union_obj.fields.iterator(); | 1534 | var it = union_obj.fields.iterator(); |
| 1527 | while (field_iterator.next()) |kv| { | 1535 | while (it.next()) |kv| { |
| 1528 | const field_name = kv.key_ptr.*; | 1536 | const field_name = kv.key_ptr.*; |
| 1529 | const field = kv.value_ptr.*; | 1537 | const field = kv.value_ptr.*; |
| 1530 | | 1538 | |
| ... | @@ -1536,7 +1544,7 @@ pub const Object = struct { | ... | @@ -1536,7 +1544,7 @@ pub const Object = struct { |
| 1536 | const field_name_copy = try gpa.dupeZ(u8, field_name); | 1544 | const field_name_copy = try gpa.dupeZ(u8, field_name); |
| 1537 | defer gpa.free(field_name_copy); | 1545 | defer gpa.free(field_name_copy); |
| 1538 | | 1546 | |
| 1539 | try di_fields.append(gpa, dib.createMemberType( | 1547 | di_fields.appendAssumeCapacity(dib.createMemberType( |
| 1540 | fwd_decl.toScope(), | 1548 | fwd_decl.toScope(), |
| 1541 | field_name_copy, | 1549 | field_name_copy, |
| 1542 | null, // file | 1550 | null, // file |
| ... | @@ -1549,31 +1557,11 @@ pub const Object = struct { | ... | @@ -1549,31 +1557,11 @@ pub const Object = struct { |
| 1549 | )); | 1557 | )); |
| 1550 | } | 1558 | } |
| 1551 | | 1559 | |
| 1552 | const tag_ty = union_obj.tag_ty; | 1560 | const union_name = if (layout.tag_size == 0) "AnonUnion" else name.ptr; |
| 1553 | if (!tag_ty.hasRuntimeBitsIgnoreComptime()) { | | |
| 1554 | const union_di_ty = dib.createUnionType( | | |
| 1555 | compile_unit_scope, | | |
| 1556 | name.ptr, | | |
| 1557 | null, // file | | |
| 1558 | 0, // line | | |
| 1559 | ty.abiSize(target) * 8, // size in bits | | |
| 1560 | ty.abiAlignment(target) * 8, // align in bits | | |
| 1561 | 0, // flags | | |
| 1562 | di_fields.items.ptr, | | |
| 1563 | @intCast(c_int, di_fields.items.len), | | |
| 1564 | 0, // run time lang | | |
| 1565 | "", // unique id | | |
| 1566 | ); | | |
| 1567 | | | |
| 1568 | dib.replaceTemporary(fwd_decl, union_di_ty); | | |
| 1569 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | | |
| 1570 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); | | |
| 1571 | return union_di_ty; | | |
| 1572 | } | | |
| 1573 | | 1561 | |
| 1574 | const union_di_ty = dib.createUnionType( | 1562 | const union_di_ty = dib.createUnionType( |
| 1575 | fwd_decl.toScope(), | 1563 | compile_unit_scope, |
| 1576 | "AnonUnion", | 1564 | union_name, |
| 1577 | null, // file | 1565 | null, // file |
| 1578 | 0, // line | 1566 | 0, // line |
| 1579 | ty.abiSize(target) * 8, // size in bits | 1567 | ty.abiSize(target) * 8, // size in bits |
| ... | @@ -1585,47 +1573,50 @@ pub const Object = struct { | ... | @@ -1585,47 +1573,50 @@ pub const Object = struct { |
| 1585 | "", // unique id | 1573 | "", // unique id |
| 1586 | ); | 1574 | ); |
| 1587 | | 1575 | |
| 1588 | const payload_size = ty.abiSize(target); | 1576 | if (layout.tag_size == 0) { |
| 1589 | const payload_align = ty.abiAlignment(target); | 1577 | dib.replaceTemporary(fwd_decl, union_di_ty); |
| 1590 | const tag_size = tag_ty.abiSize(target); | 1578 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1591 | const tag_align = tag_ty.abiAlignment(target); | 1579 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .target = o.target }); |
| 1592 | | 1580 | return union_di_ty; |
| 1593 | assert(tag_size > 0); | 1581 | } |
| 1594 | assert(tag_align > 0); | | |
| 1595 | | 1582 | |
| 1596 | var offset: u64 = 0; | 1583 | var tag_offset: u64 = undefined; |
| 1597 | offset += payload_size; | 1584 | var payload_offset: u64 = undefined; |
| 1598 | offset = std.mem.alignForwardGeneric(u64, offset, tag_align); | 1585 | if (layout.tag_align >= layout.payload_align) { |
| 1599 | const tag_offset = offset; | 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 | } |
| 1600 | | 1592 | |
| 1601 | const payload_di = dib.createMemberType( | 1593 | const tag_di = dib.createMemberType( |
| 1602 | fwd_decl.toScope(), | 1594 | fwd_decl.toScope(), |
| 1603 | "payload", | 1595 | "tag", |
| 1604 | null, // file | 1596 | null, // file |
| 1605 | 0, // line | 1597 | 0, // line |
| 1606 | payload_size * 8, // size in bits | 1598 | layout.tag_size * 8, |
| 1607 | payload_align * 8, // align in bits | 1599 | layout.tag_align * 8, // align in bits |
| 1608 | 0, // field_offset * 8, // offset in bits | 1600 | tag_offset * 8, // offset in bits |
| 1609 | 0, // flags | 1601 | 0, // flags |
| 1610 | union_di_ty, | 1602 | try o.lowerDebugType(union_obj.tag_ty, .full), |
| 1611 | ); | 1603 | ); |
| 1612 | | 1604 | |
| 1613 | const tag_di = dib.createMemberType( | 1605 | const payload_di = dib.createMemberType( |
| 1614 | fwd_decl.toScope(), | 1606 | fwd_decl.toScope(), |
| 1615 | "tag", | 1607 | "payload", |
| 1616 | null, // file | 1608 | null, // file |
| 1617 | 0, // line | 1609 | 0, // line |
| 1618 | tag_size * 8, // TODO: should this be multiplied by 8??? analyze.cpp:9237 | 1610 | layout.payload_size * 8, // size in bits |
| 1619 | tag_align * 8, // align in bits | 1611 | layout.payload_align * 8, // align in bits |
| 1620 | tag_offset * 8, // offset in bits | 1612 | payload_offset * 8, // offset in bits |
| 1621 | 0, // flags | 1613 | 0, // flags |
| 1622 | try o.lowerDebugType(tag_ty, .full), | 1614 | union_di_ty, |
| 1623 | ); | 1615 | ); |
| 1624 | | 1616 | |
| 1625 | const full_di_fields = [_]*llvm.DIType { | 1617 | const full_di_fields: [2]*llvm.DIType = |
| 1626 | payload_di, | 1618 | if (layout.tag_align >= layout.payload_align) |
| 1627 | tag_di, | 1619 | .{ tag_di, payload_di } else .{ payload_di, tag_di }; |
| 1628 | }; | | |
| 1629 | | 1620 | |
| 1630 | const full_di_ty = dib.createStructType( | 1621 | const full_di_ty = dib.createStructType( |
| 1631 | compile_unit_scope, | 1622 | compile_unit_scope, |
| ... | @@ -1637,7 +1628,7 @@ pub const Object = struct { | ... | @@ -1637,7 +1628,7 @@ pub const Object = struct { |
| 1637 | 0, // flags | 1628 | 0, // flags |
| 1638 | null, // derived from | 1629 | null, // derived from |
| 1639 | &full_di_fields, | 1630 | &full_di_fields, |
| 1640 | @intCast(c_int, full_di_fields.len), | 1631 | full_di_fields.len, |
| 1641 | 0, // run time lang | 1632 | 0, // run time lang |
| 1642 | null, // vtable holder | 1633 | null, // vtable holder |
| 1643 | "", // unique id | 1634 | "", // unique id |
| ... | @@ -1646,60 +1637,6 @@ pub const Object = struct { | ... | @@ -1646,60 +1637,6 @@ pub const Object = struct { |
| 1646 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. | 1637 | // The recursive call to `lowerDebugType` means we can't use `gop` anymore. |
| 1647 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); | 1638 | try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .target = o.target }); |
| 1648 | return full_di_ty; | 1639 | return full_di_ty; |
| 1649 | | | |
| 1650 | //if (layout.payload_size == 0) { | | |
| 1651 | // const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty); | | |
| 1652 | // gop.value_ptr.* = enum_tag_llvm_ty; | | |
| 1653 | // return enum_tag_llvm_ty; | | |
| 1654 | //} | | |
| 1655 | | | |
| 1656 | //const name = try union_obj.getFullyQualifiedName(gpa); | | |
| 1657 | //defer gpa.free(name); | | |
| 1658 | | | |
| 1659 | //const llvm_union_ty = dg.context.structCreateNamed(name); | | |
| 1660 | //gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls | | |
| 1661 | | | |
| 1662 | //const aligned_field = union_obj.fields.values()[layout.most_aligned_field]; | | |
| 1663 | //const llvm_aligned_field_ty = try dg.llvmType(aligned_field.ty); | | |
| 1664 | | | |
| 1665 | //const llvm_payload_ty = ty: { | | |
| 1666 | // if (layout.most_aligned_field_size == layout.payload_size) { | | |
| 1667 | // break :ty llvm_aligned_field_ty; | | |
| 1668 | // } | | |
| 1669 | // const padding_len = @intCast(c_uint, layout.payload_size - layout.most_aligned_field_size); | | |
| 1670 | // const fields: [2]*const llvm.Type = .{ | | |
| 1671 | // llvm_aligned_field_ty, | | |
| 1672 | // dg.context.intType(8).arrayType(padding_len), | | |
| 1673 | // }; | | |
| 1674 | // break :ty dg.context.structType(&fields, fields.len, .True); | | |
| 1675 | //}; | | |
| 1676 | | | |
| 1677 | //if (layout.tag_size == 0) { | | |
| 1678 | // var llvm_fields: [1]*const llvm.Type = .{llvm_payload_ty}; | | |
| 1679 | // llvm_union_ty.structSetBody(&llvm_fields, llvm_fields.len, .False); | | |
| 1680 | // return llvm_union_ty; | | |
| 1681 | //} | | |
| 1682 | //const enum_tag_llvm_ty = try dg.llvmType(union_obj.tag_ty); | | |
| 1683 | | | |
| 1684 | //// Put the tag before or after the payload depending on which one's | | |
| 1685 | //// alignment is greater. | | |
| 1686 | //var llvm_fields: [3]*const llvm.Type = undefined; | | |
| 1687 | //var llvm_fields_len: c_uint = 2; | | |
| 1688 | | | |
| 1689 | //if (layout.tag_align >= layout.payload_align) { | | |
| 1690 | // llvm_fields = .{ enum_tag_llvm_ty, llvm_payload_ty, undefined }; | | |
| 1691 | //} else { | | |
| 1692 | // llvm_fields = .{ llvm_payload_ty, enum_tag_llvm_ty, undefined }; | | |
| 1693 | //} | | |
| 1694 | | | |
| 1695 | //// Insert padding to make the LLVM struct ABI size match the Zig union ABI size. | | |
| 1696 | //if (layout.padding != 0) { | | |
| 1697 | // llvm_fields[2] = dg.context.intType(8).arrayType(layout.padding); | | |
| 1698 | // llvm_fields_len = 3; | | |
| 1699 | //} | | |
| 1700 | | | |
| 1701 | //llvm_union_ty.structSetBody(&llvm_fields, llvm_fields_len, .False); | | |
| 1702 | //return llvm_union_ty; | | |
| 1703 | }, | 1640 | }, |
| 1704 | .Fn => { | 1641 | .Fn => { |
| 1705 | const fn_info = ty.fnInfo(); | 1642 | const fn_info = ty.fnInfo(); |