|
2 | 2 |
|
3 | 3 | #include "llvm-c/Analysis.h"
|
4 | 4 | #include "llvm-c/Core.h"
|
| 5 | +#include "llvm-c/DebugInfo.h" |
5 | 6 | #include "llvm/ADT/ArrayRef.h"
|
6 | 7 | #include "llvm/ADT/SmallVector.h"
|
7 | 8 | #include "llvm/ADT/Statistic.h"
|
@@ -676,120 +677,84 @@ template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
|
676 | 677 | #define DIArray DINodeArray
|
677 | 678 | #define unwrapDI unwrapDIPtr
|
678 | 679 |
|
679 |
| -// These values **must** match debuginfo::DIFlags! They also *happen* |
680 |
| -// to match LLVM, but that isn't required as we do giant sets of |
681 |
| -// matching below. The value shouldn't be directly passed to LLVM. |
682 |
| -enum class LLVMRustDIFlags : uint32_t { |
683 |
| - FlagZero = 0, |
684 |
| - FlagPrivate = 1, |
685 |
| - FlagProtected = 2, |
686 |
| - FlagPublic = 3, |
687 |
| - FlagFwdDecl = (1 << 2), |
688 |
| - FlagAppleBlock = (1 << 3), |
689 |
| - FlagBlockByrefStruct = (1 << 4), |
690 |
| - FlagVirtual = (1 << 5), |
691 |
| - FlagArtificial = (1 << 6), |
692 |
| - FlagExplicit = (1 << 7), |
693 |
| - FlagPrototyped = (1 << 8), |
694 |
| - FlagObjcClassComplete = (1 << 9), |
695 |
| - FlagObjectPointer = (1 << 10), |
696 |
| - FlagVector = (1 << 11), |
697 |
| - FlagStaticMember = (1 << 12), |
698 |
| - FlagLValueReference = (1 << 13), |
699 |
| - FlagRValueReference = (1 << 14), |
700 |
| - FlagExternalTypeRef = (1 << 15), |
701 |
| - FlagIntroducedVirtual = (1 << 18), |
702 |
| - FlagBitField = (1 << 19), |
703 |
| - FlagNoReturn = (1 << 20), |
704 |
| - // Do not add values that are not supported by the minimum LLVM |
705 |
| - // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def |
706 |
| -}; |
707 |
| - |
708 |
| -inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) { |
709 |
| - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) & |
710 |
| - static_cast<uint32_t>(B)); |
711 |
| -} |
712 |
| - |
713 |
| -inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) { |
714 |
| - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) | |
715 |
| - static_cast<uint32_t>(B)); |
716 |
| -} |
717 |
| - |
718 |
| -inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) { |
719 |
| - return A = A | B; |
720 |
| -} |
721 |
| - |
722 |
| -inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; } |
723 |
| - |
724 |
| -inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) { |
725 |
| - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3); |
726 |
| -} |
727 |
| - |
728 |
| -static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { |
729 |
| - DINode::DIFlags Result = DINode::DIFlags::FlagZero; |
730 |
| - |
731 |
| - switch (visibility(Flags)) { |
732 |
| - case LLVMRustDIFlags::FlagPrivate: |
733 |
| - Result |= DINode::DIFlags::FlagPrivate; |
734 |
| - break; |
735 |
| - case LLVMRustDIFlags::FlagProtected: |
736 |
| - Result |= DINode::DIFlags::FlagProtected; |
737 |
| - break; |
738 |
| - case LLVMRustDIFlags::FlagPublic: |
739 |
| - Result |= DINode::DIFlags::FlagPublic; |
740 |
| - break; |
741 |
| - default: |
742 |
| - // The rest are handled below |
743 |
| - break; |
744 |
| - } |
745 |
| - |
746 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) { |
747 |
| - Result |= DINode::DIFlags::FlagFwdDecl; |
748 |
| - } |
749 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { |
750 |
| - Result |= DINode::DIFlags::FlagAppleBlock; |
751 |
| - } |
752 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { |
753 |
| - Result |= DINode::DIFlags::FlagVirtual; |
754 |
| - } |
755 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) { |
756 |
| - Result |= DINode::DIFlags::FlagArtificial; |
757 |
| - } |
758 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) { |
759 |
| - Result |= DINode::DIFlags::FlagExplicit; |
760 |
| - } |
761 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) { |
762 |
| - Result |= DINode::DIFlags::FlagPrototyped; |
763 |
| - } |
764 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) { |
765 |
| - Result |= DINode::DIFlags::FlagObjcClassComplete; |
766 |
| - } |
767 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) { |
768 |
| - Result |= DINode::DIFlags::FlagObjectPointer; |
769 |
| - } |
770 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagVector)) { |
771 |
| - Result |= DINode::DIFlags::FlagVector; |
772 |
| - } |
773 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) { |
774 |
| - Result |= DINode::DIFlags::FlagStaticMember; |
775 |
| - } |
776 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) { |
777 |
| - Result |= DINode::DIFlags::FlagLValueReference; |
778 |
| - } |
779 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) { |
780 |
| - Result |= DINode::DIFlags::FlagRValueReference; |
781 |
| - } |
782 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) { |
783 |
| - Result |= DINode::DIFlags::FlagIntroducedVirtual; |
784 |
| - } |
785 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) { |
786 |
| - Result |= DINode::DIFlags::FlagBitField; |
787 |
| - } |
788 |
| - if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) { |
789 |
| - Result |= DINode::DIFlags::FlagNoReturn; |
790 |
| - } |
791 |
| - |
792 |
| - return Result; |
| 680 | +// FIXME(Zalathar): This is a temporary typedef to avoid churning dozens of |
| 681 | +// bindings that are going to be deleted and replaced with their LLVM-C |
| 682 | +// equivalents, as part of #134009. After that happens, the remaining bindings |
| 683 | +// can be adjusted to use `LLVMDIFlags` instead of relying on this typedef. |
| 684 | +typedef LLVMDIFlags LLVMRustDIFlags; |
| 685 | + |
| 686 | +// Statically assert that `LLVMDIFlags` (C) and `DIFlags` (C++) have the same |
| 687 | +// layout, at least for the flags we know about. This isn't guaranteed, but is |
| 688 | +// likely to remain true, and as long as it is true it makes conversions easy. |
| 689 | +namespace { |
| 690 | +using DIFlags = DINode::DIFlags; |
| 691 | +constexpr bool eq(LLVMDIFlags CFlags, unsigned Value, DIFlags CxxFlags) { |
| 692 | + return (CFlags == Value) && (CxxFlags == Value); |
| 693 | +} |
| 694 | + |
| 695 | +static_assert(eq(LLVMDIFlagZero, 0, DIFlags::FlagZero)); |
| 696 | +static_assert(eq(LLVMDIFlagPrivate, 1, DIFlags::FlagPrivate)); |
| 697 | +static_assert(eq(LLVMDIFlagProtected, 2, DIFlags::FlagProtected)); |
| 698 | +static_assert(eq(LLVMDIFlagPublic, 3, DIFlags::FlagPublic)); |
| 699 | +static_assert(eq(LLVMDIFlagFwdDecl, 1 << 2, DIFlags::FlagFwdDecl)); |
| 700 | +static_assert(eq(LLVMDIFlagAppleBlock, 1 << 3, DIFlags::FlagAppleBlock)); |
| 701 | +static_assert(eq(LLVMDIFlagReservedBit4, 1 << 4, DIFlags::FlagReservedBit4)); |
| 702 | +static_assert(eq(LLVMDIFlagVirtual, 1 << 5, DIFlags::FlagVirtual)); |
| 703 | +static_assert(eq(LLVMDIFlagArtificial, 1 << 6, DIFlags::FlagArtificial)); |
| 704 | +static_assert(eq(LLVMDIFlagExplicit, 1 << 7, DIFlags::FlagExplicit)); |
| 705 | +static_assert(eq(LLVMDIFlagPrototyped, 1 << 8, DIFlags::FlagPrototyped)); |
| 706 | +static_assert(eq(LLVMDIFlagObjcClassComplete, 1 << 9, |
| 707 | + DIFlags::FlagObjcClassComplete)); |
| 708 | +static_assert(eq(LLVMDIFlagObjectPointer, 1 << 10, DIFlags::FlagObjectPointer)); |
| 709 | +static_assert(eq(LLVMDIFlagVector, 1 << 11, DIFlags::FlagVector)); |
| 710 | +static_assert(eq(LLVMDIFlagStaticMember, 1 << 12, DIFlags::FlagStaticMember)); |
| 711 | +static_assert(eq(LLVMDIFlagLValueReference, 1 << 13, |
| 712 | + DIFlags::FlagLValueReference)); |
| 713 | +static_assert(eq(LLVMDIFlagRValueReference, 1 << 14, |
| 714 | + DIFlags::FlagRValueReference)); |
| 715 | +// This flag has been recycled, but the value in the C API hasn't been renamed. |
| 716 | +static_assert(eq(LLVMDIFlagReserved, 1 << 15, DIFlags::FlagExportSymbols)); |
| 717 | +static_assert(eq(LLVMDIFlagSingleInheritance, 1 << 16, |
| 718 | + DIFlags::FlagSingleInheritance)); |
| 719 | +static_assert(eq(LLVMDIFlagMultipleInheritance, 2 << 16, |
| 720 | + DIFlags::FlagMultipleInheritance)); |
| 721 | +static_assert(eq(LLVMDIFlagVirtualInheritance, 3 << 16, |
| 722 | + DIFlags::FlagVirtualInheritance)); |
| 723 | +static_assert(eq(LLVMDIFlagIntroducedVirtual, 1 << 18, |
| 724 | + DIFlags::FlagIntroducedVirtual)); |
| 725 | +static_assert(eq(LLVMDIFlagBitField, 1 << 19, DIFlags::FlagBitField)); |
| 726 | +static_assert(eq(LLVMDIFlagNoReturn, 1 << 20, DIFlags::FlagNoReturn)); |
| 727 | +// The bit at (1 << 21) is unused, but was `LLVMDIFlagMainSubprogram`. |
| 728 | +static_assert(eq(LLVMDIFlagTypePassByValue, 1 << 22, |
| 729 | + DIFlags::FlagTypePassByValue)); |
| 730 | +static_assert(eq(LLVMDIFlagTypePassByReference, 1 << 23, |
| 731 | + DIFlags::FlagTypePassByReference)); |
| 732 | +static_assert(eq(LLVMDIFlagEnumClass, 1 << 24, DIFlags::FlagEnumClass)); |
| 733 | +static_assert(eq(LLVMDIFlagThunk, 1 << 25, DIFlags::FlagThunk)); |
| 734 | +static_assert(eq(LLVMDIFlagNonTrivial, 1 << 26, DIFlags::FlagNonTrivial)); |
| 735 | +static_assert(eq(LLVMDIFlagBigEndian, 1 << 27, DIFlags::FlagBigEndian)); |
| 736 | +static_assert(eq(LLVMDIFlagLittleEndian, 1 << 28, DIFlags::FlagLittleEndian)); |
| 737 | +static_assert(eq(LLVMDIFlagIndirectVirtualBase, (1 << 2) | (1 << 5), |
| 738 | + DIFlags::FlagIndirectVirtualBase)); |
| 739 | +} // namespace |
| 740 | + |
| 741 | +// There are two potential ways to convert `LLVMDIFlags` to `DIFlags`: |
| 742 | +// - Check and copy every individual bit/subvalue from input to output. |
| 743 | +// - Statically assert that both have the same layout, and cast. |
| 744 | +// As long as the static assertions succeed, a cast is easier and faster. |
| 745 | +// In the (hopefully) unlikely event that the assertions do fail someday, and |
| 746 | +// LLVM doesn't expose its own conversion function, we'll have to switch over |
| 747 | +// to copying each bit/subvalue. |
| 748 | +static DINode::DIFlags fromRust(LLVMDIFlags Flags) { |
| 749 | + // Check that all set bits are covered by the static assertions above. |
| 750 | + const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 21); |
| 751 | + if (Flags & UNKNOWN_BITS) { |
| 752 | + report_fatal_error("bad LLVMDIFlags"); |
| 753 | + } |
| 754 | + |
| 755 | + // As long as the static assertions are satisfied and no unknown bits are |
| 756 | + // present, we can convert from `LLVMDIFlags` to `DIFlags` with a cast. |
| 757 | + return static_cast<DINode::DIFlags>(Flags); |
793 | 758 | }
|
794 | 759 |
|
795 | 760 | // These values **must** match debuginfo::DISPFlags! They also *happen*
|
|
0 commit comments