diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-03 20:26:11 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-03 20:26:11 +0000 |
commit | 148779df305667b6942fee7e758fdf81a6498f38 (patch) | |
tree | 976d85fb9cb4bc8ed54348b045f742be90e10c57 /include | |
parent | a303c417bbdb53703c2c17398b08486bde78f1f6 (diff) |
Vendor import of llvm trunk r302069:vendor/llvm/llvm-trunk-r302069
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=317760
svn path=/vendor/llvm/llvm-trunk-r302069/; revision=317761; tag=vendor/llvm/llvm-trunk-r302069
Diffstat (limited to 'include')
35 files changed, 742 insertions, 365 deletions
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 6d74f344aad5..63c92c1a7fce 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -86,7 +86,7 @@ private: union { uint64_t VAL; ///< Used to store the <= 64 bits integer value. uint64_t *pVal; ///< Used to store the >64 bits integer value. - }; + } U; unsigned BitWidth; ///< The number of bits in this APInt. @@ -98,7 +98,9 @@ private: /// /// This constructor is used only internally for speed of construction of /// temporaries. It is unsafe for general use so it is not public. - APInt(uint64_t *val, unsigned bits) : pVal(val), BitWidth(bits) {} + APInt(uint64_t *val, unsigned bits) : BitWidth(bits) { + U.pVal = val; + } /// \brief Determine if this APInt just has one word to store value. /// @@ -143,16 +145,16 @@ private: // Mask out the high bits. uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - WordBits); if (isSingleWord()) - VAL &= mask; + U.VAL &= mask; else - pVal[getNumWords() - 1] &= mask; + U.pVal[getNumWords() - 1] &= mask; return *this; } /// \brief Get the word corresponding to a bit position /// \returns the corresponding word for the specified bit position. uint64_t getWord(unsigned bitPosition) const { - return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)]; } /// \brief Convert a char array into an APInt @@ -258,7 +260,7 @@ public: : BitWidth(numBits) { assert(BitWidth && "bitwidth too small"); if (isSingleWord()) { - VAL = val; + U.VAL = val; clearUnusedBits(); } else { initSlowCase(val, isSigned); @@ -300,20 +302,21 @@ public: /// @brief Copy Constructor. APInt(const APInt &that) : BitWidth(that.BitWidth) { if (isSingleWord()) - VAL = that.VAL; + U.VAL = that.U.VAL; else initSlowCase(that); } /// \brief Move Constructor. - APInt(APInt &&that) : VAL(that.VAL), BitWidth(that.BitWidth) { + APInt(APInt &&that) : BitWidth(that.BitWidth) { + memcpy(&U, &that.U, sizeof(U)); that.BitWidth = 0; } /// \brief Destructor. ~APInt() { if (needsCleanup()) - delete[] pVal; + delete[] U.pVal; } /// \brief Default constructor that creates an uninteresting APInt @@ -321,7 +324,7 @@ public: /// /// This is useful for object deserialization (pair this with the static /// method Read). - explicit APInt() : VAL(0), BitWidth(1) {} + explicit APInt() : BitWidth(1) { U.VAL = 0; } /// \brief Returns whether this instance allocated memory. bool needsCleanup() const { return !isSingleWord(); } @@ -373,7 +376,7 @@ public: /// This checks to see if the value has all bits of the APInt are set or not. bool isAllOnesValue() const { if (isSingleWord()) - return VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth); + return U.VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth); return countPopulationSlowCase() == BitWidth; } @@ -428,7 +431,7 @@ public: /// \returns true if the argument APInt value is a power of two > 0. bool isPowerOf2() const { if (isSingleWord()) - return isPowerOf2_64(VAL); + return isPowerOf2_64(U.VAL); return countPopulationSlowCase() == 1; } @@ -461,7 +464,7 @@ public: assert(numBits != 0 && "numBits must be non-zero"); assert(numBits <= BitWidth && "numBits out of range"); if (isSingleWord()) - return VAL == (WORD_MAX >> (APINT_BITS_PER_WORD - numBits)); + return U.VAL == (WORD_MAX >> (APINT_BITS_PER_WORD - numBits)); unsigned Ones = countTrailingOnesSlowCase(); return (numBits == Ones) && ((Ones + countLeadingZerosSlowCase()) == BitWidth); @@ -472,7 +475,7 @@ public: /// Ex. isMask(0x0000FFFFU) == true. bool isMask() const { if (isSingleWord()) - return isMask_64(VAL); + return isMask_64(U.VAL); unsigned Ones = countTrailingOnesSlowCase(); return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) == BitWidth); } @@ -481,7 +484,7 @@ public: /// the remainder zero. bool isShiftedMask() const { if (isSingleWord()) - return isShiftedMask_64(VAL); + return isShiftedMask_64(U.VAL); unsigned Ones = countPopulationSlowCase(); unsigned LeadZ = countLeadingZerosSlowCase(); return (Ones + LeadZ + countTrailingZeros()) == BitWidth; @@ -639,8 +642,8 @@ public: /// conversions. const uint64_t *getRawData() const { if (isSingleWord()) - return &VAL; - return &pVal[0]; + return &U.VAL; + return &U.pVal[0]; } /// @} @@ -686,7 +689,7 @@ public: /// \returns true if *this is zero, false otherwise. bool operator!() const { if (isSingleWord()) - return VAL == 0; + return U.VAL == 0; return countLeadingZerosSlowCase() == BitWidth; } @@ -700,7 +703,7 @@ public: APInt &operator=(const APInt &RHS) { // If the bitwidths are the same, we can avoid mucking with memory if (isSingleWord() && RHS.isSingleWord()) { - VAL = RHS.VAL; + U.VAL = RHS.U.VAL; BitWidth = RHS.BitWidth; return clearUnusedBits(); } @@ -713,11 +716,11 @@ public: APInt &operator=(APInt &&that) { assert(this != &that && "Self-move not supported"); if (!isSingleWord()) - delete[] pVal; + delete[] U.pVal; // Use memcpy so that type based alias analysis sees both VAL and pVal // as modified. - memcpy(&VAL, &that.VAL, sizeof(uint64_t)); + memcpy(&U, &that.U, sizeof(U)); BitWidth = that.BitWidth; that.BitWidth = 0; @@ -734,11 +737,11 @@ public: /// \returns *this after assignment of RHS value. APInt &operator=(uint64_t RHS) { if (isSingleWord()) { - VAL = RHS; + U.VAL = RHS; clearUnusedBits(); } else { - pVal[0] = RHS; - memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + U.pVal[0] = RHS; + memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); } return *this; } @@ -752,7 +755,7 @@ public: APInt &operator&=(const APInt &RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) - VAL &= RHS.VAL; + U.VAL &= RHS.U.VAL; else AndAssignSlowCase(RHS); return *this; @@ -765,11 +768,11 @@ public: /// the LHS. APInt &operator&=(uint64_t RHS) { if (isSingleWord()) { - VAL &= RHS; + U.VAL &= RHS; return *this; } - pVal[0] &= RHS; - memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + U.pVal[0] &= RHS; + memset(U.pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); return *this; } @@ -782,7 +785,7 @@ public: APInt &operator|=(const APInt &RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) - VAL |= RHS.VAL; + U.VAL |= RHS.U.VAL; else OrAssignSlowCase(RHS); return *this; @@ -795,10 +798,10 @@ public: /// the LHS. APInt &operator|=(uint64_t RHS) { if (isSingleWord()) { - VAL |= RHS; + U.VAL |= RHS; clearUnusedBits(); } else { - pVal[0] |= RHS; + U.pVal[0] |= RHS; } return *this; } @@ -812,7 +815,7 @@ public: APInt &operator^=(const APInt &RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) - VAL ^= RHS.VAL; + U.VAL ^= RHS.U.VAL; else XorAssignSlowCase(RHS); return *this; @@ -825,10 +828,10 @@ public: /// the LHS. APInt &operator^=(uint64_t RHS) { if (isSingleWord()) { - VAL ^= RHS; + U.VAL ^= RHS; clearUnusedBits(); } else { - pVal[0] ^= RHS; + U.pVal[0] ^= RHS; } return *this; } @@ -865,9 +868,9 @@ public: assert(ShiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { if (ShiftAmt == BitWidth) - VAL = 0; + U.VAL = 0; else - VAL <<= ShiftAmt; + U.VAL <<= ShiftAmt; return clearUnusedBits(); } shlSlowCase(ShiftAmt); @@ -913,11 +916,11 @@ public: void ashrInPlace(unsigned ShiftAmt) { assert(ShiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { - int64_t SExtVAL = SignExtend64(VAL, BitWidth); + int64_t SExtVAL = SignExtend64(U.VAL, BitWidth); if (ShiftAmt == BitWidth) - VAL = SExtVAL >> (APINT_BITS_PER_WORD - 1); // Fill with sign bit. + U.VAL = SExtVAL >> (APINT_BITS_PER_WORD - 1); // Fill with sign bit. else - VAL = SExtVAL >> ShiftAmt; + U.VAL = SExtVAL >> ShiftAmt; clearUnusedBits(); return; } @@ -938,9 +941,9 @@ public: assert(ShiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { if (ShiftAmt == BitWidth) - VAL = 0; + U.VAL = 0; else - VAL >>= ShiftAmt; + U.VAL >>= ShiftAmt; return; } lshrSlowCase(ShiftAmt); @@ -1059,7 +1062,7 @@ public: bool operator[](unsigned bitPosition) const { assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); return (maskBit(bitPosition) & - (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != + (isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)])) != 0; } @@ -1074,7 +1077,7 @@ public: bool operator==(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); if (isSingleWord()) - return VAL == RHS.VAL; + return U.VAL == RHS.U.VAL; return EqualSlowCase(RHS); } @@ -1265,7 +1268,7 @@ public: bool intersects(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) - return (VAL & RHS.VAL) != 0; + return (U.VAL & RHS.U.VAL) != 0; return intersectsSlowCase(RHS); } @@ -1273,7 +1276,7 @@ public: bool isSubsetOf(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) - return (VAL & ~RHS.VAL) == 0; + return (U.VAL & ~RHS.U.VAL) == 0; return isSubsetOfSlowCase(RHS); } @@ -1333,10 +1336,10 @@ public: /// \brief Set every bit to 1. void setAllBits() { if (isSingleWord()) - VAL = WORD_MAX; + U.VAL = WORD_MAX; else // Set all the bits in all the words. - memset(pVal, -1, getNumWords() * APINT_WORD_SIZE); + memset(U.pVal, -1, getNumWords() * APINT_WORD_SIZE); // Clear the unused ones clearUnusedBits(); } @@ -1348,9 +1351,9 @@ public: assert(BitPosition <= BitWidth && "BitPosition out of range"); WordType Mask = maskBit(BitPosition); if (isSingleWord()) - VAL |= Mask; + U.VAL |= Mask; else - pVal[whichWord(BitPosition)] |= Mask; + U.pVal[whichWord(BitPosition)] |= Mask; } /// Set the sign bit to 1. @@ -1369,9 +1372,9 @@ public: uint64_t mask = WORD_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); mask <<= loBit; if (isSingleWord()) - VAL |= mask; + U.VAL |= mask; else - pVal[0] |= mask; + U.pVal[0] |= mask; } else { setBitsSlowCase(loBit, hiBit); } @@ -1395,9 +1398,9 @@ public: /// \brief Set every bit to 0. void clearAllBits() { if (isSingleWord()) - VAL = 0; + U.VAL = 0; else - memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); + memset(U.pVal, 0, getNumWords() * APINT_WORD_SIZE); } /// \brief Set a given bit to 0. @@ -1407,9 +1410,9 @@ public: assert(BitPosition <= BitWidth && "BitPosition out of range"); WordType Mask = ~maskBit(BitPosition); if (isSingleWord()) - VAL &= Mask; + U.VAL &= Mask; else - pVal[whichWord(BitPosition)] &= Mask; + U.pVal[whichWord(BitPosition)] &= Mask; } /// Set the sign bit to 0. @@ -1420,7 +1423,7 @@ public: /// \brief Toggle every bit to its opposite value. void flipAllBits() { if (isSingleWord()) { - VAL ^= WORD_MAX; + U.VAL ^= WORD_MAX; clearUnusedBits(); } else { flipAllBitsSlowCase(); @@ -1500,9 +1503,9 @@ public: /// uint64_t. Otherwise an assertion will result. uint64_t getZExtValue() const { if (isSingleWord()) - return VAL; + return U.VAL; assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); - return pVal[0]; + return U.pVal[0]; } /// \brief Get sign extended value @@ -1512,9 +1515,9 @@ public: /// int64_t. Otherwise an assertion will result. int64_t getSExtValue() const { if (isSingleWord()) - return SignExtend64(VAL, BitWidth); + return SignExtend64(U.VAL, BitWidth); assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); - return int64_t(pVal[0]); + return int64_t(U.pVal[0]); } /// \brief Get bits required for string value. @@ -1534,7 +1537,7 @@ public: unsigned countLeadingZeros() const { if (isSingleWord()) { unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; - return llvm::countLeadingZeros(VAL) - unusedBits; + return llvm::countLeadingZeros(U.VAL) - unusedBits; } return countLeadingZerosSlowCase(); } @@ -1575,7 +1578,7 @@ public: /// of ones from the least significant bit to the first zero bit. unsigned countTrailingOnes() const { if (isSingleWord()) - return llvm::countTrailingOnes(VAL); + return llvm::countTrailingOnes(U.VAL); return countTrailingOnesSlowCase(); } @@ -1587,7 +1590,7 @@ public: /// \returns 0 if the value is zero, otherwise returns the number of set bits. unsigned countPopulation() const { if (isSingleWord()) - return llvm::countPopulation(VAL); + return llvm::countPopulation(U.VAL); return countPopulationSlowCase(); } @@ -1646,7 +1649,7 @@ public: uint64_t I; double D; } T; - T.I = (isSingleWord() ? VAL : pVal[0]); + T.I = (isSingleWord() ? U.VAL : U.pVal[0]); return T.D; } @@ -1660,7 +1663,7 @@ public: unsigned I; float F; } T; - T.I = unsigned((isSingleWord() ? VAL : pVal[0])); + T.I = unsigned((isSingleWord() ? U.VAL : U.pVal[0])); return T.F; } @@ -1718,7 +1721,7 @@ public: // get 0. If VAL is 0, we get WORD_MAX which gets truncated to // UINT32_MAX. if (BitWidth == 1) - return VAL - 1; + return U.VAL - 1; // Handle the zero case. if (isNullValue()) diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 317a5d3f54c8..0d898827efc6 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -346,29 +346,21 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features, Module &M) { for (auto &F : M) { auto &Ctx = F.getContext(); - AttributeList Attrs = F.getAttributes(), NewAttrs; + AttributeList Attrs = F.getAttributes(); + AttrBuilder NewAttrs; if (!CPU.empty()) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, - "target-cpu", CPU); - + NewAttrs.addAttribute("target-cpu", CPU); if (!Features.empty()) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, - "target-features", Features); - + NewAttrs.addAttribute("target-features", Features); if (DisableFPElim.getNumOccurrences() > 0) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, - "no-frame-pointer-elim", - DisableFPElim ? "true" : "false"); - + NewAttrs.addAttribute("no-frame-pointer-elim", + DisableFPElim ? "true" : "false"); if (DisableTailCalls.getNumOccurrences() > 0) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, - "disable-tail-calls", - toStringRef(DisableTailCalls)); - + NewAttrs.addAttribute("disable-tail-calls", + toStringRef(DisableTailCalls)); if (StackRealign) - NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex, - "stackrealign"); + NewAttrs.addAttribute("stackrealign"); if (TrapFuncName.getNumOccurrences() > 0) for (auto &B : F) @@ -382,8 +374,8 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features, Attribute::get(Ctx, "trap-func-name", TrapFuncName)); // Let NewAttrs override Attrs. - NewAttrs = Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs); - F.setAttributes(NewAttrs); + F.setAttributes( + Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs)); } } diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h index 086d6dff11c5..ac8aaafeadc1 100644 --- a/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -53,7 +53,7 @@ struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> { typedef void ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Len, - codeview::CVRecord<Kind> &Item, void *Ctx) { + codeview::CVRecord<Kind> &Item) { using namespace codeview; const RecordPrefix *Prefix = nullptr; BinaryStreamReader Reader(Stream); diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h b/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h index a5a3b851b841..6c08c9aa2137 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h @@ -21,6 +21,8 @@ namespace llvm { namespace codeview { +class StringTable; + struct FileChecksumEntry { uint32_t FileNameOffset; // Byte offset of filename in global stringtable. FileChecksumKind Kind; // The type of checksum. @@ -35,7 +37,7 @@ public: typedef void ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Len, - codeview::FileChecksumEntry &Item, void *Ctx); + codeview::FileChecksumEntry &Item); }; } @@ -55,8 +57,8 @@ public: Error initialize(BinaryStreamReader Reader); - Iterator begin() const { return Checksums.begin(); } - Iterator end() const { return Checksums.end(); } + Iterator begin() { return Checksums.begin(); } + Iterator end() { return Checksums.end(); } const FileChecksumArray &getArray() const { return Checksums; } @@ -66,20 +68,22 @@ private: class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment { public: - ModuleDebugFileChecksumFragment(); + explicit ModuleDebugFileChecksumFragment(StringTable &Strings); static bool classof(const ModuleDebugFragment *S) { return S->kind() == ModuleDebugFragmentKind::FileChecksums; } - void addChecksum(uint32_t StringTableOffset, FileChecksumKind Kind, + void addChecksum(StringRef FileName, FileChecksumKind Kind, ArrayRef<uint8_t> Bytes); uint32_t calculateSerializedLength() override; Error commit(BinaryStreamWriter &Writer) override; - uint32_t mapChecksumOffset(uint32_t StringTableOffset) const; + uint32_t mapChecksumOffset(StringRef FileName) const; private: + StringTable &Strings; + DenseMap<uint32_t, uint32_t> OffsetMap; uint32_t SerializedSize = 0; llvm::BumpPtrAllocator Storage; diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h b/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h index b98c8605592c..f68f21b224f1 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h @@ -57,8 +57,6 @@ private: ModuleDebugFragment &Frag; }; -typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray; - } // namespace codeview template <> @@ -66,13 +64,17 @@ struct VarStreamArrayExtractor<codeview::ModuleDebugFragmentRecord> { typedef void ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Length, - codeview::ModuleDebugFragmentRecord &Info, void *Ctx) { + codeview::ModuleDebugFragmentRecord &Info) { if (auto EC = codeview::ModuleDebugFragmentRecord::initialize(Stream, Info)) return EC; Length = Info.getRecordLength(); return Error::success(); } }; + +namespace codeview { +typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray; +} } // namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h b/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h index 177367c111c3..348497cbf7f2 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h @@ -20,6 +20,8 @@ namespace llvm { namespace codeview { class ModuleDebugInlineeLineFragmentRef; +class ModuleDebugFileChecksumFragment; +class StringTable; enum class InlineeLinesSignature : uint32_t { Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE @@ -42,11 +44,10 @@ struct InlineeSourceLine { } template <> struct VarStreamArrayExtractor<codeview::InlineeSourceLine> { - typedef codeview::ModuleDebugInlineeLineFragmentRef ContextType; + typedef bool ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Len, - codeview::InlineeSourceLine &Item, - ContextType *Fragment); + codeview::InlineeSourceLine &Item, bool HasExtraFiles); }; namespace codeview { @@ -74,7 +75,8 @@ private: class ModuleDebugInlineeLineFragment final : public ModuleDebugFragment { public: - explicit ModuleDebugInlineeLineFragment(bool HasExtraFiles); + ModuleDebugInlineeLineFragment(ModuleDebugFileChecksumFragment &Checksums, + bool HasExtraFiles); static bool classof(const ModuleDebugFragment *S) { return S->kind() == ModuleDebugFragmentKind::InlineeLines; @@ -83,11 +85,12 @@ public: Error commit(BinaryStreamWriter &Writer) override; uint32_t calculateSerializedLength() override; - void addInlineSite(TypeIndex FuncId, uint32_t FileOffset, - uint32_t SourceLine); - void addExtraFile(uint32_t FileOffset); + void addInlineSite(TypeIndex FuncId, StringRef FileName, uint32_t SourceLine); + void addExtraFile(StringRef FileName); private: + ModuleDebugFileChecksumFragment &Checksums; + bool HasExtraFiles = false; uint32_t ExtraFileCount = 0; diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h b/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h index dcfe86dd8503..3124236b8fb1 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h @@ -19,6 +19,9 @@ namespace llvm { namespace codeview { +class ModuleDebugFileChecksumFragment; +class StringTable; + // Corresponds to the `CV_DebugSLinesHeader_t` structure. struct LineFragmentHeader { support::ulittle32_t RelocOffset; // Code offset of line contribution. @@ -61,10 +64,10 @@ struct LineColumnEntry { class LineColumnExtractor { public: - typedef const LineFragmentHeader ContextType; + typedef const LineFragmentHeader *ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Len, - LineColumnEntry &Item, const LineFragmentHeader *Header); + LineColumnEntry &Item, const LineFragmentHeader *Ctx); }; class ModuleDebugLineFragmentRef final : public ModuleDebugFragmentRef { @@ -104,13 +107,14 @@ class ModuleDebugLineFragment final : public ModuleDebugFragment { }; public: - ModuleDebugLineFragment(); + ModuleDebugLineFragment(ModuleDebugFileChecksumFragment &Checksums, + StringTable &Strings); static bool classof(const ModuleDebugFragment *S) { return S->kind() == ModuleDebugFragmentKind::Lines; } - void createBlock(uint32_t ChecksumBufferOffset); + void createBlock(StringRef FileName); void addLineInfo(uint32_t Offset, const LineInfo &Line); void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, uint32_t ColStart, uint32_t ColEnd); @@ -125,6 +129,8 @@ public: bool hasColumnInfo() const; private: + ModuleDebugFileChecksumFragment &Checksums; + uint16_t RelocOffset = 0; uint16_t RelocSegment = 0; uint32_t CodeSize = 0; diff --git a/include/llvm/DebugInfo/CodeView/StringTable.h b/include/llvm/DebugInfo/CodeView/StringTable.h new file mode 100644 index 000000000000..05dc02ee849f --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/StringTable.h @@ -0,0 +1,75 @@ +//===- StringTable.h - CodeView String Table Reader/Writer ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H +#define LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Error.h" + +#include <stdint.h> + +namespace llvm { + +class BinaryStreamReader; +class BinaryStreamRef; +class BinaryStreamWriter; + +namespace codeview { + +/// Represents a read-only view of a CodeView string table. This is a very +/// simple flat buffer consisting of null-terminated strings, where strings +/// are retrieved by their offset in the buffer. StringTableRef does not own +/// the underlying storage for the buffer. +class StringTableRef { +public: + StringTableRef(); + + Error initialize(BinaryStreamRef Contents); + + Expected<StringRef> getString(uint32_t Offset) const; + + bool valid() const { return Stream.valid(); } + +private: + BinaryStreamRef Stream; +}; + +/// Represents a read-write view of a CodeView string table. StringTable owns +/// the underlying storage for the table, and is capable of serializing the +/// string table into a format understood by StringTableRef. +class StringTable { +public: + // If string S does not exist in the string table, insert it. + // Returns the ID for S. + uint32_t insert(StringRef S); + + // Return the ID for string S. Assumes S exists in the table. + uint32_t getStringId(StringRef S) const; + + uint32_t calculateSerializedSize() const; + Error commit(BinaryStreamWriter &Writer) const; + + uint32_t size() const; + + StringMap<uint32_t>::const_iterator begin() const { return Strings.begin(); } + + StringMap<uint32_t>::const_iterator end() const { return Strings.end(); } + +private: + StringMap<uint32_t> Strings; + uint32_t StringSize = 1; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h index 2bef3f61adfc..96c8a47a3669 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h +++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -19,13 +19,15 @@ class BinaryStreamReader; namespace codeview { +class StringTableRef; + class SymbolVisitorDelegate { public: virtual ~SymbolVisitorDelegate() = default; virtual uint32_t getRecordOffset(BinaryStreamReader Reader) = 0; virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; - virtual StringRef getStringTable() = 0; + virtual StringTableRef getStringTable() = 0; }; } // end namespace codeview diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h index 3c04c6716ea3..b9f3425d5deb 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -172,6 +172,9 @@ public: return DWOCUs[index].get(); } + /// Get a DIE given an exact offset. + DWARFDie getDIEForOffset(uint32_t Offset); + const DWARFUnitIndex &getCUIndex(); DWARFGdbIndex &getGdbIndex(); const DWARFUnitIndex &getTUIndex(); diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index dd0e2648bf30..e21245b97b73 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -30,7 +30,7 @@ public: struct FileNameEntry { FileNameEntry() = default; - const char *Name = nullptr; + StringRef Name = StringRef(); uint64_t DirIdx = 0; uint64_t ModTime = 0; uint64_t Length = 0; @@ -44,6 +44,10 @@ public: uint64_t TotalLength; /// Version identifier for the statement information format. uint16_t Version; + /// In v5, size in bytes of an address (or segment offset). + uint8_t AddressSize; + /// In v5, size in bytes of a segment selector. + uint8_t SegSelectorSize; /// The number of bytes following the prologue_length field to the beginning /// of the first byte of the statement program itself. uint64_t PrologueLength; @@ -63,7 +67,7 @@ public: /// The number assigned to the first special opcode. uint8_t OpcodeBase; std::vector<uint8_t> StandardOpcodeLengths; - std::vector<const char *> IncludeDirectories; + std::vector<StringRef> IncludeDirectories; std::vector<FileNameEntry> FileNames; bool IsDWARF64; @@ -100,7 +104,7 @@ public: void postAppend(); void reset(bool DefaultIsStmt); void dump(raw_ostream &OS) const; - + static void dumpTableHeader(raw_ostream &OS); static bool orderByAddress(const Row &LHS, const Row &RHS) { return LHS.Address < RHS.Address; } diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index e29ba523238c..68e541bac73c 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -312,9 +312,9 @@ public: [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) { return LHS.getOffset() < Offset; }); - if (it == DieArray.end()) - return DWARFDie(); - return DWARFDie(this, &*it); + if (it != DieArray.end() && it->getOffset() == Offset) + return DWARFDie(this, &*it); + return DWARFDie(); } uint32_t getLineTableOffset() const { diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h new file mode 100644 index 000000000000..8e12bcd2c8e2 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -0,0 +1,98 @@ +//===- DWARFVerifier.h ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H +#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H + +#include <cstdint> +#include <map> +#include <set> + +namespace llvm { +class raw_ostream; +struct DWARFAttribute; +class DWARFContext; +class DWARFDie; +class DWARFUnit; + +/// A class that verifies DWARF debug information given a DWARF Context. +class DWARFVerifier { + raw_ostream &OS; + DWARFContext &DCtx; + /// A map that tracks all references (converted absolute references) so we + /// can verify each reference points to a valid DIE and not an offset that + /// lies between to valid DIEs. + std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets; + uint32_t NumDebugInfoErrors; + uint32_t NumDebugLineErrors; + + /// Verifies the attribute's DWARF attribute and its value. + /// + /// This function currently checks for: + /// - DW_AT_ranges values is a valid .debug_ranges offset + /// - DW_AT_stmt_list is a valid .debug_line offset + /// + /// @param Die The DWARF DIE that owns the attribute value + /// @param AttrValue The DWARF attribute value to check + void verifyDebugInfoAttribute(DWARFDie &Die, DWARFAttribute &AttrValue); + + /// Verifies the attribute's DWARF form. + /// + /// This function currently checks for: + /// - All DW_FORM_ref values that are CU relative have valid CU offsets + /// - All DW_FORM_ref_addr values have valid .debug_info offsets + /// - All DW_FORM_strp values have valid .debug_str offsets + /// + /// @param Die The DWARF DIE that owns the attribute value + /// @param AttrValue The DWARF attribute value to check + void verifyDebugInfoForm(DWARFDie &Die, DWARFAttribute &AttrValue); + + /// Verifies the all valid references that were found when iterating through + /// all of the DIE attributes. + /// + /// This function will verify that all references point to DIEs whose DIE + /// offset matches. This helps to ensure if a DWARF link phase moved things + /// around, that it doesn't create invalid references by failing to relocate + /// CU relative and absolute references. + void veifyDebugInfoReferences(); + + /// Verify the the DW_AT_stmt_list encoding and value and ensure that no + /// compile units that have the same DW_AT_stmt_list value. + void verifyDebugLineStmtOffsets(); + + /// Verify that all of the rows in the line table are valid. + /// + /// This function currently checks for: + /// - addresses within a sequence that decrease in value + /// - invalid file indexes + void verifyDebugLineRows(); + +public: + DWARFVerifier(raw_ostream &S, DWARFContext &D) + : OS(S), DCtx(D), NumDebugInfoErrors(0), NumDebugLineErrors(0) {} + /// Verify the information in the .debug_info section. + /// + /// Any errors are reported to the stream that was this object was + /// constructed with. + /// + /// @return True if the .debug_info verifies successfully, false otherwise. + bool handleDebugInfo(); + + /// Verify the information in the .debug_line section. + /// + /// Any errors are reported to the stream that was this object was + /// constructed with. + /// + /// @return True if the .debug_line verifies successfully, false otherwise. + bool handleDebugLine(); +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h index 879cb4285cd7..d1f791b9daed 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -66,7 +66,7 @@ struct ModuleInfoEx { template <> struct VarStreamArrayExtractor<pdb::DbiModuleDescriptor> { typedef void ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Length, - pdb::DbiModuleDescriptor &Info, void *Ctx) { + pdb::DbiModuleDescriptor &Info) { if (auto EC = pdb::DbiModuleDescriptor::initialize(Stream, Info)) return EC; Length = Info.getRecordLength(); diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/include/llvm/DebugInfo/PDB/Native/DbiStream.h index 84ae57f2e23a..08262e47f77f 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -13,9 +13,9 @@ #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" -#include "llvm/DebugInfo/PDB/Native/StringTable.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamArray.h" @@ -91,7 +91,7 @@ private: std::unique_ptr<msf::MappedBlockStream> Stream; std::vector<ModuleInfoEx> ModuleInfos; - StringTable ECNames; + PDBStringTable ECNames; BinaryStreamRef ModInfoSubstream; BinaryStreamRef SecContrSubstream; diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/include/llvm/DebugInfo/PDB/Native/PDBFile.h index fbca62d6e9d9..3bed67141c56 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBFile.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -33,7 +33,7 @@ namespace pdb { class DbiStream; class GlobalsStream; class InfoStream; -class StringTable; +class PDBStringTable; class PDBFileBuilder; class PublicsStream; class SymbolStream; @@ -95,7 +95,7 @@ public: Expected<TpiStream &> getPDBIpiStream(); Expected<PublicsStream &> getPDBPublicsStream(); Expected<SymbolStream &> getPDBSymbolStream(); - Expected<StringTable &> getStringTable(); + Expected<PDBStringTable &> getStringTable(); BumpPtrAllocator &getAllocator() { return Allocator; } @@ -106,7 +106,7 @@ public: bool hasPDBPublicsStream(); bool hasPDBSymbolStream(); bool hasPDBTpiStream() const; - bool hasStringTable(); + bool hasPDBStringTable(); private: Expected<std::unique_ptr<msf::MappedBlockStream>> @@ -131,7 +131,7 @@ private: std::unique_ptr<SymbolStream> Symbols; std::unique_ptr<msf::MappedBlockStream> DirectoryStream; std::unique_ptr<msf::MappedBlockStream> StringTableStream; - std::unique_ptr<StringTable> Strings; + std::unique_ptr<PDBStringTable> Strings; }; } } diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h index 3898af5afc9e..cd7d3b063793 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -15,8 +15,8 @@ #include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" -#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -46,12 +46,14 @@ public: DbiStreamBuilder &getDbiBuilder(); TpiStreamBuilder &getTpiBuilder(); TpiStreamBuilder &getIpiBuilder(); - StringTableBuilder &getStringTableBuilder(); + PDBStringTableBuilder &getStringTableBuilder(); Error commit(StringRef Filename); -private: + Expected<uint32_t> getNamedStreamIndex(StringRef Name) const; Error addNamedStream(StringRef Name, uint32_t Size); + +private: Expected<msf::MSFLayout> finalizeMsfLayout(); BumpPtrAllocator &Allocator; @@ -62,7 +64,7 @@ private: std::unique_ptr<TpiStreamBuilder> Tpi; std::unique_ptr<TpiStreamBuilder> Ipi; - StringTableBuilder Strings; + PDBStringTableBuilder Strings; NamedStreamMap NamedStreams; }; } diff --git a/include/llvm/DebugInfo/PDB/Native/StringTable.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h index dd5e30e61827..7c7f16bd1c73 100644 --- a/include/llvm/DebugInfo/PDB/Native/StringTable.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -1,4 +1,4 @@ -//===- StringTable.h - PDB String Table -------------------------*- C++ -*-===// +//===- PDBStringTable.h - PDB String Table -----------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_PDB_RAW_STRINGTABLE_H -#define LLVM_DEBUGINFO_PDB_RAW_STRINGTABLE_H +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLE_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLE_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/StringTable.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" @@ -22,31 +23,38 @@ namespace llvm { class BinaryStreamReader; +namespace msf { +class MappedBlockStream; +} + namespace pdb { -class StringTable { -public: - StringTable(); +struct PDBStringTableHeader; - Error load(BinaryStreamReader &Stream); +class PDBStringTable { +public: + Error reload(BinaryStreamReader &Reader); uint32_t getByteSize() const; + uint32_t getNameCount() const; + uint32_t getHashVersion() const; + uint32_t getSignature() const; - uint32_t getNameCount() const { return NameCount; } - uint32_t getHashVersion() const { return HashVersion; } - uint32_t getSignature() const { return Signature; } - - StringRef getStringForID(uint32_t ID) const; - uint32_t getIDForString(StringRef Str) const; + Expected<StringRef> getStringForID(uint32_t ID) const; + Expected<uint32_t> getIDForString(StringRef Str) const; FixedStreamArray<support::ulittle32_t> name_ids() const; private: - BinaryStreamRef NamesBuffer; + Error readHeader(BinaryStreamReader &Reader); + Error readStrings(BinaryStreamReader &Reader); + Error readHashTable(BinaryStreamReader &Reader); + Error readEpilogue(BinaryStreamReader &Reader); + + const PDBStringTableHeader *Header = nullptr; + codeview::StringTableRef Strings; FixedStreamArray<support::ulittle32_t> IDs; uint32_t ByteSize = 0; - uint32_t Signature = 0; - uint32_t HashVersion = 0; uint32_t NameCount = 0; }; diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h new file mode 100644 index 000000000000..6f85e7a4a074 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -0,0 +1,60 @@ +//===- PDBStringTableBuilder.h - PDB String Table Builder -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file creates the "/names" stream. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLEBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLEBUILDER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/Support/Error.h" +#include <vector> + +namespace llvm { +class BinaryStreamWriter; +class WritableBinaryStreamRef; + +namespace msf { +struct MSFLayout; +} + +namespace pdb { + +class PDBFileBuilder; + +class PDBStringTableBuilder { +public: + // If string S does not exist in the string table, insert it. + // Returns the ID for S. + uint32_t insert(StringRef S); + + uint32_t calculateSerializedSize() const; + Error commit(BinaryStreamWriter &Writer) const; + + codeview::StringTable &getStrings() { return Strings; } + const codeview::StringTable &getStrings() const { return Strings; } + +private: + uint32_t calculateHashTableSize() const; + Error writeHeader(BinaryStreamWriter &Writer) const; + Error writeStrings(BinaryStreamWriter &Writer) const; + Error writeHashTable(BinaryStreamWriter &Writer) const; + Error writeEpilogue(BinaryStreamWriter &Writer) const; + + codeview::StringTable Strings; +}; + +} // end namespace pdb +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_RAW_PDBSTRINGTABLEBUILDER_H diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h index e1c6cf0021d5..93622d0a4394 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -307,13 +307,13 @@ struct InfoStreamHeader { }; /// The header preceeding the /names stream. -struct StringTableHeader { - support::ulittle32_t Signature; - support::ulittle32_t HashVersion; - support::ulittle32_t ByteSize; +struct PDBStringTableHeader { + support::ulittle32_t Signature; // PDBStringTableSignature + support::ulittle32_t HashVersion; // 1 or 2 + support::ulittle32_t ByteSize; // Number of bytes of names buffer. }; -const uint32_t StringTableSignature = 0xEFFEEFFE; +const uint32_t PDBStringTableSignature = 0xEFFEEFFE; } // namespace pdb } // namespace llvm diff --git a/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h b/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h deleted file mode 100644 index 9c4b12e33ba0..000000000000 --- a/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h +++ /dev/null @@ -1,45 +0,0 @@ -//===- StringTableBuilder.h - PDB String Table Builder ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file creates the "/names" stream. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_PDB_RAW_STRINGTABLEBUILDER_H -#define LLVM_DEBUGINFO_PDB_RAW_STRINGTABLEBUILDER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" -#include <vector> - -namespace llvm { -class BinaryStreamWriter; - -namespace pdb { - -class StringTableBuilder { -public: - // If string S does not exist in the string table, insert it. - // Returns the ID for S. - uint32_t insert(StringRef S); - uint32_t getStringIndex(StringRef S); - - uint32_t finalize(); - Error commit(BinaryStreamWriter &Writer) const; - -private: - DenseMap<StringRef, uint32_t> Strings; - uint32_t StringSize = 1; -}; - -} // end namespace pdb -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_PDB_RAW_STRINGTABLEBUILDER_H diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index af46034d5a9e..adcb7266073b 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -285,7 +285,8 @@ class AttributeList { public: enum AttrIndex : unsigned { ReturnIndex = 0U, - FunctionIndex = ~0U + FunctionIndex = ~0U, + FirstArgIndex = 1, }; private: @@ -336,6 +337,13 @@ public: static AttributeList get(LLVMContext &C, unsigned Index, const AttrBuilder &B); + /// Add an argument attribute to the list. Returns a new list because + /// attribute lists are immutable. + AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo, + Attribute::AttrKind Kind) const { + return addAttribute(C, ArgNo + FirstArgIndex, Kind); + } + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeList addAttribute(LLVMContext &C, unsigned Index, @@ -354,9 +362,6 @@ public: /// \brief Add attributes to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeList addAttributes(LLVMContext &C, unsigned Index, - AttributeList Attrs) const; - - AttributeList addAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &B) const; /// \brief Remove the specified attribute at the specified index from this @@ -375,13 +380,7 @@ public: /// attribute list. Because attribute lists are immutable, this returns the /// new list. AttributeList removeAttributes(LLVMContext &C, unsigned Index, - AttributeList Attrs) const; - - /// \brief Remove the specified attributes at the specified index from this - /// attribute list. Because attribute lists are immutable, this returns the - /// new list. - AttributeList removeAttributes(LLVMContext &C, unsigned Index, - const AttrBuilder &Attrs) const; + const AttrBuilder &AttrsToRemove) const; /// \brief Remove all attributes at the specified index from this /// attribute list. Because attribute lists are immutable, this returns the @@ -442,7 +441,7 @@ public: /// may be faster. bool hasFnAttribute(StringRef Kind) const; - /// \brief Equivalent to hasAttribute(ArgNo + 1, Kind). + /// \brief Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind). bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const; /// \brief Return true if the specified attribute is set for at least one diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index bad1d4e383d5..d61431a51a97 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -339,6 +339,10 @@ public: CALLSITE_DELEGATE_SETTER(addAttribute(i, Attr)); } + void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + CALLSITE_DELEGATE_SETTER(addParamAttr(ArgNo, Kind)); + } + void removeAttribute(unsigned i, Attribute::AttrKind Kind) { CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind)); } @@ -347,6 +351,10 @@ public: CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind)); } + void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + CALLSITE_DELEGATE_SETTER(removeParamAttr(ArgNo, Kind)); + } + /// Return true if this function has the given attribute. bool hasFnAttr(Attribute::AttrKind Kind) const { CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind)); @@ -408,11 +416,9 @@ public: CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i)); } - /// Determine if the parameter or return value is marked with NoAlias - /// attribute. - /// @param n The parameter to check. 1 is the first parameter, 0 is the return - bool doesNotAlias(unsigned n) const { - CALLSITE_DELEGATE_GETTER(doesNotAlias(n)); + /// Determine if the return value is marked with NoAlias attribute. + bool returnDoesNotAlias() const { + CALLSITE_DELEGATE_GETTER(returnDoesNotAlias()); } /// Return true if the call should not be treated as a call to a builtin. diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 9e723f977755..f9582f51ca8d 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -204,6 +204,10 @@ public: addAttribute(AttributeList::FunctionIndex, Attr); } + void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + addAttribute(ArgNo + AttributeList::FirstArgIndex, Kind); + } + /// @brief Remove function attributes from this function. void removeFnAttr(Attribute::AttrKind Kind) { removeAttribute(AttributeList::FunctionIndex, Kind); @@ -211,10 +215,14 @@ public: /// @brief Remove function attribute from this function. void removeFnAttr(StringRef Kind) { - setAttributes(AttributeSets.removeAttribute( + setAttributes(getAttributes().removeAttribute( getContext(), AttributeList::FunctionIndex, Kind)); } + void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + removeAttribute(ArgNo + AttributeList::FirstArgIndex, Kind); + } + /// \brief Set the entry count for this function. /// /// Entry count is the number of times this function was executed based on @@ -279,7 +287,7 @@ public: void addAttribute(unsigned i, Attribute Attr); /// @brief adds the attributes to the list of attributes. - void addAttributes(unsigned i, AttributeList Attrs); + void addAttributes(unsigned i, const AttrBuilder &Attrs); /// @brief removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute::AttrKind Kind); @@ -288,7 +296,7 @@ public: void removeAttribute(unsigned i, StringRef Kind); /// @brief removes the attributes from the list of attributes. - void removeAttributes(unsigned i, AttributeList Attrs); + void removeAttributes(unsigned i, const AttrBuilder &Attrs); /// @brief check if an attributes is in the list of attributes. bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const { @@ -459,35 +467,12 @@ public: /// @brief Determine if the parameter or return value is marked with NoAlias /// attribute. /// @param n The parameter to check. 1 is the first parameter, 0 is the return - bool doesNotAlias(unsigned n) const { - return AttributeSets.hasAttribute(n, Attribute::NoAlias); - } - void setDoesNotAlias(unsigned n) { - addAttribute(n, Attribute::NoAlias); - } - - /// @brief Determine if the parameter can be captured. - /// @param n The parameter to check. 1 is the first parameter, 0 is the return - bool doesNotCapture(unsigned n) const { - return AttributeSets.hasAttribute(n, Attribute::NoCapture); - } - void setDoesNotCapture(unsigned n) { - addAttribute(n, Attribute::NoCapture); - } - - bool doesNotAccessMemory(unsigned n) const { - return AttributeSets.hasAttribute(n, Attribute::ReadNone); - } - void setDoesNotAccessMemory(unsigned n) { - addAttribute(n, Attribute::ReadNone); - } - - bool onlyReadsMemory(unsigned n) const { - return doesNotAccessMemory(n) || - AttributeSets.hasAttribute(n, Attribute::ReadOnly); + bool returnDoesNotAlias() const { + return AttributeSets.hasAttribute(AttributeList::ReturnIndex, + Attribute::NoAlias); } - void setOnlyReadsMemory(unsigned n) { - addAttribute(n, Attribute::ReadOnly); + void setReturnDoesNotAlias() { + addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); } /// Optimize this function for minimum size (-Oz). diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 4d3f1dc267f2..844a7273eca9 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -1658,12 +1658,18 @@ public: /// adds the attribute to the list of attributes. void addAttribute(unsigned i, Attribute Attr); + /// Adds the attribute to the indicated argument + void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + /// removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute::AttrKind Kind); /// removes the attribute from the list of attributes. void removeAttribute(unsigned i, StringRef Kind); + /// Removes the attribute from the given argument + void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + /// adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); @@ -1734,11 +1740,9 @@ public: return Attrs.getDereferenceableOrNullBytes(i); } - /// @brief Determine if the parameter or return value is marked with NoAlias - /// attribute. - /// @param n The parameter to check. 1 is the first parameter, 0 is the return - bool doesNotAlias(unsigned n) const { - return Attrs.hasAttribute(n, Attribute::NoAlias); + /// @brief Determine if the return value is marked with NoAlias attribute. + bool returnDoesNotAlias() const { + return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); } /// Return true if the call should not be treated as a call to a @@ -3750,12 +3754,18 @@ public: /// adds the attribute to the list of attributes. void addAttribute(unsigned i, Attribute Attr); + /// Adds the attribute to the indicated argument + void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + /// removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute::AttrKind Kind); /// removes the attribute from the list of attributes. void removeAttribute(unsigned i, StringRef Kind); + /// Removes the attribute from the given argument + void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + /// adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); @@ -3827,11 +3837,9 @@ public: return Attrs.getDereferenceableOrNullBytes(i); } - /// @brief Determine if the parameter or return value is marked with NoAlias - /// attribute. - /// @param n The parameter to check. 1 is the first parameter, 0 is the return - bool doesNotAlias(unsigned n) const { - return Attrs.hasAttribute(n, Attribute::NoAlias); + /// @brief Determine if the return value is marked with NoAlias attribute. + bool returnDoesNotAlias() const { + return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); } /// Return true if the call should not be treated as a call to a diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 2f6bdf8ecf19..fc79da7ae0e6 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -100,7 +100,7 @@ namespace Intrinsic { Void, VarArg, MMX, Token, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendArgument, TruncArgument, HalfVecArgument, - SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfPtrsToElt + SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt } Kind; union { @@ -119,25 +119,43 @@ namespace Intrinsic { AK_AnyVector, AK_AnyPointer }; + unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || Kind == SameVecWidthArgument || Kind == PtrToArgument || - Kind == PtrToElt || Kind == VecOfPtrsToElt); + Kind == PtrToElt); return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument || - Kind == VecOfPtrsToElt); + Kind == SameVecWidthArgument || Kind == PtrToArgument); return (ArgKind)(Argument_Info & 7); } + // VecOfAnyPtrsToElt uses both an overloaded argument (for address space) + // and a reference argument (for matching vector width and element types) + unsigned getOverloadArgNumber() const { + assert(Kind == VecOfAnyPtrsToElt); + return Argument_Info >> 16; + } + unsigned getRefArgNumber() const { + assert(Kind == VecOfAnyPtrsToElt); + return Argument_Info & 0xFFFF; + } + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { IITDescriptor Result = { K, { Field } }; return Result; } + + static IITDescriptor get(IITDescriptorKind K, unsigned short Hi, + unsigned short Lo) { + unsigned Field = Hi << 16 | Lo; + IITDescriptor Result = {K, {Field}}; + return Result; + } }; /// Return the IIT table descriptor for the specified intrinsic into an array diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 39b992cd06a8..cf7e5d8758a9 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -155,7 +155,7 @@ class LLVMVectorSameWidth<int num, LLVMType elty> } class LLVMPointerTo<int num> : LLVMMatchType<num>; class LLVMPointerToElt<int num> : LLVMMatchType<num>; -class LLVMVectorOfPointersToElt<int num> : LLVMMatchType<num>; +class LLVMVectorOfAnyPointersToElt<int num> : LLVMMatchType<num>; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many @@ -404,7 +404,7 @@ def int_memset : Intrinsic<[], // FIXME: Add version of these floating point intrinsics which allow non-default // rounding modes and FP exception handling. -let IntrProperties = [IntrNoMem] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_fma : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; @@ -440,10 +440,12 @@ let IntrProperties = [IntrNoMem] in { } def int_minnum : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, Commutative] + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative] >; def int_maxnum : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, Commutative] + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative] >; // NOTE: these are internal interfaces. @@ -455,7 +457,7 @@ def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; // Internal interface for object size checking def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty], - [IntrNoMem]>, + [IntrNoMem, IntrSpeculatable]>, GCCBuiltin<"__builtin_object_size">; //===--------------- Constrained Floating Point Intrinsics ----------------===// @@ -500,7 +502,7 @@ def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, // // None of these intrinsics accesses memory at all. -let IntrProperties = [IntrNoMem] in { +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; @@ -511,10 +513,11 @@ let IntrProperties = [IntrNoMem] in { //===------------------------ Debugger Intrinsics -------------------------===// // -// None of these intrinsics accesses memory at all...but that doesn't mean the -// optimizers can change them aggressively. Special handling needed in a few -// places. -let IntrProperties = [IntrNoMem] in { +// None of these intrinsics accesses memory at all...but that doesn't +// mean the optimizers can change them aggressively. Special handling +// needed in a few places. These synthetic intrinsics have no +// side-effects and just mark information about their operands. +let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_dbg_declare : Intrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, @@ -592,24 +595,24 @@ def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], // Expose the carry flag from add operations on two integrals. def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; + [IntrNoMem, IntrSpeculatable]>; def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; + [IntrNoMem, IntrSpeculatable]>; def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; + [IntrNoMem, IntrSpeculatable]>; def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; + [IntrNoMem, IntrSpeculatable]>; def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; + [IntrNoMem, IntrSpeculatable]>; def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; + [IntrNoMem, IntrSpeculatable]>; //===------------------------- Memory Use Markers -------------------------===// // @@ -633,7 +636,7 @@ def int_invariant_end : Intrinsic<[], // it can be CSE only if memory didn't change between 2 barriers call, // which is valid. // The argument also can't be marked with 'returned' attribute, because -// it would remove barrier. +// it would remove barrier. def int_invariant_group_barrier : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; @@ -758,14 +761,14 @@ def int_masked_load : Intrinsic<[llvm_anyvector_ty], [IntrReadMem, IntrArgMemOnly]>; def int_masked_gather: Intrinsic<[llvm_anyvector_ty], - [LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + [LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem]>; def int_masked_scatter: Intrinsic<[], [llvm_anyvector_ty, - LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, LLVMVectorSameWidth<0, llvm_i1_ty>]>; def int_masked_expandload: Intrinsic<[llvm_anyvector_ty], diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 97c756cf4b60..1c466e73eb1b 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -3221,6 +3221,29 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// LWP +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_llwpcb : + GCCBuiltin<"__builtin_ia32_llwpcb">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_slwpcb : + GCCBuiltin<"__builtin_ia32_slwpcb">, + Intrinsic<[llvm_ptr_ty], [], []>; + def int_x86_lwpins32 : + GCCBuiltin<"__builtin_ia32_lwpins32">, + Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + def int_x86_lwpins64 : + GCCBuiltin<"__builtin_ia32_lwpins64">, + Intrinsic<[llvm_i8_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], []>; + def int_x86_lwpval32 : + GCCBuiltin<"__builtin_ia32_lwpval32">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + def int_x86_lwpval64 : + GCCBuiltin<"__builtin_ia32_lwpval64">, + Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], []>; +} + +//===----------------------------------------------------------------------===// // MMX // Empty MMX state op. diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h index 748a62be231e..f141c30f16c7 100644 --- a/include/llvm/Support/BinaryStreamArray.h +++ b/include/llvm/Support/BinaryStreamArray.h @@ -42,99 +42,34 @@ namespace llvm { /// having to specify a second template argument to VarStreamArray (documented /// below). template <typename T> struct VarStreamArrayExtractor { - typedef void Context; + struct ContextType {}; // Method intentionally deleted. You must provide an explicit specialization - // with the following method implemented. - static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item, - Context *Ctx) = delete; -}; - -/// VarStreamArray represents an array of variable length records backed by a -/// stream. This could be a contiguous sequence of bytes in memory, it could -/// be a file on disk, or it could be a PDB stream where bytes are stored as -/// discontiguous blocks in a file. Usually it is desirable to treat arrays -/// as contiguous blocks of memory, but doing so with large PDB files, for -/// example, could mean allocating huge amounts of memory just to allow -/// re-ordering of stream data to be contiguous before iterating over it. By -/// abstracting this out, we need not duplicate this memory, and we can -/// iterate over arrays in arbitrarily formatted streams. Elements are parsed -/// lazily on iteration, so there is no upfront cost associated with building -/// or copying a VarStreamArray, no matter how large it may be. -/// -/// You create a VarStreamArray by specifying a ValueType and an Extractor type. -/// If you do not specify an Extractor type, you are expected to specialize -/// VarStreamArrayExtractor<T> for your ValueType. -/// -/// The default extractor type is stateless, but by specializing -/// VarStreamArrayExtractor or defining your own custom extractor type and -/// adding the appropriate ContextType typedef to the class, you can pass a -/// context field during construction of the VarStreamArray that will be -/// passed to each call to extract. -/// -template <typename ValueType, typename ExtractorType> -class VarStreamArrayIterator; - -template <typename ValueType, - typename ExtractorType = VarStreamArrayExtractor<ValueType>> -class VarStreamArray { -public: - typedef typename ExtractorType::ContextType ContextType; - typedef VarStreamArrayIterator<ValueType, ExtractorType> Iterator; - friend Iterator; - - VarStreamArray() = default; - - explicit VarStreamArray(BinaryStreamRef Stream, - ContextType *Context = nullptr) - : Stream(Stream), Context(Context) {} - - VarStreamArray(const VarStreamArray<ValueType, ExtractorType> &Other) - : Stream(Other.Stream), Context(Other.Context) {} - - Iterator begin(bool *HadError = nullptr) const { - if (empty()) - return end(); - - return Iterator(*this, Context, HadError); - } - - Iterator end() const { return Iterator(); } - - bool empty() const { return Stream.getLength() == 0; } - - /// \brief given an offset into the array's underlying stream, return an - /// iterator to the record at that offset. This is considered unsafe - /// since the behavior is undefined if \p Offset does not refer to the - /// beginning of a valid record. - Iterator at(uint32_t Offset) const { - return Iterator(*this, Context, Stream.drop_front(Offset), nullptr); - } - - BinaryStreamRef getUnderlyingStream() const { return Stream; } + // with one of the following two methods implemented. + static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item) = delete; -private: - BinaryStreamRef Stream; - ContextType *Context = nullptr; + static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item, + const ContextType &Ctx) = delete; }; -template <typename ValueType, typename ExtractorType> +template <typename ArrayType, typename Value, typename Extractor, + typename WrappedCtx> class VarStreamArrayIterator : public iterator_facade_base< - VarStreamArrayIterator<ValueType, ExtractorType>, - std::forward_iterator_tag, ValueType> { - typedef typename ExtractorType::ContextType ContextType; - typedef VarStreamArrayIterator<ValueType, ExtractorType> IterType; - typedef VarStreamArray<ValueType, ExtractorType> ArrayType; + VarStreamArrayIterator<ArrayType, Value, Extractor, WrappedCtx>, + std::forward_iterator_tag, Value> { + typedef VarStreamArrayIterator<ArrayType, Value, Extractor, WrappedCtx> + IterType; public: - VarStreamArrayIterator(const ArrayType &Array, ContextType *Context, + VarStreamArrayIterator() = default; + VarStreamArrayIterator(const ArrayType &Array, const WrappedCtx &Ctx, BinaryStreamRef Stream, bool *HadError = nullptr) - : IterRef(Stream), Context(Context), Array(&Array), HadError(HadError) { + : IterRef(Stream), Ctx(&Ctx), Array(&Array), HadError(HadError) { if (IterRef.getLength() == 0) moveToEnd(); else { - auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context); + auto EC = Ctx.template invoke<Extractor>(IterRef, ThisLen, ThisValue); if (EC) { consumeError(std::move(EC)); markError(); @@ -142,11 +77,13 @@ public: } } - VarStreamArrayIterator(const ArrayType &Array, ContextType *Context, + VarStreamArrayIterator(const ArrayType &Array, const WrappedCtx &Ctx, bool *HadError = nullptr) - : VarStreamArrayIterator(Array, Context, Array.Stream, HadError) {} + : VarStreamArrayIterator(Array, Ctx, Array.Stream, HadError) {} + + VarStreamArrayIterator(const WrappedCtx &Ctx) : Ctx(&Ctx) {} + VarStreamArrayIterator(const VarStreamArrayIterator &Other) = default; - VarStreamArrayIterator() = default; ~VarStreamArrayIterator() = default; bool operator==(const IterType &R) const { @@ -164,12 +101,12 @@ public: return false; } - const ValueType &operator*() const { + const Value &operator*() const { assert(Array && !HasError); return ThisValue; } - ValueType &operator*() { + Value &operator*() { assert(Array && !HasError); return ThisValue; } @@ -185,7 +122,7 @@ public: moveToEnd(); } else { // There is some data after the current record. - auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context); + auto EC = Ctx->template invoke<Extractor>(IterRef, ThisLen, ThisValue); if (EC) { consumeError(std::move(EC)); markError(); @@ -210,15 +147,136 @@ private: *HadError = true; } - ValueType ThisValue; + Value ThisValue; BinaryStreamRef IterRef; - ContextType *Context{nullptr}; + const WrappedCtx *Ctx{nullptr}; const ArrayType *Array{nullptr}; uint32_t ThisLen{0}; bool HasError{false}; bool *HadError{nullptr}; }; +template <typename T, typename Context> struct ContextWrapper { + ContextWrapper() = default; + + explicit ContextWrapper(Context &&Ctx) : Ctx(Ctx) {} + + template <typename Extractor> + Error invoke(BinaryStreamRef Stream, uint32_t &Len, T &Item) const { + return Extractor::extract(Stream, Len, Item, Ctx); + } + + Context Ctx; +}; + +template <typename T> struct ContextWrapper<T, void> { + ContextWrapper() = default; + + template <typename Extractor> + Error invoke(BinaryStreamRef Stream, uint32_t &Len, T &Item) const { + return Extractor::extract(Stream, Len, Item); + } +}; + +/// VarStreamArray represents an array of variable length records backed by a +/// stream. This could be a contiguous sequence of bytes in memory, it could +/// be a file on disk, or it could be a PDB stream where bytes are stored as +/// discontiguous blocks in a file. Usually it is desirable to treat arrays +/// as contiguous blocks of memory, but doing so with large PDB files, for +/// example, could mean allocating huge amounts of memory just to allow +/// re-ordering of stream data to be contiguous before iterating over it. By +/// abstracting this out, we need not duplicate this memory, and we can +/// iterate over arrays in arbitrarily formatted streams. Elements are parsed +/// lazily on iteration, so there is no upfront cost associated with building +/// or copying a VarStreamArray, no matter how large it may be. +/// +/// You create a VarStreamArray by specifying a ValueType and an Extractor type. +/// If you do not specify an Extractor type, you are expected to specialize +/// VarStreamArrayExtractor<T> for your ValueType. +/// +/// The default extractor type is stateless, but by specializing +/// VarStreamArrayExtractor or defining your own custom extractor type and +/// adding the appropriate ContextType typedef to the class, you can pass a +/// context field during construction of the VarStreamArray that will be +/// passed to each call to extract. +/// +template <typename Value, typename Extractor, typename WrappedCtx> +class VarStreamArrayBase { + typedef VarStreamArrayBase<Value, Extractor, WrappedCtx> MyType; + +public: + typedef VarStreamArrayIterator<MyType, Value, Extractor, WrappedCtx> Iterator; + friend Iterator; + + VarStreamArrayBase() = default; + + VarStreamArrayBase(BinaryStreamRef Stream, const WrappedCtx &Ctx) + : Stream(Stream), Ctx(Ctx) {} + + VarStreamArrayBase(const MyType &Other) + : Stream(Other.Stream), Ctx(Other.Ctx) {} + + Iterator begin(bool *HadError = nullptr) const { + if (empty()) + return end(); + + return Iterator(*this, Ctx, Stream, HadError); + } + + bool valid() const { return Stream.valid(); } + + Iterator end() const { return Iterator(Ctx); } + + bool empty() const { return Stream.getLength() == 0; } + + /// \brief given an offset into the array's underlying stream, return an + /// iterator to the record at that offset. This is considered unsafe + /// since the behavior is undefined if \p Offset does not refer to the + /// beginning of a valid record. + Iterator at(uint32_t Offset) const { + return Iterator(*this, Ctx, Stream.drop_front(Offset), nullptr); + } + + BinaryStreamRef getUnderlyingStream() const { return Stream; } + +private: + BinaryStreamRef Stream; + WrappedCtx Ctx; +}; + +template <typename Value, typename Extractor, typename Context> +class VarStreamArrayImpl + : public VarStreamArrayBase<Value, Extractor, + ContextWrapper<Value, Context>> { + typedef ContextWrapper<Value, Context> WrappedContext; + typedef VarStreamArrayImpl<Value, Extractor, Context> MyType; + typedef VarStreamArrayBase<Value, Extractor, WrappedContext> BaseType; + +public: + typedef Context ContextType; + + VarStreamArrayImpl() = default; + VarStreamArrayImpl(BinaryStreamRef Stream, Context &&Ctx) + : BaseType(Stream, WrappedContext(std::forward<Context>(Ctx))) {} +}; + +template <typename Value, typename Extractor> +class VarStreamArrayImpl<Value, Extractor, void> + : public VarStreamArrayBase<Value, Extractor, ContextWrapper<Value, void>> { + typedef ContextWrapper<Value, void> WrappedContext; + typedef VarStreamArrayImpl<Value, Extractor, void> MyType; + typedef VarStreamArrayBase<Value, Extractor, WrappedContext> BaseType; + +public: + VarStreamArrayImpl() = default; + VarStreamArrayImpl(BinaryStreamRef Stream) + : BaseType(Stream, WrappedContext()) {} +}; + +template <typename Value, typename Extractor = VarStreamArrayExtractor<Value>> +using VarStreamArray = + VarStreamArrayImpl<Value, Extractor, typename Extractor::ContextType>; + template <typename T> class FixedStreamArrayIterator; /// FixedStreamArray is similar to VarStreamArray, except with each record diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h index f30d82d81b25..77738077f5ff 100644 --- a/include/llvm/Support/BinaryStreamReader.h +++ b/include/llvm/Support/BinaryStreamReader.h @@ -31,6 +31,7 @@ namespace llvm { /// are overridable. class BinaryStreamReader { public: + BinaryStreamReader() = default; explicit BinaryStreamReader(BinaryStreamRef Stream); virtual ~BinaryStreamReader() {} @@ -172,13 +173,29 @@ public: /// \returns a success error code if the data was successfully read, otherwise /// returns an appropriate error code. template <typename T, typename U> - Error - readArray(VarStreamArray<T, U> &Array, uint32_t Size, - typename VarStreamArray<T, U>::ContextType *Context = nullptr) { + Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) { BinaryStreamRef S; if (auto EC = readStreamRef(S, Size)) return EC; - Array = VarStreamArray<T, U>(S, Context); + Array = VarStreamArray<T, U>(S); + return Error::success(); + } + + /// Read a VarStreamArray of size \p Size bytes and store the result into + /// \p Array. Updates the stream's offset to point after the newly read + /// array. Never causes a copy (although iterating the elements of the + /// VarStreamArray may, depending upon the implementation of the underlying + /// stream). + /// + /// \returns a success error code if the data was successfully read, otherwise + /// returns an appropriate error code. + template <typename T, typename U, typename ContextType> + Error readArray(VarStreamArray<T, U> &Array, uint32_t Size, + ContextType &&Context) { + BinaryStreamRef S; + if (auto EC = readStreamRef(S, Size)) + return EC; + Array = VarStreamArray<T, U>(S, std::move(Context)); return Error::success(); } @@ -227,6 +244,9 @@ public: /// \returns the next byte in the stream. uint8_t peek() const; + std::pair<BinaryStreamReader, BinaryStreamReader> + split(uint32_t Offset) const; + private: BinaryStreamRef Stream; uint32_t Offset; diff --git a/include/llvm/Support/BinaryStreamRef.h b/include/llvm/Support/BinaryStreamRef.h index 23ce02fd7ca4..465e724a6886 100644 --- a/include/llvm/Support/BinaryStreamRef.h +++ b/include/llvm/Support/BinaryStreamRef.h @@ -98,6 +98,9 @@ public: BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset, uint32_t Length) = delete; + /// Check if a Stream is valid. + bool valid() const { return Stream != nullptr; } + /// Given an Offset into this StreamRef and a Size, return a reference to a /// buffer owned by the stream. /// diff --git a/include/llvm/Support/BinaryStreamWriter.h b/include/llvm/Support/BinaryStreamWriter.h index 6734a797ccc4..1b61c32a2541 100644 --- a/include/llvm/Support/BinaryStreamWriter.h +++ b/include/llvm/Support/BinaryStreamWriter.h @@ -20,6 +20,7 @@ #include "llvm/Support/Error.h" #include <cstdint> #include <type_traits> +#include <utility> namespace llvm { @@ -30,8 +31,6 @@ namespace llvm { /// although no methods are overridable. class BinaryStreamWriter { public: - // FIXME: We should be able to slice and drop_front etc on Writers / Readers. - BinaryStreamWriter() = default; explicit BinaryStreamWriter(WritableBinaryStreamRef Stream); virtual ~BinaryStreamWriter() {} @@ -152,6 +151,9 @@ public: return writeStreamRef(Array.getUnderlyingStream()); } + /// Splits the Writer into two Writers at a given offset. + std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint32_t Off) const; + void setOffset(uint32_t Off) { Offset = Off; } uint32_t getOffset() const { return Offset; } uint32_t getLength() const { return Stream.getLength(); } diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index 2d1180c228e3..380b628fd95f 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -58,6 +58,28 @@ public: /// NULL will be returned. const char *getCStr(uint32_t *offset_ptr) const; + /// Extract a C string from \a *OffsetPtr. + /// + /// Returns a StringRef for the C String from the data at the offset + /// pointed to by \a OffsetPtr. A variable length NULL terminated C + /// string will be extracted and the \a OffsetPtr will be + /// updated with the offset of the byte that follows the NULL + /// terminator byte. + /// + /// \param[in,out] OffsetPtr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// \return + /// A StringRef for the C string value in the data. If the offset + /// pointed to by \a OffsetPtr is out of bounds, or if the + /// offset plus the length of the C string is out of bounds, + /// a default-initialized StringRef will be returned. + StringRef getCStrRef(uint32_t *OffsetPtr) const; + /// Extract an unsigned integer of size \a byte_size from \a /// *offset_ptr. /// diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def index 74e1d405cebd..5021e2b26ce5 100644 --- a/include/llvm/Support/ELFRelocs/Hexagon.def +++ b/include/llvm/Support/ELFRelocs/Hexagon.def @@ -99,3 +99,8 @@ ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91) ELF_RELOC(R_HEX_LD_GOT_16_X, 92) ELF_RELOC(R_HEX_LD_GOT_11_X, 93) ELF_RELOC(R_HEX_23_REG, 94) +ELF_RELOC(R_HEX_GD_PLT_B22_PCREL_X, 95) +ELF_RELOC(R_HEX_GD_PLT_B32_PCREL_X, 96) +ELF_RELOC(R_HEX_LD_PLT_B22_PCREL_X, 97) +ELF_RELOC(R_HEX_LD_PLT_B32_PCREL_X, 98) +ELF_RELOC(R_HEX_27_REG, 99) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index aa9230044b1f..ced183852146 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -2061,6 +2061,14 @@ public: return false; } + // Return true if the instruction that performs a << b actually performs + // a << (b % (sizeof(a) * 8)). + virtual bool supportsModuloShift(ISD::NodeType Inst, EVT ReturnType) const { + assert((Inst == ISD::SHL || Inst == ISD::SRA || Inst == ISD::SRL) && + "Expect a shift instruction"); + return false; + } + //===--------------------------------------------------------------------===// // Runtime Library hooks // |