|
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,73 @@ 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 | +#define ASSERT_DIFLAG_VALUE(FLAG, VALUE) \ |
| 690 | + static_assert((LLVMDI##FLAG == (VALUE)) && (DINode::DIFlags::FLAG == (VALUE))) |
| 691 | +ASSERT_DIFLAG_VALUE(FlagZero, 0); |
| 692 | +ASSERT_DIFLAG_VALUE(FlagPrivate, 1); |
| 693 | +ASSERT_DIFLAG_VALUE(FlagProtected, 2); |
| 694 | +ASSERT_DIFLAG_VALUE(FlagPublic, 3); |
| 695 | +// Bit (1 << 1) is part of the private/protected/public values above. |
| 696 | +ASSERT_DIFLAG_VALUE(FlagFwdDecl, 1 << 2); |
| 697 | +ASSERT_DIFLAG_VALUE(FlagAppleBlock, 1 << 3); |
| 698 | +ASSERT_DIFLAG_VALUE(FlagReservedBit4, 1 << 4); |
| 699 | +ASSERT_DIFLAG_VALUE(FlagVirtual, 1 << 5); |
| 700 | +ASSERT_DIFLAG_VALUE(FlagArtificial, 1 << 6); |
| 701 | +ASSERT_DIFLAG_VALUE(FlagExplicit, 1 << 7); |
| 702 | +ASSERT_DIFLAG_VALUE(FlagPrototyped, 1 << 8); |
| 703 | +ASSERT_DIFLAG_VALUE(FlagObjcClassComplete, 1 << 9); |
| 704 | +ASSERT_DIFLAG_VALUE(FlagObjectPointer, 1 << 10); |
| 705 | +ASSERT_DIFLAG_VALUE(FlagVector, 1 << 11); |
| 706 | +ASSERT_DIFLAG_VALUE(FlagStaticMember, 1 << 12); |
| 707 | +ASSERT_DIFLAG_VALUE(FlagLValueReference, 1 << 13); |
| 708 | +ASSERT_DIFLAG_VALUE(FlagRValueReference, 1 << 14); |
| 709 | +// Bit (1 << 15) has been recycled, but the C API value hasn't been renamed. |
| 710 | +static_assert((LLVMDIFlagReserved == (1 << 15)) && |
| 711 | + (DINode::DIFlags::FlagExportSymbols == (1 << 15))); |
| 712 | +ASSERT_DIFLAG_VALUE(FlagSingleInheritance, 1 << 16); |
| 713 | +ASSERT_DIFLAG_VALUE(FlagMultipleInheritance, 2 << 16); |
| 714 | +ASSERT_DIFLAG_VALUE(FlagVirtualInheritance, 3 << 16); |
| 715 | +// Bit (1 << 17) is part of the inheritance values above. |
| 716 | +ASSERT_DIFLAG_VALUE(FlagIntroducedVirtual, 1 << 18); |
| 717 | +ASSERT_DIFLAG_VALUE(FlagBitField, 1 << 19); |
| 718 | +ASSERT_DIFLAG_VALUE(FlagNoReturn, 1 << 20); |
| 719 | +// Bit (1 << 21) is unused, but was `LLVMDIFlagMainSubprogram`. |
| 720 | +ASSERT_DIFLAG_VALUE(FlagTypePassByValue, 1 << 22); |
| 721 | +ASSERT_DIFLAG_VALUE(FlagTypePassByReference, 1 << 23); |
| 722 | +ASSERT_DIFLAG_VALUE(FlagEnumClass, 1 << 24); |
| 723 | +ASSERT_DIFLAG_VALUE(FlagThunk, 1 << 25); |
| 724 | +ASSERT_DIFLAG_VALUE(FlagNonTrivial, 1 << 26); |
| 725 | +ASSERT_DIFLAG_VALUE(FlagBigEndian, 1 << 27); |
| 726 | +ASSERT_DIFLAG_VALUE(FlagLittleEndian, 1 << 28); |
| 727 | +ASSERT_DIFLAG_VALUE(FlagIndirectVirtualBase, (1 << 2) | (1 << 5)); |
| 728 | +#undef ASSERT_DIFLAG_VALUE |
| 729 | + |
| 730 | +// There are two potential ways to convert `LLVMDIFlags` to `DIFlags`: |
| 731 | +// - Check and copy every individual bit/subvalue from input to output. |
| 732 | +// - Statically assert that both have the same layout, and cast. |
| 733 | +// As long as the static assertions succeed, a cast is easier and faster. |
| 734 | +// In the (hopefully) unlikely event that the assertions do fail someday, and |
| 735 | +// LLVM doesn't expose its own conversion function, we'll have to switch over |
| 736 | +// to copying each bit/subvalue. |
| 737 | +static DINode::DIFlags fromRust(LLVMDIFlags Flags) { |
| 738 | + // Check that all set bits are covered by the static assertions above. |
| 739 | + const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 21); |
| 740 | + if (Flags & UNKNOWN_BITS) { |
| 741 | + report_fatal_error("bad LLVMDIFlags"); |
| 742 | + } |
| 743 | + |
| 744 | + // As long as the static assertions are satisfied and no unknown bits are |
| 745 | + // present, we can convert from `LLVMDIFlags` to `DIFlags` with a cast. |
| 746 | + return static_cast<DINode::DIFlags>(Flags); |
793 | 747 | } |
794 | 748 |
|
795 | 749 | // These values **must** match debuginfo::DISPFlags! They also *happen* |
|
0 commit comments