diff --git a/contrib/libc++/include/experimental/coroutine b/contrib/libc++/include/experimental/coroutine index d2a03ae8a8c8..21c1ea566403 100644 --- a/contrib/libc++/include/experimental/coroutine +++ b/contrib/libc++/include/experimental/coroutine @@ -145,6 +145,19 @@ public: return __tmp; } + // FIXME: Should from_address(nullptr) be allowed? + _LIBCPP_ALWAYS_INLINE + static coroutine_handle from_address(nullptr_t) _NOEXCEPT { + return coroutine_handle(nullptr); + } + + template + static coroutine_handle from_address(_Tp*) { + static_assert(_CallIsValid, + "coroutine_handle::from_address cannot be called with " + "non-void pointers"); + } + private: bool __is_suspended() const _NOEXCEPT { // FIXME actually implement a check for if the coro is suspended. @@ -218,11 +231,22 @@ public: // FIXME: should from_address work with nullptr? _LIBCPP_ALWAYS_INLINE static coroutine_handle from_address(nullptr_t) _NOEXCEPT { - return {}; + return coroutine_handle(nullptr); } - // from_address cannot be used with the coroutines promise type. - static coroutine_handle from_address(_Promise*) = delete; + template + static coroutine_handle from_address(_Tp*) { + static_assert(_CallIsValid, + "coroutine_handle::from_address cannot be called with " + "non-void pointers"); + } + + template + static coroutine_handle from_address(_Promise*) { + static_assert(_CallIsValid, + "coroutine_handle::from_address cannot be used with " + "pointers to the coroutine's promise type; use 'from_promise' instead"); + } _LIBCPP_ALWAYS_INLINE static coroutine_handle from_promise(_Promise& __promise) _NOEXCEPT { diff --git a/contrib/libc++/include/module.modulemap b/contrib/libc++/include/module.modulemap index 462d4234ae6c..98b1870afcc1 100644 --- a/contrib/libc++/include/module.modulemap +++ b/contrib/libc++/include/module.modulemap @@ -502,6 +502,7 @@ module std [system] { export * } module coroutine { + requires coroutines header "experimental/coroutine" export * } diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 4a6fc245c225..1d715b590ab7 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -1536,8 +1536,7 @@ class ScalarEvolution { /// Determine if the SCEV can be evaluated at loop's entry. It is true if it /// doesn't depend on a SCEVUnknown of an instruction which is dominated by /// the header of loop L. - bool isAvailableAtLoopEntry(const SCEV *S, const Loop *L, DominatorTree &DT, - LoopInfo &LI); + bool isAvailableAtLoopEntry(const SCEV *S, const Loop *L); /// Return true if the given SCEV changes value in a known way in the /// specified loop. This property being true implies that the value is diff --git a/contrib/llvm/include/llvm/CodeGen/DIE.h b/contrib/llvm/include/llvm/CodeGen/DIE.h index 4be44e62fa92..4f47ba6e3852 100644 --- a/contrib/llvm/include/llvm/CodeGen/DIE.h +++ b/contrib/llvm/include/llvm/CodeGen/DIE.h @@ -383,11 +383,11 @@ class DIEValue { return; #define HANDLE_DIEVALUE_SMALL(T) \ case is##T: \ - destruct(); + destruct(); \ return; #define HANDLE_DIEVALUE_LARGE(T) \ case is##T: \ - destruct(); + destruct(); \ return; #include "llvm/CodeGen/DIEValue.def" } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index f881ad0c9d80..3316e71916ed 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -13,6 +13,8 @@ #include #include +#include "llvm/Support/Endian.h" + namespace llvm { namespace codeview { @@ -291,7 +293,7 @@ enum class ModifierOptions : uint16_t { }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions) -enum class ModuleDebugFragmentKind : uint32_t { +enum class DebugSubsectionKind : uint32_t { None = 0, Symbols = 0xf1, Lines = 0xf2, @@ -550,6 +552,24 @@ enum LineFlags : uint16_t { LF_None = 0, LF_HaveColumns = 1, // CV_LINES_HAVE_COLUMNS }; + +/// Data in the the SUBSEC_FRAMEDATA subection. +struct FrameData { + support::ulittle32_t RvaStart; + support::ulittle32_t CodeSize; + support::ulittle32_t LocalSize; + support::ulittle32_t ParamsSize; + support::ulittle32_t MaxStackSize; + support::ulittle32_t FrameFunc; + support::ulittle16_t PrologSize; + support::ulittle16_t SavedRegsSize; + support::ulittle32_t Flags; + enum : uint32_t { + HasSEH = 1 << 0, + HasEH = 1 << 1, + IsFunctionStart = 1 << 2, + }; +}; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h similarity index 63% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h index 6c08c9aa2137..e7036033d2d9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h @@ -1,4 +1,4 @@ -//===- ModuleDebugFileChecksumFragment.h ------------------------*- C++ -*-===// +//===- DebugChecksumsSubsection.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H -#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGCHECKSUMSSUBSECTION_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" @@ -21,7 +21,7 @@ namespace llvm { namespace codeview { -class StringTable; +class DebugStringTableSubsection; struct FileChecksumEntry { uint32_t FileNameOffset; // Byte offset of filename in global stringtable. @@ -43,19 +43,22 @@ template <> struct VarStreamArrayExtractor { namespace llvm { namespace codeview { -class ModuleDebugFileChecksumFragmentRef final : public ModuleDebugFragmentRef { +class DebugChecksumsSubsectionRef final : public DebugSubsectionRef { typedef VarStreamArray FileChecksumArray; typedef FileChecksumArray::Iterator Iterator; public: - ModuleDebugFileChecksumFragmentRef() - : ModuleDebugFragmentRef(ModuleDebugFragmentKind::FileChecksums) {} + DebugChecksumsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::FileChecksums) {} - static bool classof(const ModuleDebugFragmentRef *S) { - return S->kind() == ModuleDebugFragmentKind::FileChecksums; + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::FileChecksums; } + bool valid() const { return Checksums.valid(); } + Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Stream); Iterator begin() { return Checksums.begin(); } Iterator end() { return Checksums.end(); } @@ -66,23 +69,23 @@ class ModuleDebugFileChecksumFragmentRef final : public ModuleDebugFragmentRef { FileChecksumArray Checksums; }; -class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment { +class DebugChecksumsSubsection final : public DebugSubsection { public: - explicit ModuleDebugFileChecksumFragment(StringTable &Strings); + explicit DebugChecksumsSubsection(DebugStringTableSubsection &Strings); - static bool classof(const ModuleDebugFragment *S) { - return S->kind() == ModuleDebugFragmentKind::FileChecksums; + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FileChecksums; } void addChecksum(StringRef FileName, FileChecksumKind Kind, ArrayRef Bytes); - uint32_t calculateSerializedLength() override; - Error commit(BinaryStreamWriter &Writer) override; + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; uint32_t mapChecksumOffset(StringRef FileName) const; private: - StringTable &Strings; + DebugStringTableSubsection &Strings; DenseMap OffsetMap; uint32_t SerializedSize = 0; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h new file mode 100644 index 000000000000..686b5c4f242e --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -0,0 +1,59 @@ +//===- DebugFrameDataSubsection.h ------------------------------*- 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_DEBUGFRAMEDATASUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGFRAMEDATASUBSECTION_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class DebugFrameDataSubsectionRef final : public DebugSubsectionRef { +public: + DebugFrameDataSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::FrameData) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FrameData; + } + + Error initialize(BinaryStreamReader Reader); + + FixedStreamArray::Iterator begin() const { return Frames.begin(); } + FixedStreamArray::Iterator end() const { return Frames.end(); } + + const void *getRelocPtr() const { return RelocPtr; } + +private: + const uint32_t *RelocPtr = nullptr; + FixedStreamArray Frames; +}; + +class DebugFrameDataSubsection final : public DebugSubsection { +public: + DebugFrameDataSubsection() + : DebugSubsection(DebugSubsectionKind::FrameData) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::FrameData; + } + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void addFrameData(const FrameData &Frame); + +private: + std::vector Frames; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h similarity index 67% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h index 348497cbf7f2..e2cfc3c99233 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -1,4 +1,4 @@ -//===- ModuleDebugInlineeLinesFragment.h ------------------------*- C++ -*-===// +//===- DebugInlineeLinesSubsection.h ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H -#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H +#ifndef LLVM_DEBUGINFO_CODEVIEW_BUGINLINEELINESSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_BUGINLINEELINESSUBSECTION_H +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" @@ -19,9 +19,8 @@ namespace llvm { namespace codeview { -class ModuleDebugInlineeLineFragmentRef; -class ModuleDebugFileChecksumFragment; -class StringTable; +class DebugInlineeLinesSubsectionsRef; +class DebugChecksumsSubsection; enum class InlineeLinesSignature : uint32_t { Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE @@ -51,15 +50,15 @@ template <> struct VarStreamArrayExtractor { }; namespace codeview { -class ModuleDebugInlineeLineFragmentRef final : public ModuleDebugFragmentRef { +class DebugInlineeLinesSubsectionRef final : public DebugSubsectionRef { typedef VarStreamArray LinesArray; typedef LinesArray::Iterator Iterator; public: - ModuleDebugInlineeLineFragmentRef(); + DebugInlineeLinesSubsectionRef(); - static bool classof(const ModuleDebugFragmentRef *S) { - return S->kind() == ModuleDebugFragmentKind::InlineeLines; + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::InlineeLines; } Error initialize(BinaryStreamReader Reader); @@ -73,23 +72,23 @@ class ModuleDebugInlineeLineFragmentRef final : public ModuleDebugFragmentRef { VarStreamArray Lines; }; -class ModuleDebugInlineeLineFragment final : public ModuleDebugFragment { +class DebugInlineeLinesSubsection final : public DebugSubsection { public: - ModuleDebugInlineeLineFragment(ModuleDebugFileChecksumFragment &Checksums, - bool HasExtraFiles); + DebugInlineeLinesSubsection(DebugChecksumsSubsection &Checksums, + bool HasExtraFiles); - static bool classof(const ModuleDebugFragment *S) { - return S->kind() == ModuleDebugFragmentKind::InlineeLines; + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::InlineeLines; } - Error commit(BinaryStreamWriter &Writer) override; - uint32_t calculateSerializedLength() override; + Error commit(BinaryStreamWriter &Writer) const override; + uint32_t calculateSerializedSize() const override; void addInlineSite(TypeIndex FuncId, StringRef FileName, uint32_t SourceLine); void addExtraFile(StringRef FileName); private: - ModuleDebugFileChecksumFragment &Checksums; + DebugChecksumsSubsection &Checksums; bool HasExtraFiles = false; uint32_t ExtraFileCount = 0; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h similarity index 81% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h index 3124236b8fb1..1b63af59c2ed 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h @@ -1,4 +1,4 @@ -//===- ModuleDebugLineFragment.h --------------------------------*- C++ -*-===// +//===- DebugLinesSubsection.h --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,8 +10,8 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" @@ -19,8 +19,8 @@ namespace llvm { namespace codeview { -class ModuleDebugFileChecksumFragment; -class StringTable; +class DebugChecksumsSubsection; +class DebugStringTableSubsection; // Corresponds to the `CV_DebugSLinesHeader_t` structure. struct LineFragmentHeader { @@ -70,16 +70,16 @@ class LineColumnExtractor { LineColumnEntry &Item, const LineFragmentHeader *Ctx); }; -class ModuleDebugLineFragmentRef final : public ModuleDebugFragmentRef { +class DebugLinesSubsectionRef final : public DebugSubsectionRef { friend class LineColumnExtractor; typedef VarStreamArray LineInfoArray; typedef LineInfoArray::Iterator Iterator; public: - ModuleDebugLineFragmentRef(); + DebugLinesSubsectionRef(); - static bool classof(const ModuleDebugFragmentRef *S) { - return S->kind() == ModuleDebugFragmentKind::Lines; + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::Lines; } Error initialize(BinaryStreamReader Reader); @@ -96,7 +96,7 @@ class ModuleDebugLineFragmentRef final : public ModuleDebugFragmentRef { LineInfoArray LinesAndColumns; }; -class ModuleDebugLineFragment final : public ModuleDebugFragment { +class DebugLinesSubsection final : public DebugSubsection { struct Block { Block(uint32_t ChecksumBufferOffset) : ChecksumBufferOffset(ChecksumBufferOffset) {} @@ -107,11 +107,11 @@ class ModuleDebugLineFragment final : public ModuleDebugFragment { }; public: - ModuleDebugLineFragment(ModuleDebugFileChecksumFragment &Checksums, - StringTable &Strings); + DebugLinesSubsection(DebugChecksumsSubsection &Checksums, + DebugStringTableSubsection &Strings); - static bool classof(const ModuleDebugFragment *S) { - return S->kind() == ModuleDebugFragmentKind::Lines; + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::Lines; } void createBlock(StringRef FileName); @@ -119,8 +119,8 @@ class ModuleDebugLineFragment final : public ModuleDebugFragment { void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, uint32_t ColStart, uint32_t ColEnd); - uint32_t calculateSerializedLength() override; - Error commit(BinaryStreamWriter &Writer) override; + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; void setRelocationAddress(uint16_t Segment, uint16_t Offset); void setCodeSize(uint32_t Size); @@ -129,7 +129,7 @@ class ModuleDebugLineFragment final : public ModuleDebugFragment { bool hasColumnInfo() const; private: - ModuleDebugFileChecksumFragment &Checksums; + DebugChecksumsSubsection &Checksums; uint16_t RelocOffset = 0; uint16_t RelocSegment = 0; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/StringTable.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h similarity index 55% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/StringTable.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h index 05dc02ee849f..fbe39cb16f09 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/StringTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -1,4 +1,4 @@ -//===- StringTable.h - CodeView String Table Reader/Writer ------*- C++ -*-===// +//===- DebugStringTableSubsection.h - CodeView String Table -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H -#define LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H +#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" - +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Error.h" @@ -28,11 +28,15 @@ 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 { +/// are retrieved by their offset in the buffer. DebugStringTableSubsectionRef +/// does not own the underlying storage for the buffer. +class DebugStringTableSubsectionRef : public DebugSubsectionRef { public: - StringTableRef(); + DebugStringTableSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::StringTable; + } Error initialize(BinaryStreamRef Contents); @@ -44,11 +48,18 @@ class StringTableRef { 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 { +/// Represents a read-write view of a CodeView string table. +/// DebugStringTableSubsection owns the underlying storage for the table, and is +/// capable of serializing the string table into a format understood by +/// DebugStringTableSubsectionRef. +class DebugStringTableSubsection : public DebugSubsection { public: + DebugStringTableSubsection(); + + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::StringTable; + } + // If string S does not exist in the string table, insert it. // Returns the ID for S. uint32_t insert(StringRef S); @@ -56,8 +67,8 @@ class StringTable { // 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 calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; uint32_t size() const; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h new file mode 100644 index 000000000000..e427e0006a55 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h @@ -0,0 +1,52 @@ +//===- DebugSubsection.h ------------------------------------*- 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_MODULEDEBUGFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Casting.h" + +namespace llvm { +namespace codeview { + +class DebugSubsectionRef { +public: + explicit DebugSubsectionRef(DebugSubsectionKind Kind) : Kind(Kind) {} + virtual ~DebugSubsectionRef(); + + static bool classof(const DebugSubsectionRef *S) { return true; } + + DebugSubsectionKind kind() const { return Kind; } + +protected: + DebugSubsectionKind Kind; +}; + +class DebugSubsection { +public: + explicit DebugSubsection(DebugSubsectionKind Kind) : Kind(Kind) {} + virtual ~DebugSubsection(); + + static bool classof(const DebugSubsection *S) { return true; } + + DebugSubsectionKind kind() const { return Kind; } + + virtual Error commit(BinaryStreamWriter &Writer) const = 0; + virtual uint32_t calculateSerializedSize() const = 0; + +protected: + DebugSubsectionKind Kind; +}; + +} // namespace codeview +} // namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h similarity index 55% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h index f68f21b224f1..b2e1131e5968 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -1,4 +1,4 @@ -//===- ModuleDebugFragment.h ------------------------------------*- C++ -*-===// +//===- DebugSubsection.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -20,52 +20,49 @@ namespace llvm { namespace codeview { -class ModuleDebugFragment; +class DebugSubsection; // Corresponds to the `CV_DebugSSubsectionHeader_t` structure. -struct ModuleDebugFragmentHeader { - support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum +struct DebugSubsectionHeader { + support::ulittle32_t Kind; // codeview::DebugSubsectionKind enum support::ulittle32_t Length; // number of bytes occupied by this record. }; -class ModuleDebugFragmentRecord { +class DebugSubsectionRecord { public: - ModuleDebugFragmentRecord(); - ModuleDebugFragmentRecord(ModuleDebugFragmentKind Kind, BinaryStreamRef Data); + DebugSubsectionRecord(); + DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data); - static Error initialize(BinaryStreamRef Stream, - ModuleDebugFragmentRecord &Info); + static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info); uint32_t getRecordLength() const; - ModuleDebugFragmentKind kind() const; + DebugSubsectionKind kind() const; BinaryStreamRef getRecordData() const; private: - ModuleDebugFragmentKind Kind; + DebugSubsectionKind Kind; BinaryStreamRef Data; }; -class ModuleDebugFragmentRecordBuilder { +class DebugSubsectionRecordBuilder { public: - ModuleDebugFragmentRecordBuilder(ModuleDebugFragmentKind Kind, - ModuleDebugFragment &Frag); + DebugSubsectionRecordBuilder(DebugSubsectionKind Kind, DebugSubsection &Frag); uint32_t calculateSerializedLength(); Error commit(BinaryStreamWriter &Writer); private: - ModuleDebugFragmentKind Kind; - ModuleDebugFragment &Frag; + DebugSubsectionKind Kind; + DebugSubsection &Frag; }; } // namespace codeview -template <> -struct VarStreamArrayExtractor { +template <> struct VarStreamArrayExtractor { typedef void ContextType; static Error extract(BinaryStreamRef Stream, uint32_t &Length, - codeview::ModuleDebugFragmentRecord &Info) { - if (auto EC = codeview::ModuleDebugFragmentRecord::initialize(Stream, Info)) + codeview::DebugSubsectionRecord &Info) { + if (auto EC = codeview::DebugSubsectionRecord::initialize(Stream, Info)) return EC; Length = Info.getRecordLength(); return Error::success(); @@ -73,7 +70,7 @@ struct VarStreamArrayExtractor { }; namespace codeview { -typedef VarStreamArray ModuleDebugFragmentArray; +typedef VarStreamArray DebugSubsectionArray; } } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h similarity index 50% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index 1f55d2024203..55bef491c97e 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -1,4 +1,4 @@ -//===- ModuleDebugFragmentVisitor.h -----------------------------*- C++ -*-===// +//===- DebugSubsectionVisitor.h -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,43 +17,41 @@ namespace llvm { namespace codeview { -class ModuleDebugFileChecksumFragmentRef; -class ModuleDebugFragmentRecord; -class ModuleDebugInlineeLineFragmentRef; -class ModuleDebugLineFragmentRef; -class ModuleDebugUnknownFragmentRef; +class DebugChecksumsSubsectionRef; +class DebugSubsectionRecord; +class DebugInlineeLinesSubsectionRef; +class DebugLinesSubsectionRef; +class DebugUnknownSubsectionRef; -class ModuleDebugFragmentVisitor { +class DebugSubsectionVisitor { public: - virtual ~ModuleDebugFragmentVisitor() = default; + virtual ~DebugSubsectionVisitor() = default; - virtual Error visitUnknown(ModuleDebugUnknownFragmentRef &Unknown) { + virtual Error visitUnknown(DebugUnknownSubsectionRef &Unknown) { return Error::success(); } - virtual Error visitLines(ModuleDebugLineFragmentRef &Lines) { + virtual Error visitLines(DebugLinesSubsectionRef &Lines) { return Error::success(); } - virtual Error - visitFileChecksums(ModuleDebugFileChecksumFragmentRef &Checksums) { + virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) { return Error::success(); } - virtual Error visitInlineeLines(ModuleDebugInlineeLineFragmentRef &Inlinees) { + virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) { return Error::success(); } virtual Error finished() { return Error::success(); } }; -Error visitModuleDebugFragment(const ModuleDebugFragmentRecord &R, - ModuleDebugFragmentVisitor &V); +Error visitDebugSubsection(const DebugSubsectionRecord &R, + DebugSubsectionVisitor &V); template -Error visitModuleDebugFragments(T &&FragmentRange, - ModuleDebugFragmentVisitor &V) { +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { for (const auto &L : FragmentRange) { - if (auto EC = visitModuleDebugFragment(L, V)) + if (auto EC = visitDebugSubsection(L, V)) return EC; } if (auto EC = V.finished()) diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h new file mode 100644 index 000000000000..3d1eb27ba270 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h @@ -0,0 +1,53 @@ +//===- DebugSymbolsSubsection.h --------------------------------*- 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_DEBUGSYMBOLSSUBSECTION_H +#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H + +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { +class DebugSymbolsSubsectionRef final : public DebugSubsectionRef { +public: + DebugSymbolsSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::Symbols) {} + + static bool classof(const DebugSubsectionRef *S) { + return S->kind() == DebugSubsectionKind::Symbols; + } + + Error initialize(BinaryStreamReader Reader); + +private: + CVSymbolArray Records; +}; + +class DebugSymbolsSubsection final : public DebugSubsection { +public: + DebugSymbolsSubsection() : DebugSubsection(DebugSubsectionKind::Symbols) {} + static bool classof(const DebugSubsection *S) { + return S->kind() == DebugSubsectionKind::Symbols; + } + + uint32_t calculateSerializedSize() const override; + Error commit(BinaryStreamWriter &Writer) const override; + + void addSymbol(CVSymbol Symbol); + +private: + uint32_t Length = 0; + std::vector Records; +}; +} +} + +#endif diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h similarity index 60% rename from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h rename to contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h index b8c1c02e5cf1..ea9a96ca8d68 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h @@ -1,4 +1,4 @@ -//===- ModuleDebugUnknownFragment.h -----------------------------*- C++ -*-===// +//===- DebugUnknownSubsection.h -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,17 +10,16 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGUNKNOWNFRAGMENT_H #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGUNKNOWNFRAGMENT_H -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/Support/BinaryStreamRef.h" namespace llvm { namespace codeview { -class ModuleDebugUnknownFragmentRef final : public ModuleDebugFragmentRef { +class DebugUnknownSubsectionRef final : public DebugSubsectionRef { public: - ModuleDebugUnknownFragmentRef(ModuleDebugFragmentKind Kind, - BinaryStreamRef Data) - : ModuleDebugFragmentRef(Kind), Data(Data) {} + DebugUnknownSubsectionRef(DebugSubsectionKind Kind, BinaryStreamRef Data) + : DebugSubsectionRef(Kind), Data(Data) {} BinaryStreamRef getData() const { return Data; } diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h deleted file mode 100644 index a5311cae9480..000000000000 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h +++ /dev/null @@ -1,48 +0,0 @@ -//===- ModuleDebugFragment.h ------------------------------------*- 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_MODULEDEBUGFRAGMENT_H -#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H - -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/Support/BinaryStreamWriter.h" -#include "llvm/Support/Casting.h" - -namespace llvm { -namespace codeview { - -class ModuleDebugFragmentRef { -public: - explicit ModuleDebugFragmentRef(ModuleDebugFragmentKind Kind) : Kind(Kind) {} - virtual ~ModuleDebugFragmentRef(); - - ModuleDebugFragmentKind kind() const { return Kind; } - -protected: - ModuleDebugFragmentKind Kind; -}; - -class ModuleDebugFragment { -public: - explicit ModuleDebugFragment(ModuleDebugFragmentKind Kind) : Kind(Kind) {} - virtual ~ModuleDebugFragment(); - - ModuleDebugFragmentKind kind() const { return Kind; } - - virtual Error commit(BinaryStreamWriter &Writer) = 0; - virtual uint32_t calculateSerializedLength() = 0; - -protected: - ModuleDebugFragmentKind Kind; -}; - -} // namespace codeview -} // namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h index 96c8a47a3669..a2a3c6f18fba 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -19,7 +19,7 @@ class BinaryStreamReader; namespace codeview { -class StringTableRef; +class DebugStringTableSubsectionRef; class SymbolVisitorDelegate { public: @@ -27,7 +27,7 @@ class SymbolVisitorDelegate { virtual uint32_t getRecordOffset(BinaryStreamReader Reader) = 0; virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0; - virtual StringTableRef getStringTable() = 0; + virtual DebugStringTableSubsectionRef getStringTable() = 0; }; } // end namespace codeview diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index 8cc5db981f56..e5858d0f45e3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -11,9 +11,9 @@ #define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/Error.h" @@ -25,7 +25,7 @@ namespace llvm { class BinaryStreamWriter; namespace codeview { -class ModuleDebugFragmentRecordBuilder; +class DebugSubsectionRecordBuilder; } namespace msf { @@ -49,11 +49,11 @@ class DbiModuleDescriptorBuilder { void setObjFileName(StringRef Name); void addSymbol(codeview::CVSymbol Symbol); - void addC13Fragment(std::unique_ptr Lines); + void addC13Fragment(std::unique_ptr Lines); void addC13Fragment( - std::unique_ptr Inlinees); + std::unique_ptr Inlinees); void setC13FileChecksums( - std::unique_ptr Checksums); + std::unique_ptr Checksums); uint16_t getStreamIndex() const; StringRef getModuleName() const { return ModuleName; } @@ -83,12 +83,11 @@ class DbiModuleDescriptorBuilder { std::vector SourceFiles; std::vector Symbols; - std::unique_ptr ChecksumInfo; - std::vector> LineInfo; - std::vector> - Inlinees; + std::unique_ptr ChecksumInfo; + std::vector> LineInfo; + std::vector> Inlinees; - std::vector> + std::vector> C13Builders; ModuleInfoHeader Layout; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h index 8f95481f4152..dc35f8c72cd9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -10,7 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" @@ -19,8 +19,6 @@ #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h index 2c95690ed580..822ce3ce13d3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -12,7 +12,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/Support/BinaryStreamArray.h" @@ -25,8 +25,7 @@ class PDBFile; class DbiModuleDescriptor; class ModuleDebugStreamRef { - typedef codeview::ModuleDebugFragmentArray::Iterator - LinesAndChecksumsIterator; + typedef codeview::DebugSubsectionArray::Iterator LinesAndChecksumsIterator; public: ModuleDebugStreamRef(const DbiModuleDescriptor &Module, @@ -58,7 +57,7 @@ class ModuleDebugStreamRef { BinaryStreamRef C13LinesSubstream; BinaryStreamRef GlobalRefsSubstream; - codeview::ModuleDebugFragmentArray LinesAndChecksums; + codeview::DebugSubsectionArray LinesAndChecksums; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h index 7c7f16bd1c73..6aeb0a5479cb 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -12,7 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" @@ -52,7 +52,7 @@ class PDBStringTable { Error readEpilogue(BinaryStreamReader &Reader); const PDBStringTableHeader *Header = nullptr; - codeview::StringTableRef Strings; + codeview::DebugStringTableSubsectionRef Strings; FixedStreamArray IDs; uint32_t ByteSize = 0; uint32_t NameCount = 0; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h index 6f85e7a4a074..0faa02dc4525 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -16,7 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/Support/Error.h" #include @@ -41,8 +41,10 @@ class PDBStringTableBuilder { uint32_t calculateSerializedSize() const; Error commit(BinaryStreamWriter &Writer) const; - codeview::StringTable &getStrings() { return Strings; } - const codeview::StringTable &getStrings() const { return Strings; } + codeview::DebugStringTableSubsection &getStrings() { return Strings; } + const codeview::DebugStringTableSubsection &getStrings() const { + return Strings; + } private: uint32_t calculateHashTableSize() const; @@ -51,7 +53,7 @@ class PDBStringTableBuilder { Error writeHashTable(BinaryStreamWriter &Writer) const; Error writeEpilogue(BinaryStreamWriter &Writer) const; - codeview::StringTable Strings; + codeview::DebugStringTableSubsection Strings; }; } // end namespace pdb diff --git a/contrib/llvm/include/llvm/MC/ConstantPools.h b/contrib/llvm/include/llvm/MC/ConstantPools.h index 5d4e32a672dd..ef33250204ec 100644 --- a/contrib/llvm/include/llvm/MC/ConstantPools.h +++ b/contrib/llvm/include/llvm/MC/ConstantPools.h @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/SMLoc.h" #include +#include namespace llvm { @@ -44,7 +45,7 @@ struct ConstantPoolEntry { class ConstantPool { using EntryVecTy = SmallVector; EntryVecTy Entries; - DenseMap CachedEntries; + std::map CachedEntries; public: // Initialize a new empty constant pool diff --git a/contrib/llvm/include/llvm/Support/ManagedStatic.h b/contrib/llvm/include/llvm/Support/ManagedStatic.h index 7ce86eee95d2..b4bf3210cc73 100644 --- a/contrib/llvm/include/llvm/Support/ManagedStatic.h +++ b/contrib/llvm/include/llvm/Support/ManagedStatic.h @@ -14,25 +14,22 @@ #ifndef LLVM_SUPPORT_MANAGEDSTATIC_H #define LLVM_SUPPORT_MANAGEDSTATIC_H -#include "llvm/Support/Compiler.h" #include #include namespace llvm { /// object_creator - Helper method for ManagedStatic. -template -LLVM_LIBRARY_VISIBILITY void* object_creator() { - return new C(); -} +template struct object_creator { + static void *call() { return new C(); } +}; /// object_deleter - Helper method for ManagedStatic. /// -template struct LLVM_LIBRARY_VISIBILITY object_deleter { +template struct object_deleter { static void call(void *Ptr) { delete (T *)Ptr; } }; -template -struct LLVM_LIBRARY_VISIBILITY object_deleter { +template struct object_deleter { static void call(void *Ptr) { delete[](T *)Ptr; } }; @@ -59,14 +56,15 @@ class ManagedStaticBase { /// libraries that link in LLVM components) and for making destruction be /// explicit through the llvm_shutdown() function call. /// -template +template , + class Deleter = object_deleter> class ManagedStatic : public ManagedStaticBase { public: // Accessors. C &operator*() { void *Tmp = Ptr.load(std::memory_order_acquire); if (!Tmp) - RegisterManagedStatic(object_creator, object_deleter::call); + RegisterManagedStatic(Creator::call, Deleter::call); return *static_cast(Ptr.load(std::memory_order_relaxed)); } @@ -76,7 +74,7 @@ class ManagedStatic : public ManagedStaticBase { const C &operator*() const { void *Tmp = Ptr.load(std::memory_order_acquire); if (!Tmp) - RegisterManagedStatic(object_creator, object_deleter::call); + RegisterManagedStatic(Creator::call, Deleter::call); return *static_cast(Ptr.load(std::memory_order_relaxed)); } diff --git a/contrib/llvm/include/llvm/TableGen/Record.h b/contrib/llvm/include/llvm/TableGen/Record.h index d14a56cb87e0..437f68b24e57 100644 --- a/contrib/llvm/include/llvm/TableGen/Record.h +++ b/contrib/llvm/include/llvm/TableGen/Record.h @@ -1189,6 +1189,9 @@ class DagInit final : public TypedInit, public FoldingSetNode, return Init ? Init->getValue() : StringRef(); } + ArrayRef getArgs() const { + return makeArrayRef(getTrailingObjects(), NumArgs); + } ArrayRef getArgNames() const { return makeArrayRef(getTrailingObjects(), NumArgNames); } @@ -1200,19 +1203,16 @@ class DagInit final : public TypedInit, public FoldingSetNode, typedef SmallVectorImpl::const_iterator const_arg_iterator; typedef SmallVectorImpl::const_iterator const_name_iterator; - inline const_arg_iterator arg_begin() const { return getTrailingObjects(); } - inline const_arg_iterator arg_end () const { return arg_begin() + NumArgs; } - inline iterator_range args() const { - return llvm::make_range(arg_begin(), arg_end()); - } + inline const_arg_iterator arg_begin() const { return getArgs().begin(); } + inline const_arg_iterator arg_end () const { return getArgs().end(); } - inline size_t arg_size () const { return NumArgs; } + inline size_t arg_size () const { return NumArgs; } inline bool arg_empty() const { return NumArgs == 0; } - inline const_name_iterator name_begin() const { return getTrailingObjects(); } - inline const_name_iterator name_end () const { return name_begin() + NumArgNames; } + inline const_name_iterator name_begin() const { return getArgNames().begin();} + inline const_name_iterator name_end () const { return getArgNames().end(); } - inline size_t name_size () const { return NumArgNames; } + inline size_t name_size () const { return NumArgNames; } inline bool name_empty() const { return NumArgNames == 0; } Init *getBit(unsigned Bit) const override { diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h b/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h index a971df975b6f..324ebca46de2 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h @@ -58,10 +58,11 @@ class Expression { private: ExpressionType EType; unsigned Opcode; + mutable hash_code HashVal; public: Expression(ExpressionType ET = ET_Base, unsigned O = ~2U) - : EType(ET), Opcode(O) {} + : EType(ET), Opcode(O), HashVal(0) {} Expression(const Expression &) = delete; Expression &operator=(const Expression &) = delete; virtual ~Expression(); @@ -82,6 +83,14 @@ class Expression { return equals(Other); } + hash_code getComputedHash() const { + // It's theoretically possible for a thing to hash to zero. In that case, + // we will just compute the hash a few extra times, which is no worse that + // we did before, which was to compute it always. + if (static_cast(HashVal) == 0) + HashVal = getHashValue(); + return HashVal; + } virtual bool equals(const Expression &Other) const { return true; } diff --git a/contrib/llvm/lib/Analysis/ScalarEvolution.cpp b/contrib/llvm/lib/Analysis/ScalarEvolution.cpp index d280fda0a162..f55ce202bcbb 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolution.cpp @@ -2178,8 +2178,7 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type, return Flags; } -bool ScalarEvolution::isAvailableAtLoopEntry(const SCEV *S, const Loop *L, - DominatorTree &DT, LoopInfo &LI) { +bool ScalarEvolution::isAvailableAtLoopEntry(const SCEV *S, const Loop *L) { if (!isLoopInvariant(S, L)) return false; // If a value depends on a SCEVUnknown which is defined after the loop, we @@ -2516,7 +2515,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); const Loop *AddRecLoop = AddRec->getLoop(); for (unsigned i = 0, e = Ops.size(); i != e; ++i) - if (isAvailableAtLoopEntry(Ops[i], AddRecLoop, DT, LI)) { + if (isAvailableAtLoopEntry(Ops[i], AddRecLoop)) { LIOps.push_back(Ops[i]); Ops.erase(Ops.begin()+i); --i; --e; @@ -2791,7 +2790,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); const Loop *AddRecLoop = AddRec->getLoop(); for (unsigned i = 0, e = Ops.size(); i != e; ++i) - if (isAvailableAtLoopEntry(Ops[i], AddRecLoop, DT, LI)) { + if (isAvailableAtLoopEntry(Ops[i], AddRecLoop)) { LIOps.push_back(Ops[i]); Ops.erase(Ops.begin()+i); --i; --e; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 114aea391a86..385c78bbccef 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -15,8 +15,8 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" @@ -393,7 +393,7 @@ void CodeViewDebug::endModule() { // subprograms. switchToDebugSectionForSymbol(nullptr); - MCSymbol *CompilerInfo = beginCVSubsection(ModuleDebugFragmentKind::Symbols); + MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols); emitCompilerInformation(); endCVSubsection(CompilerInfo); @@ -417,7 +417,7 @@ void CodeViewDebug::endModule() { // Emit UDT records for any types used by global variables. if (!GlobalUDTs.empty()) { - MCSymbol *SymbolsEnd = beginCVSubsection(ModuleDebugFragmentKind::Symbols); + MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols); emitDebugInfoForUDTs(GlobalUDTs); endCVSubsection(SymbolsEnd); } @@ -630,8 +630,7 @@ void CodeViewDebug::emitInlineeLinesSubsection() { return; OS.AddComment("Inlinee lines subsection"); - MCSymbol *InlineEnd = - beginCVSubsection(ModuleDebugFragmentKind::InlineeLines); + MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines); // We don't provide any extra file info. // FIXME: Find out if debuggers use this info. @@ -756,7 +755,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // Emit a symbol subsection, required by VS2012+ to find function boundaries. OS.AddComment("Symbol subsection for " + Twine(FuncName)); - MCSymbol *SymbolsEnd = beginCVSubsection(ModuleDebugFragmentKind::Symbols); + MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols); { MCSymbol *ProcRecordBegin = MMI->getContext().createTempSymbol(), *ProcRecordEnd = MMI->getContext().createTempSymbol(); @@ -2111,7 +2110,7 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) { maybeRecordLocation(DL, Asm->MF); } -MCSymbol *CodeViewDebug::beginCVSubsection(ModuleDebugFragmentKind Kind) { +MCSymbol *CodeViewDebug::beginCVSubsection(DebugSubsectionKind Kind) { MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(), *EndLabel = MMI->getContext().createTempSymbol(); OS.EmitIntValue(unsigned(Kind), 4); @@ -2171,7 +2170,7 @@ void CodeViewDebug::emitDebugInfoForGlobals() { if (!GV->hasComdat() && !GV->isDeclarationForLinker()) { if (!EndLabel) { OS.AddComment("Symbol subsection for globals"); - EndLabel = beginCVSubsection(ModuleDebugFragmentKind::Symbols); + EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); } // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. emitDebugInfoForGlobal(GVE->getVariable(), GV, Asm->getSymbol(GV)); @@ -2189,7 +2188,7 @@ void CodeViewDebug::emitDebugInfoForGlobals() { OS.AddComment("Symbol subsection for " + Twine(GlobalValue::dropLLVMManglingEscape(GV->getName()))); switchToDebugSectionForSymbol(GVSym); - EndLabel = beginCVSubsection(ModuleDebugFragmentKind::Symbols); + EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. emitDebugInfoForGlobal(GVE->getVariable(), GV, GVSym); endCVSubsection(EndLabel); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 46b2daa1e007..1c0c1644edaf 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -216,7 +216,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { /// Opens a subsection of the given kind in a .debug$S codeview section. /// Returns an end label for use with endCVSubsection when the subsection is /// finished. - MCSymbol *beginCVSubsection(codeview::ModuleDebugFragmentKind Kind); + MCSymbol *beginCVSubsection(codeview::DebugSubsectionKind Kind); void endCVSubsection(MCSymbol *EndLabel); diff --git a/contrib/llvm/lib/CodeGen/GlobalISel/Localizer.cpp b/contrib/llvm/lib/CodeGen/GlobalISel/Localizer.cpp index bdca732b4e33..c2a568e4b452 100644 --- a/contrib/llvm/lib/CodeGen/GlobalISel/Localizer.cpp +++ b/contrib/llvm/lib/CodeGen/GlobalISel/Localizer.cpp @@ -23,7 +23,7 @@ using namespace llvm; char Localizer::ID = 0; INITIALIZE_PASS(Localizer, DEBUG_TYPE, "Move/duplicate certain instructions close to their use", false, - false); + false) Localizer::Localizer() : MachineFunctionPass(ID) { initializeLocalizerPass(*PassRegistry::getPassRegistry()); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 23a302f3e561..ab36bc1417ae 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14567,7 +14567,8 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG) { // extract instead or remove that condition entirely. auto *Ld = dyn_cast(Extract->getOperand(0)); auto *ExtIdx = dyn_cast(Extract->getOperand(1)); - if (!Ld || !Ld->hasOneUse() || Ld->isVolatile() || !ExtIdx) + if (!Ld || !Ld->hasOneUse() || Ld->getExtensionType() || Ld->isVolatile() || + !ExtIdx) return SDValue(); // The narrow load will be offset from the base address of the old load if diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index d0a8b34c69c6..da2fb72bec45 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -925,10 +925,6 @@ getStrictFPOpcodeAction(const TargetLowering &TLI, unsigned Opcode, EVT VT) { if (Action != TargetLowering::Legal) Action = TargetLowering::Expand; - // ISD::FPOWI returns 'Legal' even though it should be expanded. - if (Opcode == ISD::STRICT_FPOWI && Action == TargetLowering::Legal) - Action = TargetLowering::Expand; - return Action; } @@ -1027,7 +1023,6 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) { break; case ISD::EXTRACT_ELEMENT: case ISD::FLT_ROUNDS_: - case ISD::FPOWI: case ISD::MERGE_VALUES: case ISD::EH_RETURN: case ISD::FRAME_TO_ARGS_OFFSET: diff --git a/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp b/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp index 5f63fd4320bb..0def5ae6d0d0 100644 --- a/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -935,6 +935,7 @@ void TargetLoweringBase::initActions() { // These library functions default to expand. setOperationAction(ISD::FROUND, VT, Expand); + setOperationAction(ISD::FPOWI, VT, Expand); // These operations default to expand for vector types. if (VT.isVector()) { diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp similarity index 72% rename from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp rename to contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp index 42f0afc3e2d7..1a85a339f8c3 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp @@ -1,4 +1,4 @@ -//===- ModuleDebugFileChecksumFragment.cpp ----------------------*- C++ -*-===// +//===- DebugChecksumsSubsection.cpp ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/Support/BinaryStreamReader.h" using namespace llvm; @@ -42,22 +42,24 @@ Error llvm::VarStreamArrayExtractor::extract( return Error::success(); } -Error ModuleDebugFileChecksumFragmentRef::initialize( - BinaryStreamReader Reader) { +Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) { if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) return EC; return Error::success(); } +Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) { + BinaryStreamReader Reader(Section); + return initialize(Reader); +} -ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment( - StringTable &Strings) - : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums), - Strings(Strings) {} +DebugChecksumsSubsection::DebugChecksumsSubsection( + DebugStringTableSubsection &Strings) + : DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {} -void ModuleDebugFileChecksumFragment::addChecksum(StringRef FileName, - FileChecksumKind Kind, - ArrayRef Bytes) { +void DebugChecksumsSubsection::addChecksum(StringRef FileName, + FileChecksumKind Kind, + ArrayRef Bytes) { FileChecksumEntry Entry; if (!Bytes.empty()) { uint8_t *Copy = Storage.Allocate(Bytes.size()); @@ -78,11 +80,11 @@ void ModuleDebugFileChecksumFragment::addChecksum(StringRef FileName, SerializedSize += Len; } -uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() { +uint32_t DebugChecksumsSubsection::calculateSerializedSize() const { return SerializedSize; } -Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) { +Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const { for (const auto &FC : Checksums) { FileChecksumEntryHeader Header; Header.ChecksumKind = uint8_t(FC.Kind); @@ -98,8 +100,7 @@ Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) { return Error::success(); } -uint32_t -ModuleDebugFileChecksumFragment::mapChecksumOffset(StringRef FileName) const { +uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const { uint32_t Offset = Strings.getStringId(FileName); auto Iter = OffsetMap.find(Offset); assert(Iter != OffsetMap.end()); diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp new file mode 100644 index 000000000000..fd558aa9cc8a --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp @@ -0,0 +1,44 @@ +//===- DebugFrameDataSubsection.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" +#include "llvm/DebugInfo/CodeView/CodeViewError.h" + +using namespace llvm; +using namespace llvm::codeview; + +Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) { + if (auto EC = Reader.readObject(RelocPtr)) + return EC; + if (Reader.bytesRemaining() % sizeof(FrameData) != 0) + return make_error(cv_error_code::corrupt_record, + "Invalid frame data record format!"); + + uint32_t Count = Reader.bytesRemaining() / sizeof(FrameData); + if (auto EC = Reader.readArray(Frames, Count)) + return EC; + return Error::success(); +} + +uint32_t DebugFrameDataSubsection::calculateSerializedSize() const { + return 4 + sizeof(FrameData) * Frames.size(); +} + +Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const { + if (auto EC = Writer.writeInteger(0)) + return EC; + + if (auto EC = Writer.writeArray(makeArrayRef(Frames))) + return EC; + return Error::success(); +} + +void DebugFrameDataSubsection::addFrameData(const FrameData &Frame) { + Frames.push_back(Frame); +} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp similarity index 66% rename from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp rename to contrib/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp index cb6a8478797f..520a0ee4454f 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp @@ -1,4 +1,4 @@ -//===- ModuleDebugInlineeLineFragment.cpp ------------------------*- C++-*-===// +//===- DebugInlineeLinesSubsection.cpp ------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" using namespace llvm; using namespace llvm::codeview; @@ -37,10 +37,10 @@ Error VarStreamArrayExtractor::extract( return Error::success(); } -ModuleDebugInlineeLineFragmentRef::ModuleDebugInlineeLineFragmentRef() - : ModuleDebugFragmentRef(ModuleDebugFragmentKind::InlineeLines) {} +DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {} -Error ModuleDebugInlineeLineFragmentRef::initialize(BinaryStreamReader Reader) { +Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) { if (auto EC = Reader.readEnum(Signature)) return EC; @@ -52,16 +52,16 @@ Error ModuleDebugInlineeLineFragmentRef::initialize(BinaryStreamReader Reader) { return Error::success(); } -bool ModuleDebugInlineeLineFragmentRef::hasExtraFiles() const { +bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const { return Signature == InlineeLinesSignature::ExtraFiles; } -ModuleDebugInlineeLineFragment::ModuleDebugInlineeLineFragment( - ModuleDebugFileChecksumFragment &Checksums, bool HasExtraFiles) - : ModuleDebugFragment(ModuleDebugFragmentKind::InlineeLines), - Checksums(Checksums), HasExtraFiles(HasExtraFiles) {} +DebugInlineeLinesSubsection::DebugInlineeLinesSubsection( + DebugChecksumsSubsection &Checksums, bool HasExtraFiles) + : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums), + HasExtraFiles(HasExtraFiles) {} -uint32_t ModuleDebugInlineeLineFragment::calculateSerializedLength() { +uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const { // 4 bytes for the signature uint32_t Size = sizeof(InlineeLinesSignature); @@ -78,7 +78,7 @@ uint32_t ModuleDebugInlineeLineFragment::calculateSerializedLength() { return Size; } -Error ModuleDebugInlineeLineFragment::commit(BinaryStreamWriter &Writer) { +Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const { InlineeLinesSignature Sig = InlineeLinesSignature::Normal; if (HasExtraFiles) Sig = InlineeLinesSignature::ExtraFiles; @@ -102,7 +102,7 @@ Error ModuleDebugInlineeLineFragment::commit(BinaryStreamWriter &Writer) { return Error::success(); } -void ModuleDebugInlineeLineFragment::addExtraFile(StringRef FileName) { +void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) { uint32_t Offset = Checksums.mapChecksumOffset(FileName); auto &Entry = Entries.back(); @@ -110,9 +110,9 @@ void ModuleDebugInlineeLineFragment::addExtraFile(StringRef FileName) { ++ExtraFileCount; } -void ModuleDebugInlineeLineFragment::addInlineSite(TypeIndex FuncId, - StringRef FileName, - uint32_t SourceLine) { +void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId, + StringRef FileName, + uint32_t SourceLine) { uint32_t Offset = Checksums.mapChecksumOffset(FileName); Entries.emplace_back(); diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp similarity index 69% rename from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp rename to contrib/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp index e0ee934709ba..2fce06ca2a17 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp @@ -1,4 +1,4 @@ -//===- ModuleDebugLineFragment.cpp -------------------------------*- C++-*-===// +//===- DebugLinesSubsection.cpp -------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" using namespace llvm; using namespace llvm::codeview; @@ -49,10 +49,10 @@ Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len, return Error::success(); } -ModuleDebugLineFragmentRef::ModuleDebugLineFragmentRef() - : ModuleDebugFragmentRef(ModuleDebugFragmentKind::Lines) {} +DebugLinesSubsectionRef::DebugLinesSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::Lines) {} -Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) { +Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) { if (auto EC = Reader.readObject(Header)) return EC; @@ -63,23 +63,21 @@ Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) { return Error::success(); } -bool ModuleDebugLineFragmentRef::hasColumnInfo() const { +bool DebugLinesSubsectionRef::hasColumnInfo() const { return !!(Header->Flags & LF_HaveColumns); } -ModuleDebugLineFragment::ModuleDebugLineFragment( - ModuleDebugFileChecksumFragment &Checksums, StringTable &Strings) - : ModuleDebugFragment(ModuleDebugFragmentKind::Lines), - Checksums(Checksums) {} +DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums, + DebugStringTableSubsection &Strings) + : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {} -void ModuleDebugLineFragment::createBlock(StringRef FileName) { +void DebugLinesSubsection::createBlock(StringRef FileName) { uint32_t Offset = Checksums.mapChecksumOffset(FileName); Blocks.emplace_back(Offset); } -void ModuleDebugLineFragment::addLineInfo(uint32_t Offset, - const LineInfo &Line) { +void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) { Block &B = Blocks.back(); LineNumberEntry LNE; LNE.Flags = Line.getRawData(); @@ -87,10 +85,10 @@ void ModuleDebugLineFragment::addLineInfo(uint32_t Offset, B.Lines.push_back(LNE); } -void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset, - const LineInfo &Line, - uint32_t ColStart, - uint32_t ColEnd) { +void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset, + const LineInfo &Line, + uint32_t ColStart, + uint32_t ColEnd) { Block &B = Blocks.back(); assert(B.Lines.size() == B.Columns.size()); @@ -101,7 +99,7 @@ void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset, B.Columns.push_back(CNE); } -Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) { +Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const { LineFragmentHeader Header; Header.CodeSize = CodeSize; Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; @@ -135,7 +133,7 @@ Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) { return Error::success(); } -uint32_t ModuleDebugLineFragment::calculateSerializedLength() { +uint32_t DebugLinesSubsection::calculateSerializedSize() const { uint32_t Size = sizeof(LineFragmentHeader); for (const auto &B : Blocks) { Size += sizeof(LineBlockFragmentHeader); @@ -146,16 +144,16 @@ uint32_t ModuleDebugLineFragment::calculateSerializedLength() { return Size; } -void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment, - uint16_t Offset) { +void DebugLinesSubsection::setRelocationAddress(uint16_t Segment, + uint16_t Offset) { RelocOffset = Offset; RelocSegment = Segment; } -void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; } +void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; } -void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; } +void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; } -bool ModuleDebugLineFragment::hasColumnInfo() const { +bool DebugLinesSubsection::hasColumnInfo() const { return Flags & LF_HaveColumns; } diff --git a/contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp similarity index 61% rename from contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp rename to contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index 21f11204686b..b8741eb0b675 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -1,4 +1,4 @@ -//===- StringTable.cpp - CodeView String Table Reader/Writer ----*- C++ -*-===// +//===- DebugStringTableSubsection.cpp - CodeView String Table ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/StringTable.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/Support/BinaryStream.h" #include "llvm/Support/BinaryStreamReader.h" @@ -16,14 +16,16 @@ using namespace llvm; using namespace llvm::codeview; -StringTableRef::StringTableRef() {} +DebugStringTableSubsectionRef::DebugStringTableSubsectionRef() + : DebugSubsectionRef(DebugSubsectionKind::StringTable) {} -Error StringTableRef::initialize(BinaryStreamRef Contents) { +Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) { Stream = Contents; return Error::success(); } -Expected StringTableRef::getString(uint32_t Offset) const { +Expected +DebugStringTableSubsectionRef::getString(uint32_t Offset) const { BinaryStreamReader Reader(Stream); Reader.setOffset(Offset); StringRef Result; @@ -32,7 +34,10 @@ Expected StringTableRef::getString(uint32_t Offset) const { return Result; } -uint32_t StringTable::insert(StringRef S) { +DebugStringTableSubsection::DebugStringTableSubsection() + : DebugSubsection(DebugSubsectionKind::StringTable) {} + +uint32_t DebugStringTableSubsection::insert(StringRef S) { auto P = Strings.insert({S, StringSize}); // If a given string didn't exist in the string table, we want to increment @@ -42,9 +47,11 @@ uint32_t StringTable::insert(StringRef S) { return P.first->second; } -uint32_t StringTable::calculateSerializedSize() const { return StringSize; } +uint32_t DebugStringTableSubsection::calculateSerializedSize() const { + return StringSize; +} -Error StringTable::commit(BinaryStreamWriter &Writer) const { +Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { assert(Writer.bytesRemaining() == StringSize); uint32_t MaxOffset = 1; @@ -62,9 +69,9 @@ Error StringTable::commit(BinaryStreamWriter &Writer) const { return Error::success(); } -uint32_t StringTable::size() const { return Strings.size(); } +uint32_t DebugStringTableSubsection::size() const { return Strings.size(); } -uint32_t StringTable::getStringId(StringRef S) const { +uint32_t DebugStringTableSubsection::getStringId(StringRef S) const { auto P = Strings.find(S); assert(P != Strings.end()); return P->second; diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp similarity index 55% rename from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp rename to contrib/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp index 2af1917413da..67b428bfa713 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp @@ -1,4 +1,4 @@ -//===- ModuleDebugFragment.cpp -----------------------------------*- C++-*-===// +//===- DebugSubsection.cpp -----------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" using namespace llvm::codeview; -ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {} +DebugSubsectionRef::~DebugSubsectionRef() {} -ModuleDebugFragment::~ModuleDebugFragment() {} +DebugSubsection::~DebugSubsection() {} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp new file mode 100644 index 000000000000..511f36d0020a --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -0,0 +1,81 @@ +//===- DebugSubsectionRecord.cpp -----------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" + +#include "llvm/Support/BinaryStreamReader.h" + +using namespace llvm; +using namespace llvm::codeview; + +DebugSubsectionRecord::DebugSubsectionRecord() + : Kind(DebugSubsectionKind::None) {} + +DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind, + BinaryStreamRef Data) + : Kind(Kind), Data(Data) {} + +Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, + DebugSubsectionRecord &Info) { + const DebugSubsectionHeader *Header; + BinaryStreamReader Reader(Stream); + if (auto EC = Reader.readObject(Header)) + return EC; + + DebugSubsectionKind Kind = + static_cast(uint32_t(Header->Kind)); + switch (Kind) { + case DebugSubsectionKind::FileChecksums: + case DebugSubsectionKind::Lines: + case DebugSubsectionKind::InlineeLines: + break; + default: + llvm_unreachable("Unexpected debug fragment kind!"); + } + if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) + return EC; + Info.Kind = Kind; + return Error::success(); +} + +uint32_t DebugSubsectionRecord::getRecordLength() const { + uint32_t Result = sizeof(DebugSubsectionHeader) + Data.getLength(); + assert(Result % 4 == 0); + return Result; +} + +DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } + +BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } + +DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( + DebugSubsectionKind Kind, DebugSubsection &Frag) + : Kind(Kind), Frag(Frag) {} + +uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { + uint32_t Size = sizeof(DebugSubsectionHeader) + + alignTo(Frag.calculateSerializedSize(), 4); + return Size; +} + +Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) { + DebugSubsectionHeader Header; + Header.Kind = uint32_t(Kind); + Header.Length = calculateSerializedLength() - sizeof(DebugSubsectionHeader); + + if (auto EC = Writer.writeObject(Header)) + return EC; + if (auto EC = Frag.commit(Writer)) + return EC; + if (auto EC = Writer.padToAlignment(4)) + return EC; + + return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp new file mode 100644 index 000000000000..f2c4dea8685f --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -0,0 +1,52 @@ +//===- DebugSubsectionVisitor.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" + +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamRef.h" + +using namespace llvm; +using namespace llvm::codeview; + +Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, + DebugSubsectionVisitor &V) { + BinaryStreamReader Reader(R.getRecordData()); + switch (R.kind()) { + case DebugSubsectionKind::Lines: { + DebugLinesSubsectionRef Fragment; + if (auto EC = Fragment.initialize(Reader)) + return EC; + + return V.visitLines(Fragment); + } + case DebugSubsectionKind::FileChecksums: { + DebugChecksumsSubsectionRef Fragment; + if (auto EC = Fragment.initialize(Reader)) + return EC; + + return V.visitFileChecksums(Fragment); + } + case DebugSubsectionKind::InlineeLines: { + DebugInlineeLinesSubsectionRef Fragment; + if (auto EC = Fragment.initialize(Reader)) + return EC; + return V.visitInlineeLines(Fragment); + } + default: { + DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData()); + return V.visitUnknown(Fragment); + } + } +} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp b/contrib/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp new file mode 100644 index 000000000000..dc8ba8c929ae --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp @@ -0,0 +1,34 @@ +//===- DebugSymbolsSubsection.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" + +using namespace llvm; +using namespace llvm::codeview; + +Error DebugSymbolsSubsectionRef::initialize(BinaryStreamReader Reader) { + return Reader.readArray(Records, Reader.getLength()); +} + +uint32_t DebugSymbolsSubsection::calculateSerializedSize() const { + return Length; +} + +Error DebugSymbolsSubsection::commit(BinaryStreamWriter &Writer) const { + for (const auto &Record : Records) { + if (auto EC = Writer.writeBytes(Record.RecordData)) + return EC; + } + return Error::success(); +} + +void DebugSymbolsSubsection::addSymbol(CVSymbol Symbol) { + Records.push_back(Symbol); + Length += Symbol.length(); +} \ No newline at end of file diff --git a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp index fc6008ba66de..0441110c85ef 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp @@ -245,20 +245,20 @@ static const EnumEntry FrameProcSymFlagNames[] = { }; static const EnumEntry ModuleSubstreamKindNames[] = { - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, None), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Symbols), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Lines), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, StringTable), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FileChecksums), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FrameData), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, InlineeLines), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeImports), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeExports), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, ILLines), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FuncMDTokenMap), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, TypeMDTokenMap), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, MergedAssemblyInput), - CV_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CoffSymbolRVA), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, None), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, Symbols), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, Lines), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, StringTable), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, FileChecksums), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, FrameData), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, InlineeLines), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeImports), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeExports), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, ILLines), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, FuncMDTokenMap), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, TypeMDTokenMap), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, MergedAssemblyInput), + CV_ENUM_CLASS_ENT(DebugSubsectionKind, CoffSymbolRVA), }; static const EnumEntry ExportSymFlagNames[] = { diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp deleted file mode 100644 index b2543de78069..000000000000 --- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp +++ /dev/null @@ -1,84 +0,0 @@ -//===- ModuleDebugFragmentRecord.cpp -----------------------------*- C++-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" - -#include "llvm/Support/BinaryStreamReader.h" - -using namespace llvm; -using namespace llvm::codeview; - -ModuleDebugFragmentRecord::ModuleDebugFragmentRecord() - : Kind(ModuleDebugFragmentKind::None) {} - -ModuleDebugFragmentRecord::ModuleDebugFragmentRecord( - ModuleDebugFragmentKind Kind, BinaryStreamRef Data) - : Kind(Kind), Data(Data) {} - -Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream, - ModuleDebugFragmentRecord &Info) { - const ModuleDebugFragmentHeader *Header; - BinaryStreamReader Reader(Stream); - if (auto EC = Reader.readObject(Header)) - return EC; - - ModuleDebugFragmentKind Kind = - static_cast(uint32_t(Header->Kind)); - switch (Kind) { - case ModuleDebugFragmentKind::FileChecksums: - case ModuleDebugFragmentKind::Lines: - case ModuleDebugFragmentKind::InlineeLines: - break; - default: - llvm_unreachable("Unexpected debug fragment kind!"); - } - if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) - return EC; - Info.Kind = Kind; - return Error::success(); -} - -uint32_t ModuleDebugFragmentRecord::getRecordLength() const { - uint32_t Result = sizeof(ModuleDebugFragmentHeader) + Data.getLength(); - assert(Result % 4 == 0); - return Result; -} - -ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; } - -BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const { - return Data; -} - -ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder( - ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag) - : Kind(Kind), Frag(Frag) {} - -uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() { - uint32_t Size = sizeof(ModuleDebugFragmentHeader) + - alignTo(Frag.calculateSerializedLength(), 4); - return Size; -} - -Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) { - ModuleDebugFragmentHeader Header; - Header.Kind = uint32_t(Kind); - Header.Length = - calculateSerializedLength() - sizeof(ModuleDebugFragmentHeader); - - if (auto EC = Writer.writeObject(Header)) - return EC; - if (auto EC = Frag.commit(Writer)) - return EC; - if (auto EC = Writer.padToAlignment(4)) - return EC; - - return Error::success(); -} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp deleted file mode 100644 index dc591f3990e2..000000000000 --- a/contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===- ModuleDebugFragmentVisitor.cpp ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" - -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" -#include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/BinaryStreamRef.h" - -using namespace llvm; -using namespace llvm::codeview; - -Error llvm::codeview::visitModuleDebugFragment( - const ModuleDebugFragmentRecord &R, ModuleDebugFragmentVisitor &V) { - BinaryStreamReader Reader(R.getRecordData()); - switch (R.kind()) { - case ModuleDebugFragmentKind::Lines: { - ModuleDebugLineFragmentRef Fragment; - if (auto EC = Fragment.initialize(Reader)) - return EC; - - return V.visitLines(Fragment); - } - case ModuleDebugFragmentKind::FileChecksums: { - ModuleDebugFileChecksumFragmentRef Fragment; - if (auto EC = Fragment.initialize(Reader)) - return EC; - - return V.visitFileChecksums(Fragment); - } - case ModuleDebugFragmentKind::InlineeLines: { - ModuleDebugInlineeLineFragmentRef Fragment; - if (auto EC = Fragment.initialize(Reader)) - return EC; - return V.visitInlineeLines(Fragment); - } - default: { - ModuleDebugUnknownFragmentRef Fragment(R.kind(), R.getRecordData()); - return V.visitUnknown(Fragment); - } - } -} diff --git a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 7d01c8c5f194..2f5a7d256c60 100644 --- a/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -11,8 +11,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" @@ -369,7 +369,7 @@ Error CVSymbolDumperImpl::visitKnownRecord( DictScope S(W, "DefRangeSubfield"); if (ObjDelegate) { - StringTableRef Strings = ObjDelegate->getStringTable(); + DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program); if (!ExpectedProgram) { consumeError(ExpectedProgram.takeError()); @@ -390,7 +390,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DictScope S(W, "DefRange"); if (ObjDelegate) { - StringTableRef Strings = ObjDelegate->getStringTable(); + DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); auto ExpectedProgram = Strings.getString(DefRange.Program); if (!ExpectedProgram) { consumeError(ExpectedProgram.takeError()); diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 867864e47dce..b28ec2ff33ac 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -10,7 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" @@ -170,8 +170,8 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, } void DbiModuleDescriptorBuilder::addC13Fragment( - std::unique_ptr Lines) { - ModuleDebugLineFragment &Frag = *Lines; + std::unique_ptr Lines) { + DebugLinesSubsection &Frag = *Lines; // File Checksums have to come first, so push an empty entry on if this // is the first. @@ -180,12 +180,12 @@ void DbiModuleDescriptorBuilder::addC13Fragment( this->LineInfo.push_back(std::move(Lines)); C13Builders.push_back( - llvm::make_unique(Frag.kind(), Frag)); + llvm::make_unique(Frag.kind(), Frag)); } void DbiModuleDescriptorBuilder::addC13Fragment( - std::unique_ptr Inlinees) { - ModuleDebugInlineeLineFragment &Frag = *Inlinees; + std::unique_ptr Inlinees) { + DebugInlineeLinesSubsection &Frag = *Inlinees; // File Checksums have to come first, so push an empty entry on if this // is the first. @@ -194,17 +194,17 @@ void DbiModuleDescriptorBuilder::addC13Fragment( this->Inlinees.push_back(std::move(Inlinees)); C13Builders.push_back( - llvm::make_unique(Frag.kind(), Frag)); + llvm::make_unique(Frag.kind(), Frag)); } void DbiModuleDescriptorBuilder::setC13FileChecksums( - std::unique_ptr Checksums) { + std::unique_ptr Checksums) { assert(!ChecksumInfo && "Can't have more than one checksum info!"); if (C13Builders.empty()) C13Builders.push_back(nullptr); ChecksumInfo = std::move(Checksums); - C13Builders[0] = llvm::make_unique( + C13Builders[0] = llvm::make_unique( ChecksumInfo->kind(), *ChecksumInfo); } diff --git a/contrib/llvm/lib/MC/MCCodeView.cpp b/contrib/llvm/lib/MC/MCCodeView.cpp index 2b97ecc0fd2c..a0a0ef312276 100644 --- a/contrib/llvm/lib/MC/MCCodeView.cpp +++ b/contrib/llvm/lib/MC/MCCodeView.cpp @@ -145,7 +145,7 @@ void CodeViewContext::emitStringTable(MCObjectStreamer &OS) { MCSymbol *StringBegin = Ctx.createTempSymbol("strtab_begin", false), *StringEnd = Ctx.createTempSymbol("strtab_end", false); - OS.EmitIntValue(unsigned(ModuleDebugFragmentKind::StringTable), 4); + OS.EmitIntValue(unsigned(DebugSubsectionKind::StringTable), 4); OS.emitAbsoluteSymbolDiff(StringEnd, StringBegin, 4); OS.EmitLabel(StringBegin); @@ -172,7 +172,7 @@ void CodeViewContext::emitFileChecksums(MCObjectStreamer &OS) { MCSymbol *FileBegin = Ctx.createTempSymbol("filechecksums_begin", false), *FileEnd = Ctx.createTempSymbol("filechecksums_end", false); - OS.EmitIntValue(unsigned(ModuleDebugFragmentKind::FileChecksums), 4); + OS.EmitIntValue(unsigned(DebugSubsectionKind::FileChecksums), 4); OS.emitAbsoluteSymbolDiff(FileEnd, FileBegin, 4); OS.EmitLabel(FileBegin); @@ -197,7 +197,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, MCSymbol *LineBegin = Ctx.createTempSymbol("linetable_begin", false), *LineEnd = Ctx.createTempSymbol("linetable_end", false); - OS.EmitIntValue(unsigned(ModuleDebugFragmentKind::Lines), 4); + OS.EmitIntValue(unsigned(DebugSubsectionKind::Lines), 4); OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4); OS.EmitLabel(LineBegin); OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0); diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index e1e2c22e1df1..f36c25a0ce91 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -1559,11 +1559,13 @@ IEEEFloat::opStatus IEEEFloat::divideSpecials(const IEEEFloat &rhs) { case PackCategoriesIntoKey(fcInfinity, fcNaN): category = fcNaN; copySignificand(rhs); + LLVM_FALLTHROUGH; case PackCategoriesIntoKey(fcNaN, fcZero): case PackCategoriesIntoKey(fcNaN, fcNormal): case PackCategoriesIntoKey(fcNaN, fcInfinity): case PackCategoriesIntoKey(fcNaN, fcNaN): sign = false; + LLVM_FALLTHROUGH; case PackCategoriesIntoKey(fcInfinity, fcZero): case PackCategoriesIntoKey(fcInfinity, fcNormal): case PackCategoriesIntoKey(fcZero, fcInfinity): diff --git a/contrib/llvm/lib/Support/Timer.cpp b/contrib/llvm/lib/Support/Timer.cpp index 8d68c6ae9682..dec6baf7bf47 100644 --- a/contrib/llvm/lib/Support/Timer.cpp +++ b/contrib/llvm/lib/Support/Timer.cpp @@ -72,10 +72,15 @@ std::unique_ptr llvm::CreateInfoOutputFile() { return llvm::make_unique(2, false); // stderr. } -static TimerGroup *getDefaultTimerGroup() { - static TimerGroup DefaultTimerGroup("misc", "Miscellaneous Ungrouped Timers"); - return &DefaultTimerGroup; -} +namespace { +struct CreateDefaultTimerGroup { + static void *call() { + return new TimerGroup("misc", "Miscellaneous Ungrouped Timers"); + } +}; +} // namespace +static ManagedStatic DefaultTimerGroup; +static TimerGroup *getDefaultTimerGroup() { return &*DefaultTimerGroup; } //===----------------------------------------------------------------------===// // Timer Implementation diff --git a/contrib/llvm/lib/TableGen/Record.cpp b/contrib/llvm/lib/TableGen/Record.cpp index 09f9759ce7da..f07208b1fb90 100644 --- a/contrib/llvm/lib/TableGen/Record.cpp +++ b/contrib/llvm/lib/TableGen/Record.cpp @@ -405,27 +405,21 @@ IntInit::convertInitializerBitRange(ArrayRef Bits) const { } CodeInit *CodeInit::get(StringRef V) { - static DenseMap ThePool; + static StringMap ThePool(Allocator); - auto I = ThePool.insert(std::make_pair(V, nullptr)); - if (I.second) { - StringRef VCopy = V.copy(Allocator); - I.first->first = VCopy; - I.first->second = new(Allocator) CodeInit(VCopy); - } - return I.first->second; + auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first; + if (!Entry.second) + Entry.second = new(Allocator) CodeInit(Entry.getKey()); + return Entry.second; } StringInit *StringInit::get(StringRef V) { - static DenseMap ThePool; + static StringMap ThePool(Allocator); - auto I = ThePool.insert(std::make_pair(V, nullptr)); - if (I.second) { - StringRef VCopy = V.copy(Allocator); - I.first->first = VCopy; - I.first->second = new(Allocator) StringInit(VCopy); - } - return I.first->second; + auto &Entry = *ThePool.insert(std::make_pair(V, nullptr)).first; + if (!Entry.second) + Entry.second = new(Allocator) StringInit(Entry.getKey()); + return Entry.second; } Init *StringInit::convertInitializerTo(RecTy *Ty) const { @@ -1540,7 +1534,7 @@ Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const { SmallVector NewArgs; NewArgs.reserve(arg_size()); bool ArgsChanged = false; - for (const Init *Arg : args()) { + for (const Init *Arg : getArgs()) { Init *NewArg = Arg->resolveReferences(R, RV); NewArgs.push_back(NewArg); ArgsChanged |= NewArg != Arg; diff --git a/contrib/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/contrib/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 0b92249580c8..e96ee7d29b3e 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/contrib/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -137,6 +137,34 @@ static cl::opt EnableRedZone("aarch64-redzone", STATISTIC(NumRedZoneFunctions, "Number of functions using red zone"); +/// Look at each instruction that references stack frames and return the stack +/// size limit beyond which some of these instructions will require a scratch +/// register during their expansion later. +static unsigned estimateRSStackSizeLimit(MachineFunction &MF) { + // FIXME: For now, just conservatively guestimate based on unscaled indexing + // range. We'll end up allocating an unnecessary spill slot a lot, but + // realistically that's not a big deal at this stage of the game. + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + if (MI.isDebugValue() || MI.isPseudo() || + MI.getOpcode() == AArch64::ADDXri || + MI.getOpcode() == AArch64::ADDSXri) + continue; + + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + if (!MI.getOperand(i).isFI()) + continue; + + int Offset = 0; + if (isAArch64FrameOffsetLegal(MI, Offset, nullptr, nullptr, nullptr) == + AArch64FrameOffsetCannotUpdate) + return 0; + } + } + } + return 255; +} + bool AArch64FrameLowering::canUseRedZone(const MachineFunction &MF) const { if (!EnableRedZone) return false; @@ -1169,16 +1197,13 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF, unsigned NumRegsSpilled = SavedRegs.count(); bool CanEliminateFrame = NumRegsSpilled == 0; - // FIXME: Set BigStack if any stack slot references may be out of range. - // For now, just conservatively guestimate based on unscaled indexing - // range. We'll end up allocating an unnecessary spill slot a lot, but - // realistically that's not a big deal at this stage of the game. // The CSR spill slots have not been allocated yet, so estimateStackSize // won't include them. MachineFrameInfo &MFI = MF.getFrameInfo(); unsigned CFSize = MFI.estimateStackSize(MF) + 8 * NumRegsSpilled; DEBUG(dbgs() << "Estimated stack frame size: " << CFSize << " bytes.\n"); - bool BigStack = (CFSize >= 256); + unsigned EstimatedStackSizeLimit = estimateRSStackSizeLimit(MF); + bool BigStack = (CFSize > EstimatedStackSizeLimit); if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) AFI->setHasStackFrame(true); diff --git a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 62f4c953830b..f798010906cc 100644 --- a/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -381,7 +381,6 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, setOperationAction(ISD::FNEARBYINT, MVT::v4f16, Expand); setOperationAction(ISD::FNEG, MVT::v4f16, Expand); setOperationAction(ISD::FPOW, MVT::v4f16, Expand); - setOperationAction(ISD::FPOWI, MVT::v4f16, Expand); setOperationAction(ISD::FREM, MVT::v4f16, Expand); setOperationAction(ISD::FROUND, MVT::v4f16, Expand); setOperationAction(ISD::FRINT, MVT::v4f16, Expand); @@ -413,7 +412,6 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, setOperationAction(ISD::FNEARBYINT, MVT::v8f16, Expand); setOperationAction(ISD::FNEG, MVT::v8f16, Expand); setOperationAction(ISD::FPOW, MVT::v8f16, Expand); - setOperationAction(ISD::FPOWI, MVT::v8f16, Expand); setOperationAction(ISD::FREM, MVT::v8f16, Expand); setOperationAction(ISD::FROUND, MVT::v8f16, Expand); setOperationAction(ISD::FRINT, MVT::v8f16, Expand); @@ -726,7 +724,6 @@ void AArch64TargetLowering::addTypeForNEON(MVT VT, MVT PromotedBitwiseVT) { if (VT == MVT::v2f32 || VT == MVT::v4f32 || VT == MVT::v2f64) { setOperationAction(ISD::FSIN, VT, Expand); setOperationAction(ISD::FCOS, VT, Expand); - setOperationAction(ISD::FPOWI, VT, Expand); setOperationAction(ISD::FPOW, VT, Expand); setOperationAction(ISD::FLOG, VT, Expand); setOperationAction(ISD::FLOG2, VT, Expand); diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index 660879426810..0582ce95693a 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -730,7 +730,7 @@ class SISubtarget final : public AMDGPUSubtarget { /// \returns True if waitcnt instruction is needed before barrier instruction, /// false otherwise. bool needWaitcntBeforeBarrier() const { - return getGeneration() < GFX9; + return true; } /// \returns true if the flat_scratch register should be initialized with the diff --git a/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index a9d3a31a7240..48827f463997 100644 --- a/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -736,6 +736,9 @@ void GCNPassConfig::addMachineSSAOptimization() { addPass(createSIShrinkInstructionsPass()); if (EnableSDWAPeephole) { addPass(&SIPeepholeSDWAID); + addPass(&MachineLICMID); + addPass(&MachineCSEID); + addPass(&SIFoldOperandsID); addPass(&DeadMachineInstructionElimID); } } diff --git a/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp b/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp index d63414735b95..f13629a3185f 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp @@ -247,9 +247,10 @@ static bool tryAddToFoldList(SmallVectorImpl &FoldList, // If the use operand doesn't care about the value, this may be an operand only // used for register indexing, in which case it is unsafe to fold. -static bool isUseSafeToFold(const MachineInstr &MI, +static bool isUseSafeToFold(const SIInstrInfo *TII, + const MachineInstr &MI, const MachineOperand &UseMO) { - return !UseMO.isUndef(); + return !UseMO.isUndef() && !TII->isSDWA(MI); //return !MI.hasRegisterImplicitUseOperand(UseMO.getReg()); } @@ -261,7 +262,7 @@ void SIFoldOperands::foldOperand( SmallVectorImpl &CopiesToReplace) const { const MachineOperand &UseOp = UseMI->getOperand(UseOpIdx); - if (!isUseSafeToFold(*UseMI, UseOp)) + if (!isUseSafeToFold(TII, *UseMI, UseOp)) return; // FIXME: Fold operands with subregs. diff --git a/contrib/llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp b/contrib/llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp index 4dc090d9b7ed..fae249b04492 100644 --- a/contrib/llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp +++ b/contrib/llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp @@ -55,6 +55,7 @@ class SIPeepholeSDWA : public MachineFunctionPass { std::unordered_map> SDWAOperands; std::unordered_map PotentialMatches; + SmallVector ConvertedInstructions; Optional foldToImm(const MachineOperand &Op) const; @@ -69,6 +70,7 @@ class SIPeepholeSDWA : public MachineFunctionPass { void matchSDWAOperands(MachineFunction &MF); bool isConvertibleToSDWA(const MachineInstr &MI) const; bool convertToSDWA(MachineInstr &MI, const SDWAOperandsVector &SDWAOperands); + void legalizeScalarOperands(MachineInstr &MI) const; StringRef getPassName() const override { return "SI Peephole SDWA"; } @@ -289,7 +291,7 @@ bool SDWASrcOperand::convertToSDWA(MachineInstr &MI, const SIInstrInfo *TII) { MachineOperand *SrcSel = TII->getNamedOperand(MI, AMDGPU::OpName::src0_sel); MachineOperand *SrcMods = TII->getNamedOperand(MI, AMDGPU::OpName::src0_modifiers); - assert(Src && Src->isReg()); + assert(Src && (Src->isReg() || Src->isImm())); if (!isSameReg(*Src, *getReplacedOperand())) { // If this is not src0 then it should be src1 Src = TII->getNamedOperand(MI, AMDGPU::OpName::src1); @@ -580,18 +582,8 @@ void SIPeepholeSDWA::matchSDWAOperands(MachineFunction &MF) { } bool SIPeepholeSDWA::isConvertibleToSDWA(const MachineInstr &MI) const { - // Check if this instruction can be converted to SDWA: - // 1. Does this opcode support SDWA - if (AMDGPU::getSDWAOp(MI.getOpcode()) == -1) - return false; - - // 2. Are all operands - VGPRs - for (const MachineOperand &Operand : MI.explicit_operands()) { - if (!Operand.isReg() || !TRI->isVGPR(*MRI, Operand.getReg())) - return false; - } - - return true; + // Check if this instruction has opcode that supports SDWA + return AMDGPU::getSDWAOp(MI.getOpcode()) != -1; } bool SIPeepholeSDWA::convertToSDWA(MachineInstr &MI, @@ -685,7 +677,9 @@ bool SIPeepholeSDWA::convertToSDWA(MachineInstr &MI, if (PotentialMatches.count(Operand->getParentInst()) == 0) Converted |= Operand->convertToSDWA(*SDWAInst, TII); } - if (!Converted) { + if (Converted) { + ConvertedInstructions.push_back(SDWAInst); + } else { SDWAInst->eraseFromParent(); return false; } @@ -698,6 +692,29 @@ bool SIPeepholeSDWA::convertToSDWA(MachineInstr &MI, return true; } +// If an instruction was converted to SDWA it should not have immediates or SGPR +// operands. Copy its scalar operands into VGPRs. +void SIPeepholeSDWA::legalizeScalarOperands(MachineInstr &MI) const { + const MCInstrDesc &Desc = TII->get(MI.getOpcode()); + for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) { + MachineOperand &Op = MI.getOperand(I); + if (!Op.isImm() && !(Op.isReg() && !TRI->isVGPR(*MRI, Op.getReg()))) + continue; + if (Desc.OpInfo[I].RegClass == -1 || + !TRI->hasVGPRs(TRI->getRegClass(Desc.OpInfo[I].RegClass))) + continue; + unsigned VGPR = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass); + auto Copy = BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(), + TII->get(AMDGPU::V_MOV_B32_e32), VGPR); + if (Op.isImm()) + Copy.addImm(Op.getImm()); + else if (Op.isReg()) + Copy.addReg(Op.getReg(), Op.isKill() ? RegState::Kill : 0, + Op.getSubReg()); + Op.ChangeToRegister(VGPR, false); + } +} + bool SIPeepholeSDWA::runOnMachineFunction(MachineFunction &MF) { const SISubtarget &ST = MF.getSubtarget(); @@ -728,5 +745,9 @@ bool SIPeepholeSDWA::runOnMachineFunction(MachineFunction &MF) { PotentialMatches.clear(); SDWAOperands.clear(); + + while (!ConvertedInstructions.empty()) + legalizeScalarOperands(*ConvertedInstructions.pop_back_val()); + return false; } diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp index 62e774d869da..949d821e36b2 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -585,7 +585,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FSQRT, MVT::v2f64, Expand); setOperationAction(ISD::FSIN, MVT::v2f64, Expand); setOperationAction(ISD::FCOS, MVT::v2f64, Expand); - setOperationAction(ISD::FPOWI, MVT::v2f64, Expand); setOperationAction(ISD::FPOW, MVT::v2f64, Expand); setOperationAction(ISD::FLOG, MVT::v2f64, Expand); setOperationAction(ISD::FLOG2, MVT::v2f64, Expand); @@ -603,7 +602,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FSQRT, MVT::v4f32, Expand); setOperationAction(ISD::FSIN, MVT::v4f32, Expand); setOperationAction(ISD::FCOS, MVT::v4f32, Expand); - setOperationAction(ISD::FPOWI, MVT::v4f32, Expand); setOperationAction(ISD::FPOW, MVT::v4f32, Expand); setOperationAction(ISD::FLOG, MVT::v4f32, Expand); setOperationAction(ISD::FLOG2, MVT::v4f32, Expand); @@ -620,7 +618,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FSQRT, MVT::v2f32, Expand); setOperationAction(ISD::FSIN, MVT::v2f32, Expand); setOperationAction(ISD::FCOS, MVT::v2f32, Expand); - setOperationAction(ISD::FPOWI, MVT::v2f32, Expand); setOperationAction(ISD::FPOW, MVT::v2f32, Expand); setOperationAction(ISD::FLOG, MVT::v2f32, Expand); setOperationAction(ISD::FLOG2, MVT::v2f32, Expand); @@ -743,7 +740,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FSQRT, MVT::f64, Expand); setOperationAction(ISD::FSIN, MVT::f64, Expand); setOperationAction(ISD::FCOS, MVT::f64, Expand); - setOperationAction(ISD::FPOWI, MVT::f64, Expand); setOperationAction(ISD::FPOW, MVT::f64, Expand); setOperationAction(ISD::FLOG, MVT::f64, Expand); setOperationAction(ISD::FLOG2, MVT::f64, Expand); diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 1dffebe97f2d..5ecf9320d5c2 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -2003,7 +2003,7 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, // Floating point arithmetic/math functions: ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FMA, ISD::FDIV, ISD::FREM, ISD::FNEG, ISD::FABS, ISD::FSQRT, ISD::FSIN, - ISD::FCOS, ISD::FPOWI, ISD::FPOW, ISD::FLOG, ISD::FLOG2, + ISD::FCOS, ISD::FPOW, ISD::FLOG, ISD::FLOG2, ISD::FLOG10, ISD::FEXP, ISD::FEXP2, ISD::FCEIL, ISD::FTRUNC, ISD::FRINT, ISD::FNEARBYINT, ISD::FROUND, ISD::FFLOOR, ISD::FMINNUM, ISD::FMAXNUM, ISD::FSINCOS, diff --git a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d407774574be..d855d3e7f778 100644 --- a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -13,6 +13,7 @@ #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsTargetStreamer.h" #include "MCTargetDesc/MipsBaseInfo.h" +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -216,9 +217,15 @@ class MipsAsmParser : public MCTargetAsmParser { unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, MCSymbol *Sym); + bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, bool Is64FPU, + SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandLoadAddress(unsigned DstReg, unsigned BaseReg, const MCOperand &Offset, bool Is32BitAddress, SMLoc IDLoc, MCStreamer &Out, @@ -1011,6 +1018,16 @@ class MipsOperand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); } + void addStrictlyAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); + } + + void addStrictlyFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getFGR64Reg())); + } + void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getFGR64Reg())); @@ -1027,6 +1044,15 @@ class MipsOperand : public MCParsedAsmOperand { "registers"); } + void addStrictlyFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getFGR32Reg())); + // FIXME: We ought to do this for -integrated-as without -via-file-asm too. + if (!AsmParser.useOddSPReg() && RegIdx.Index & 1) + AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU " + "registers"); + } + void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(getFGRH32Reg())); @@ -1574,6 +1600,11 @@ class MipsOperand : public MCParsedAsmOperand { return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; } + bool isStrictlyFGRAsmReg() const { + // AFGR64 is $0-$15 but we handle this in getAFGR64() + return isRegIdx() && RegIdx.Kind == RegKind_FGR && RegIdx.Index <= 31; + } + bool isHWRegsAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31; } @@ -2368,6 +2399,27 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::PseudoTRUNC_W_D: return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; + + case Mips::LoadImmSingleGPR: + return expandLoadImmReal(Inst, true, true, false, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; + case Mips::LoadImmSingleFGR: + return expandLoadImmReal(Inst, true, false, false, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; + case Mips::LoadImmDoubleGPR: + return expandLoadImmReal(Inst, false, true, false, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; + case Mips::LoadImmDoubleFGR: + return expandLoadImmReal(Inst, false, false, true, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; + case Mips::LoadImmDoubleFGR_32: + return expandLoadImmReal(Inst, false, false, false, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; case Mips::Ulh: return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::Ulhu: @@ -2952,6 +3004,302 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, return false; } +// Each double-precision register DO-D15 overlaps with two of the single +// precision registers F0-F31. As an example, all of the following hold true: +// D0 + 1 == F1, F1 + 1 == D1, F1 + 1 == F2, depending on the context. +static unsigned nextReg(unsigned Reg) { + if (MipsMCRegisterClasses[Mips::FGR32RegClassID].contains(Reg)) + return Reg == (unsigned)Mips::F31 ? (unsigned)Mips::F0 : Reg + 1; + switch (Reg) { + default: llvm_unreachable("Unknown register in assembly macro expansion!"); + case Mips::ZERO: return Mips::AT; + case Mips::AT: return Mips::V0; + case Mips::V0: return Mips::V1; + case Mips::V1: return Mips::A0; + case Mips::A0: return Mips::A1; + case Mips::A1: return Mips::A2; + case Mips::A2: return Mips::A3; + case Mips::A3: return Mips::T0; + case Mips::T0: return Mips::T1; + case Mips::T1: return Mips::T2; + case Mips::T2: return Mips::T3; + case Mips::T3: return Mips::T4; + case Mips::T4: return Mips::T5; + case Mips::T5: return Mips::T6; + case Mips::T6: return Mips::T7; + case Mips::T7: return Mips::S0; + case Mips::S0: return Mips::S1; + case Mips::S1: return Mips::S2; + case Mips::S2: return Mips::S3; + case Mips::S3: return Mips::S4; + case Mips::S4: return Mips::S5; + case Mips::S5: return Mips::S6; + case Mips::S6: return Mips::S7; + case Mips::S7: return Mips::T8; + case Mips::T8: return Mips::T9; + case Mips::T9: return Mips::K0; + case Mips::K0: return Mips::K1; + case Mips::K1: return Mips::GP; + case Mips::GP: return Mips::SP; + case Mips::SP: return Mips::FP; + case Mips::FP: return Mips::RA; + case Mips::RA: return Mips::ZERO; + case Mips::D0: return Mips::F1; + case Mips::D1: return Mips::F3; + case Mips::D2: return Mips::F5; + case Mips::D3: return Mips::F7; + case Mips::D4: return Mips::F9; + case Mips::D5: return Mips::F11; + case Mips::D6: return Mips::F13; + case Mips::D7: return Mips::F15; + case Mips::D8: return Mips::F17; + case Mips::D9: return Mips::F19; + case Mips::D10: return Mips::F21; + case Mips::D11: return Mips::F23; + case Mips::D12: return Mips::F25; + case Mips::D13: return Mips::F27; + case Mips::D14: return Mips::F29; + case Mips::D15: return Mips::F31; + } +} + +// FIXME: This method is too general. In principle we should compute the number +// of instructions required to synthesize the immediate inline compared to +// synthesizing the address inline and relying on non .text sections. +// For static O32 and N32 this may yield a small benefit, for static N64 this is +// likely to yield a much larger benefit as we have to synthesize a 64bit +// address to load a 64 bit value. +bool MipsAsmParser::emitPartialAddress(MipsTargetStreamer &TOut, SMLoc IDLoc, + MCSymbol *Sym) { + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + if(IsPicEnabled) { + const MCExpr *GotSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *GotExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT, GotSym, getContext()); + + if(isABI_O32() || isABI_N32()) { + TOut.emitRRX(Mips::LW, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), + IDLoc, STI); + } else { //isABI_N64() + TOut.emitRRX(Mips::LD, ATReg, Mips::GP, MCOperand::createExpr(GotExpr), + IDLoc, STI); + } + } else { //!IsPicEnabled + const MCExpr *HiSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *HiExpr = + MipsMCExpr::create(MipsMCExpr::MEK_HI, HiSym, getContext()); + + // FIXME: This is technically correct but gives a different result to gas, + // but gas is incomplete there (it has a fixme noting it doesn't work with + // 64-bit addresses). + // FIXME: With -msym32 option, the address expansion for N64 should probably + // use the O32 / N32 case. It's safe to use the 64 address expansion as the + // symbol's value is considered sign extended. + if(isABI_O32() || isABI_N32()) { + TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI); + } else { //isABI_N64() + const MCExpr *HighestSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *HighestExpr = + MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, HighestSym, getContext()); + const MCExpr *HigherSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *HigherExpr = + MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, HigherSym, getContext()); + + TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, + STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, + MCOperand::createExpr(HigherExpr), IDLoc, STI); + TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), + IDLoc, STI); + TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); + } + } + return false; +} + +bool MipsAsmParser::expandLoadImmReal(MCInst &Inst, bool IsSingle, bool IsGPR, + bool Is64FPU, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + assert(Inst.getNumOperands() == 2 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isImm() && + "Invalid instruction operand."); + + unsigned FirstReg = Inst.getOperand(0).getReg(); + uint64_t ImmOp64 = Inst.getOperand(1).getImm(); + + uint32_t HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32; + // If ImmOp64 is AsmToken::Integer type (all bits set to zero in the + // exponent field), convert it to double (e.g. 1 to 1.0) + if ((HiImmOp64 & 0x7ff00000) == 0) { + APFloat RealVal(APFloat::IEEEdouble(), ImmOp64); + ImmOp64 = RealVal.bitcastToAPInt().getZExtValue(); + } + + uint32_t LoImmOp64 = ImmOp64 & 0xffffffff; + HiImmOp64 = (ImmOp64 & 0xffffffff00000000) >> 32; + + if (IsSingle) { + // Conversion of a double in an uint64_t to a float in a uint32_t, + // retaining the bit pattern of a float. + uint32_t ImmOp32; + double doubleImm = BitsToDouble(ImmOp64); + float tmp_float = static_cast(doubleImm); + ImmOp32 = FloatToBits(tmp_float); + + if (IsGPR) { + if (loadImmediate(ImmOp32, FirstReg, Mips::NoRegister, true, true, IDLoc, + Out, STI)) + return true; + return false; + } else { + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + if (LoImmOp64 == 0) { + if (loadImmediate(ImmOp32, ATReg, Mips::NoRegister, true, true, IDLoc, + Out, STI)) + return true; + TOut.emitRR(Mips::MTC1, FirstReg, ATReg, IDLoc, STI); + return false; + } + + MCSection *CS = getStreamer().getCurrentSectionOnly(); + // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections + // where appropriate. + MCSection *ReadOnlySection = getContext().getELFSection( + ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); + + MCSymbol *Sym = getContext().createTempSymbol(); + const MCExpr *LoSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *LoExpr = + MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext()); + + getStreamer().SwitchSection(ReadOnlySection); + getStreamer().EmitLabel(Sym, IDLoc); + getStreamer().EmitIntValue(ImmOp32, 4); + getStreamer().SwitchSection(CS); + + if(emitPartialAddress(TOut, IDLoc, Sym)) + return true; + TOut.emitRRX(Mips::LWC1, FirstReg, ATReg, + MCOperand::createExpr(LoExpr), IDLoc, STI); + } + return false; + } + + // if(!IsSingle) + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + if (IsGPR) { + if (LoImmOp64 == 0) { + if(isABI_N32() || isABI_N64()) { + if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, false, true, + IDLoc, Out, STI)) + return true; + return false; + } else { + if (loadImmediate(HiImmOp64, FirstReg, Mips::NoRegister, true, true, + IDLoc, Out, STI)) + return true; + + if (loadImmediate(0, nextReg(FirstReg), Mips::NoRegister, true, true, + IDLoc, Out, STI)) + return true; + return false; + } + } + + MCSection *CS = getStreamer().getCurrentSectionOnly(); + MCSection *ReadOnlySection = getContext().getELFSection( + ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); + + MCSymbol *Sym = getContext().createTempSymbol(); + const MCExpr *LoSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *LoExpr = + MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext()); + + getStreamer().SwitchSection(ReadOnlySection); + getStreamer().EmitLabel(Sym, IDLoc); + getStreamer().EmitIntValue(HiImmOp64, 4); + getStreamer().EmitIntValue(LoImmOp64, 4); + getStreamer().SwitchSection(CS); + + if(emitPartialAddress(TOut, IDLoc, Sym)) + return true; + if(isABI_N64()) + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, + MCOperand::createExpr(LoExpr), IDLoc, STI); + else + TOut.emitRRX(Mips::ADDiu, ATReg, ATReg, + MCOperand::createExpr(LoExpr), IDLoc, STI); + + if(isABI_N32() || isABI_N64()) + TOut.emitRRI(Mips::LD, FirstReg, ATReg, 0, IDLoc, STI); + else { + TOut.emitRRI(Mips::LW, FirstReg, ATReg, 0, IDLoc, STI); + TOut.emitRRI(Mips::LW, nextReg(FirstReg), ATReg, 4, IDLoc, STI); + } + return false; + } else { // if(!IsGPR && !IsSingle) + if ((LoImmOp64 == 0) && + !((HiImmOp64 & 0xffff0000) && (HiImmOp64 & 0x0000ffff))) { + // FIXME: In the case where the constant is zero, we can load the + // register directly from the zero register. + if (loadImmediate(HiImmOp64, ATReg, Mips::NoRegister, true, true, IDLoc, + Out, STI)) + return true; + if (isABI_N32() || isABI_N64()) + TOut.emitRR(Mips::DMTC1, FirstReg, ATReg, IDLoc, STI); + else if (hasMips32r2()) { + TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI); + TOut.emitRRR(Mips::MTHC1_D32, FirstReg, FirstReg, ATReg, IDLoc, STI); + } else { + TOut.emitRR(Mips::MTC1, nextReg(FirstReg), ATReg, IDLoc, STI); + TOut.emitRR(Mips::MTC1, FirstReg, Mips::ZERO, IDLoc, STI); + } + return false; + } + + MCSection *CS = getStreamer().getCurrentSectionOnly(); + // FIXME: Enhance this expansion to use the .lit4 & .lit8 sections + // where appropriate. + MCSection *ReadOnlySection = getContext().getELFSection( + ".rodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); + + MCSymbol *Sym = getContext().createTempSymbol(); + const MCExpr *LoSym = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + const MipsMCExpr *LoExpr = + MipsMCExpr::create(MipsMCExpr::MEK_LO, LoSym, getContext()); + + getStreamer().SwitchSection(ReadOnlySection); + getStreamer().EmitLabel(Sym, IDLoc); + getStreamer().EmitIntValue(HiImmOp64, 4); + getStreamer().EmitIntValue(LoImmOp64, 4); + getStreamer().SwitchSection(CS); + + if(emitPartialAddress(TOut, IDLoc, Sym)) + return true; + TOut.emitRRX(Is64FPU ? Mips::LDC164 : Mips::LDC1, FirstReg, ATReg, + MCOperand::createExpr(LoExpr), IDLoc, STI); + } + return false; +} + bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { @@ -4318,45 +4666,6 @@ bool MipsAsmParser::expandDMULMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } -static unsigned nextReg(unsigned Reg) { - switch (Reg) { - case Mips::ZERO: return Mips::AT; - case Mips::AT: return Mips::V0; - case Mips::V0: return Mips::V1; - case Mips::V1: return Mips::A0; - case Mips::A0: return Mips::A1; - case Mips::A1: return Mips::A2; - case Mips::A2: return Mips::A3; - case Mips::A3: return Mips::T0; - case Mips::T0: return Mips::T1; - case Mips::T1: return Mips::T2; - case Mips::T2: return Mips::T3; - case Mips::T3: return Mips::T4; - case Mips::T4: return Mips::T5; - case Mips::T5: return Mips::T6; - case Mips::T6: return Mips::T7; - case Mips::T7: return Mips::S0; - case Mips::S0: return Mips::S1; - case Mips::S1: return Mips::S2; - case Mips::S2: return Mips::S3; - case Mips::S3: return Mips::S4; - case Mips::S4: return Mips::S5; - case Mips::S5: return Mips::S6; - case Mips::S6: return Mips::S7; - case Mips::S7: return Mips::T8; - case Mips::T8: return Mips::T9; - case Mips::T9: return Mips::K0; - case Mips::K0: return Mips::K1; - case Mips::K1: return Mips::GP; - case Mips::GP: return Mips::SP; - case Mips::SP: return Mips::FP; - case Mips::FP: return Mips::RA; - case Mips::RA: return Mips::ZERO; - default: return 0; - } - -} - // Expand 'ld $ offset($reg2)' to 'lw $, offset($reg2); // lw $>, offset+4($reg2)' // or expand 'sd $ offset($reg2)' to 'sw $, offset($reg2); diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp index 8fe4e75f3e18..760630c41176 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -362,7 +362,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::FCOS, MVT::f64, Expand); setOperationAction(ISD::FSINCOS, MVT::f32, Expand); setOperationAction(ISD::FSINCOS, MVT::f64, Expand); - setOperationAction(ISD::FPOWI, MVT::f32, Expand); setOperationAction(ISD::FPOW, MVT::f32, Expand); setOperationAction(ISD::FPOW, MVT::f64, Expand); setOperationAction(ISD::FLOG, MVT::f32, Expand); diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td index df42d56d041b..d81a769d7fd9 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td @@ -681,6 +681,29 @@ def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), "trunc.w.d\t$fd, $fs, $rs">, FGR_64, HARDFLOAT; +def LoadImmSingleGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins imm64:$fpimm), + "li.s\t$rd, $fpimm">; + +def LoadImmSingleFGR : MipsAsmPseudoInst<(outs StrictlyFGR32Opnd:$rd), + (ins imm64:$fpimm), + "li.s\t$rd, $fpimm">, + HARDFLOAT; + +def LoadImmDoubleGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins imm64:$fpimm), + "li.d\t$rd, $fpimm">; + +def LoadImmDoubleFGR_32 : MipsAsmPseudoInst<(outs StrictlyAFGR64Opnd:$rd), + (ins imm64:$fpimm), + "li.d\t$rd, $fpimm">, + FGR_32, HARDFLOAT; + +def LoadImmDoubleFGR : MipsAsmPseudoInst<(outs StrictlyFGR64Opnd:$rd), + (ins imm64:$fpimm), + "li.d\t$rd, $fpimm">, + FGR_64, HARDFLOAT; + //===----------------------------------------------------------------------===// // InstAliases. //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td index ccfdcc89b078..08fb3d7d4352 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -552,16 +552,31 @@ def AFGR64AsmOperand : MipsAsmRegOperand { let PredicateMethod = "isFGRAsmReg"; } +def StrictlyAFGR64AsmOperand : MipsAsmRegOperand { + let Name = "StrictlyAFGR64AsmReg"; + let PredicateMethod = "isStrictlyFGRAsmReg"; +} + def FGR64AsmOperand : MipsAsmRegOperand { let Name = "FGR64AsmReg"; let PredicateMethod = "isFGRAsmReg"; } +def StrictlyFGR64AsmOperand : MipsAsmRegOperand { + let Name = "StrictlyFGR64AsmReg"; + let PredicateMethod = "isStrictlyFGRAsmReg"; +} + def FGR32AsmOperand : MipsAsmRegOperand { let Name = "FGR32AsmReg"; let PredicateMethod = "isFGRAsmReg"; } +def StrictlyFGR32AsmOperand : MipsAsmRegOperand { + let Name = "StrictlyFGR32AsmReg"; + let PredicateMethod = "isStrictlyFGRAsmReg"; +} + def FGRH32AsmOperand : MipsAsmRegOperand { let Name = "FGRH32AsmReg"; let PredicateMethod = "isFGRAsmReg"; @@ -639,14 +654,26 @@ def AFGR64Opnd : RegisterOperand { let ParserMatchClass = AFGR64AsmOperand; } +def StrictlyAFGR64Opnd : RegisterOperand { + let ParserMatchClass = StrictlyAFGR64AsmOperand; +} + def FGR64Opnd : RegisterOperand { let ParserMatchClass = FGR64AsmOperand; } +def StrictlyFGR64Opnd : RegisterOperand { + let ParserMatchClass = StrictlyFGR64AsmOperand; +} + def FGR32Opnd : RegisterOperand { let ParserMatchClass = FGR32AsmOperand; } +def StrictlyFGR32Opnd : RegisterOperand { + let ParserMatchClass = StrictlyFGR32AsmOperand; +} + def FGRCCOpnd : RegisterOperand { // The assembler doesn't use register classes so we can re-use // FGR32AsmOperand. diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index b90a5ee28342..216efcc4a1ee 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -539,7 +539,6 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::FSIN, VT, Expand); setOperationAction(ISD::FCOS, VT, Expand); setOperationAction(ISD::FABS, VT, Expand); - setOperationAction(ISD::FPOWI, VT, Expand); setOperationAction(ISD::FFLOOR, VT, Expand); setOperationAction(ISD::FCEIL, VT, Expand); setOperationAction(ISD::FTRUNC, VT, Expand); @@ -798,7 +797,6 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::FABS , MVT::v4f64, Legal); setOperationAction(ISD::FSIN , MVT::v4f64, Expand); setOperationAction(ISD::FCOS , MVT::v4f64, Expand); - setOperationAction(ISD::FPOWI , MVT::v4f64, Expand); setOperationAction(ISD::FPOW , MVT::v4f64, Expand); setOperationAction(ISD::FLOG , MVT::v4f64, Expand); setOperationAction(ISD::FLOG2 , MVT::v4f64, Expand); @@ -844,7 +842,6 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::FABS , MVT::v4f32, Legal); setOperationAction(ISD::FSIN , MVT::v4f32, Expand); setOperationAction(ISD::FCOS , MVT::v4f32, Expand); - setOperationAction(ISD::FPOWI , MVT::v4f32, Expand); setOperationAction(ISD::FPOW , MVT::v4f32, Expand); setOperationAction(ISD::FLOG , MVT::v4f32, Expand); setOperationAction(ISD::FLOG2 , MVT::v4f32, Expand); diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZ.td b/contrib/llvm/lib/Target/SystemZ/SystemZ.td index 6bdfd4d07edc..c5f324418da5 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZ.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZ.td @@ -54,6 +54,8 @@ include "SystemZInstrFormats.td" include "SystemZInstrInfo.td" include "SystemZInstrVector.td" include "SystemZInstrFP.td" +include "SystemZInstrHFP.td" +include "SystemZInstrDFP.td" def SystemZInstrInfo : InstrInfo {} diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZFeatures.td b/contrib/llvm/lib/Target/SystemZ/SystemZFeatures.td index 7bfa378aa85c..ffb0b8d1c861 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZFeatures.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZFeatures.td @@ -115,12 +115,18 @@ def FeatureTransactionalExecution : SystemZFeature< "Assume that the transactional-execution facility is installed" >; +def FeatureDFPZonedConversion : SystemZFeature< + "dfp-zoned-conversion", "DFPZonedConversion", + "Assume that the DFP zoned-conversion facility is installed" +>; + def Arch10NewFeatures : SystemZFeatureList<[ FeatureExecutionHint, FeatureLoadAndTrap, FeatureMiscellaneousExtensions, FeatureProcessorAssist, - FeatureTransactionalExecution + FeatureTransactionalExecution, + FeatureDFPZonedConversion ]>; //===----------------------------------------------------------------------===// @@ -144,6 +150,11 @@ def FeatureMessageSecurityAssist5 : SystemZFeature< "Assume that the message-security-assist extension facility 5 is installed" >; +def FeatureDFPPackedConversion : SystemZFeature< + "dfp-packed-conversion", "DFPPackedConversion", + "Assume that the DFP packed-conversion facility is installed" +>; + def FeatureVector : SystemZFeature< "vector", "Vector", "Assume that the vectory facility is installed" @@ -154,6 +165,7 @@ def Arch11NewFeatures : SystemZFeatureList<[ FeatureLoadAndZeroRightmostByte, FeatureLoadStoreOnCond2, FeatureMessageSecurityAssist5, + FeatureDFPPackedConversion, FeatureVector ]>; diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 235e095f0010..ae141dbcad34 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -4189,12 +4189,20 @@ static SDValue buildVector(SelectionDAG &DAG, const SDLoc &DL, EVT VT, if (Single.getNode() && (Count > 1 || Single.getOpcode() == ISD::LOAD)) return DAG.getNode(SystemZISD::REPLICATE, DL, VT, Single); + // If all elements are loads, use VLREP/VLEs (below). + bool AllLoads = true; + for (auto Elem : Elems) + if (Elem.getOpcode() != ISD::LOAD || cast(Elem)->isIndexed()) { + AllLoads = false; + break; + } + // The best way of building a v2i64 from two i64s is to use VLVGP. - if (VT == MVT::v2i64) + if (VT == MVT::v2i64 && !AllLoads) return joinDwords(DAG, DL, Elems[0], Elems[1]); // Use a 64-bit merge high to combine two doubles. - if (VT == MVT::v2f64) + if (VT == MVT::v2f64 && !AllLoads) return buildMergeScalars(DAG, DL, VT, Elems[0], Elems[1]); // Build v4f32 values directly from the FPRs: @@ -4204,7 +4212,7 @@ static SDValue buildVector(SelectionDAG &DAG, const SDLoc &DL, EVT VT, // // V VMRHG // - if (VT == MVT::v4f32) { + if (VT == MVT::v4f32 && !AllLoads) { SDValue Op01 = buildMergeScalars(DAG, DL, VT, Elems[0], Elems[1]); SDValue Op23 = buildMergeScalars(DAG, DL, VT, Elems[2], Elems[3]); // Avoid unnecessary undefs by reusing the other operand. @@ -4246,23 +4254,37 @@ static SDValue buildVector(SelectionDAG &DAG, const SDLoc &DL, EVT VT, Constants[I] = DAG.getUNDEF(Elems[I].getValueType()); Result = DAG.getBuildVector(VT, DL, Constants); } else { - // Otherwise try to use VLVGP to start the sequence in order to + // Otherwise try to use VLREP or VLVGP to start the sequence in order to // avoid a false dependency on any previous contents of the vector - // register. This only makes sense if one of the associated elements - // is defined. - unsigned I1 = NumElements / 2 - 1; - unsigned I2 = NumElements - 1; - bool Def1 = !Elems[I1].isUndef(); - bool Def2 = !Elems[I2].isUndef(); - if (Def1 || Def2) { - SDValue Elem1 = Elems[Def1 ? I1 : I2]; - SDValue Elem2 = Elems[Def2 ? I2 : I1]; - Result = DAG.getNode(ISD::BITCAST, DL, VT, - joinDwords(DAG, DL, Elem1, Elem2)); - Done[I1] = true; - Done[I2] = true; - } else - Result = DAG.getUNDEF(VT); + // register. + + // Use a VLREP if at least one element is a load. + unsigned LoadElIdx = UINT_MAX; + for (unsigned I = 0; I < NumElements; ++I) + if (Elems[I].getOpcode() == ISD::LOAD && + cast(Elems[I])->isUnindexed()) { + LoadElIdx = I; + break; + } + if (LoadElIdx != UINT_MAX) { + Result = DAG.getNode(SystemZISD::REPLICATE, DL, VT, Elems[LoadElIdx]); + Done[LoadElIdx] = true; + } else { + // Try to use VLVGP. + unsigned I1 = NumElements / 2 - 1; + unsigned I2 = NumElements - 1; + bool Def1 = !Elems[I1].isUndef(); + bool Def2 = !Elems[I2].isUndef(); + if (Def1 || Def2) { + SDValue Elem1 = Elems[Def1 ? I1 : I2]; + SDValue Elem2 = Elems[Def2 ? I2 : I1]; + Result = DAG.getNode(ISD::BITCAST, DL, VT, + joinDwords(DAG, DL, Elem1, Elem2)); + Done[I1] = true; + Done[I2] = true; + } else + Result = DAG.getUNDEF(VT); + } } // Use VLVGx to insert the other elements. diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrDFP.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrDFP.td new file mode 100644 index 000000000000..08ab2d7bbc52 --- /dev/null +++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrDFP.td @@ -0,0 +1,231 @@ +//==- SystemZInstrDFP.td - Floating-point SystemZ instructions -*- tblgen-*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The instructions in this file implement SystemZ decimal floating-point +// arithmetic. These instructions are inot currently used for code generation, +// are provided for use with the assembler and disassembler only. If LLVM +// ever supports decimal floating-point types (_Decimal64 etc.), they can +// also be used for code generation for those types. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Move instructions +//===----------------------------------------------------------------------===// + +// Load and test. +let Defs = [CC] in { + def LTDTR : UnaryRRE<"ltdtr", 0xB3D6, null_frag, FP64, FP64>; + def LTXTR : UnaryRRE<"ltxtr", 0xB3DE, null_frag, FP128, FP128>; +} + + +//===----------------------------------------------------------------------===// +// Conversion instructions +//===----------------------------------------------------------------------===// + +// Convert floating-point values to narrower representations. The destination +// of LDXTR is a 128-bit value, but only the first register of the pair is used. +def LEDTR : TernaryRRFe<"ledtr", 0xB3D5, FP32, FP64>; +def LDXTR : TernaryRRFe<"ldxtr", 0xB3DD, FP128, FP128>; + +// Extend floating-point values to wider representations. +def LDETR : BinaryRRFd<"ldetr", 0xB3D4, FP64, FP32>; +def LXDTR : BinaryRRFd<"lxdtr", 0xB3DC, FP128, FP64>; + +// Convert a signed integer value to a floating-point one. +def CDGTR : UnaryRRE<"cdgtr", 0xB3F1, null_frag, FP64, GR64>; +def CXGTR : UnaryRRE<"cxgtr", 0xB3F9, null_frag, FP128, GR64>; +let Predicates = [FeatureFPExtension] in { + def CDGTRA : TernaryRRFe<"cdgtra", 0xB3F1, FP64, GR64>; + def CXGTRA : TernaryRRFe<"cxgtra", 0xB3F9, FP128, GR64>; + def CDFTR : TernaryRRFe<"cdftr", 0xB951, FP64, GR32>; + def CXFTR : TernaryRRFe<"cxftr", 0xB959, FP128, GR32>; +} + +// Convert an unsigned integer value to a floating-point one. +let Predicates = [FeatureFPExtension] in { + def CDLGTR : TernaryRRFe<"cdlgtr", 0xB952, FP64, GR64>; + def CXLGTR : TernaryRRFe<"cxlgtr", 0xB95A, FP128, GR64>; + def CDLFTR : TernaryRRFe<"cdlftr", 0xB953, FP64, GR32>; + def CXLFTR : TernaryRRFe<"cxlftr", 0xB95B, FP128, GR32>; +} + +// Convert a floating-point value to a signed integer value. +let Defs = [CC] in { + def CGDTR : BinaryRRFe<"cgdtr", 0xB3E1, GR64, FP64>; + def CGXTR : BinaryRRFe<"cgxtr", 0xB3E9, GR64, FP128>; + let Predicates = [FeatureFPExtension] in { + def CGDTRA : TernaryRRFe<"cgdtra", 0xB3E1, GR64, FP64>; + def CGXTRA : TernaryRRFe<"cgxtra", 0xB3E9, GR64, FP128>; + def CFDTR : TernaryRRFe<"cfdtr", 0xB941, GR32, FP64>; + def CFXTR : TernaryRRFe<"cfxtr", 0xB949, GR32, FP128>; + } +} + +// Convert a floating-point value to an unsigned integer value. +let Defs = [CC] in { + let Predicates = [FeatureFPExtension] in { + def CLGDTR : TernaryRRFe<"clgdtr", 0xB942, GR64, FP64>; + def CLGXTR : TernaryRRFe<"clgxtr", 0xB94A, GR64, FP128>; + def CLFDTR : TernaryRRFe<"clfdtr", 0xB943, GR32, FP64>; + def CLFXTR : TernaryRRFe<"clfxtr", 0xB94B, GR32, FP128>; + } +} + +// Convert a packed value to a floating-point one. +def CDSTR : UnaryRRE<"cdstr", 0xB3F3, null_frag, FP64, GR64>; +def CXSTR : UnaryRRE<"cxstr", 0xB3FB, null_frag, FP128, GR128>; +def CDUTR : UnaryRRE<"cdutr", 0xB3F2, null_frag, FP64, GR64>; +def CXUTR : UnaryRRE<"cxutr", 0xB3FA, null_frag, FP128, GR128>; + +// Convert a floating-point value to a packed value. +def CSDTR : BinaryRRFd<"csdtr", 0xB3E3, GR64, FP64>; +def CSXTR : BinaryRRFd<"csxtr", 0xB3EB, GR128, FP128>; +def CUDTR : UnaryRRE<"cudtr", 0xB3E2, null_frag, GR64, FP64>; +def CUXTR : UnaryRRE<"cuxtr", 0xB3EA, null_frag, GR128, FP128>; + +// Convert from/to memory values in the zoned format. +let Predicates = [FeatureDFPZonedConversion] in { + def CDZT : BinaryRSL<"cdzt", 0xEDAA, FP64>; + def CXZT : BinaryRSL<"cxzt", 0xEDAB, FP128>; + def CZDT : StoreBinaryRSL<"czdt", 0xEDA8, FP64>; + def CZXT : StoreBinaryRSL<"czxt", 0xEDA9, FP128>; +} + +// Convert from/to memory values in the packed format. +let Predicates = [FeatureDFPPackedConversion] in { + def CDPT : BinaryRSL<"cdpt", 0xEDAE, FP64>; + def CXPT : BinaryRSL<"cxpt", 0xEDAF, FP128>; + def CPDT : StoreBinaryRSL<"cpdt", 0xEDAC, FP64>; + def CPXT : StoreBinaryRSL<"cpxt", 0xEDAD, FP128>; +} + +// Perform floating-point operation. +let Defs = [CC, R1L, F0Q], Uses = [R0L, F4Q] in + def PFPO : SideEffectInherentE<"pfpo", 0x010A>; + + +//===----------------------------------------------------------------------===// +// Unary arithmetic +//===----------------------------------------------------------------------===// + +// Round to an integer, with the second operand (M3) specifying the rounding +// mode. M4 can be set to 4 to suppress detection of inexact conditions. +def FIDTR : TernaryRRFe<"fidtr", 0xB3D7, FP64, FP64>; +def FIXTR : TernaryRRFe<"fixtr", 0xB3DF, FP128, FP128>; + +// Extract biased exponent. +def EEDTR : UnaryRRE<"eedtr", 0xB3E5, null_frag, FP64, FP64>; +def EEXTR : UnaryRRE<"eextr", 0xB3ED, null_frag, FP128, FP128>; + +// Extract significance. +def ESDTR : UnaryRRE<"esdtr", 0xB3E7, null_frag, FP64, FP64>; +def ESXTR : UnaryRRE<"esxtr", 0xB3EF, null_frag, FP128, FP128>; + + +//===----------------------------------------------------------------------===// +// Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition. +let Defs = [CC] in { + let isCommutable = 1 in { + def ADTR : BinaryRRFa<"adtr", 0xB3D2, null_frag, FP64, FP64, FP64>; + def AXTR : BinaryRRFa<"axtr", 0xB3DA, null_frag, FP128, FP128, FP128>; + } + let Predicates = [FeatureFPExtension] in { + def ADTRA : TernaryRRFa<"adtra", 0xB3D2, FP64, FP64, FP64>; + def AXTRA : TernaryRRFa<"axtra", 0xB3DA, FP128, FP128, FP128>; + } +} + +// Subtraction. +let Defs = [CC] in { + def SDTR : BinaryRRFa<"sdtr", 0xB3D3, null_frag, FP64, FP64, FP64>; + def SXTR : BinaryRRFa<"sxtr", 0xB3DB, null_frag, FP128, FP128, FP128>; + let Predicates = [FeatureFPExtension] in { + def SDTRA : TernaryRRFa<"sdtra", 0xB3D3, FP64, FP64, FP64>; + def SXTRA : TernaryRRFa<"sxtra", 0xB3DB, FP128, FP128, FP128>; + } +} + +// Multiplication. +let isCommutable = 1 in { + def MDTR : BinaryRRFa<"mdtr", 0xB3D0, null_frag, FP64, FP64, FP64>; + def MXTR : BinaryRRFa<"mxtr", 0xB3D8, null_frag, FP128, FP128, FP128>; +} +let Predicates = [FeatureFPExtension] in { + def MDTRA : TernaryRRFa<"mdtra", 0xB3D0, FP64, FP64, FP64>; + def MXTRA : TernaryRRFa<"mxtra", 0xB3D8, FP128, FP128, FP128>; +} + +// Division. +def DDTR : BinaryRRFa<"ddtr", 0xB3D1, null_frag, FP64, FP64, FP64>; +def DXTR : BinaryRRFa<"dxtr", 0xB3D9, null_frag, FP128, FP128, FP128>; +let Predicates = [FeatureFPExtension] in { + def DDTRA : TernaryRRFa<"ddtra", 0xB3D1, FP64, FP64, FP64>; + def DXTRA : TernaryRRFa<"dxtra", 0xB3D9, FP128, FP128, FP128>; +} + +// Quantize. +def QADTR : TernaryRRFb<"qadtr", 0xB3F5, FP64, FP64, FP64>; +def QAXTR : TernaryRRFb<"qaxtr", 0xB3FD, FP128, FP128, FP128>; + +// Reround. +def RRDTR : TernaryRRFb<"rrdtr", 0xB3F7, FP64, FP64, FP64>; +def RRXTR : TernaryRRFb<"rrxtr", 0xB3FF, FP128, FP128, FP128>; + +// Shift significand left/right. +def SLDT : BinaryRXF<"sldt", 0xED40, null_frag, FP64, FP64, null_frag, 0>; +def SLXT : BinaryRXF<"slxt", 0xED48, null_frag, FP128, FP128, null_frag, 0>; +def SRDT : BinaryRXF<"srdt", 0xED41, null_frag, FP64, FP64, null_frag, 0>; +def SRXT : BinaryRXF<"srxt", 0xED49, null_frag, FP128, FP128, null_frag, 0>; + +// Insert biased exponent. +def IEDTR : BinaryRRFb<"iedtr", 0xB3F6, null_frag, FP64, FP64, FP64>; +def IEXTR : BinaryRRFb<"iextr", 0xB3FE, null_frag, FP128, FP128, FP128>; + + +//===----------------------------------------------------------------------===// +// Comparisons +//===----------------------------------------------------------------------===// + +// Compare. +let Defs = [CC] in { + def CDTR : CompareRRE<"cdtr", 0xB3E4, null_frag, FP64, FP64>; + def CXTR : CompareRRE<"cxtr", 0xB3EC, null_frag, FP128, FP128>; +} + +// Compare and signal. +let Defs = [CC] in { + def KDTR : CompareRRE<"kdtr", 0xB3E0, null_frag, FP64, FP64>; + def KXTR : CompareRRE<"kxtr", 0xB3E8, null_frag, FP128, FP128>; +} + +// Compare biased exponent. +let Defs = [CC] in { + def CEDTR : CompareRRE<"cedtr", 0xB3F4, null_frag, FP64, FP64>; + def CEXTR : CompareRRE<"cextr", 0xB3FC, null_frag, FP128, FP128>; +} + +// Test Data Class. +let Defs = [CC] in { + def TDCET : TestRXE<"tdcet", 0xED50, null_frag, FP32>; + def TDCDT : TestRXE<"tdcdt", 0xED54, null_frag, FP64>; + def TDCXT : TestRXE<"tdcxt", 0xED58, null_frag, FP128>; +} + +// Test Data Group. +let Defs = [CC] in { + def TDGET : TestRXE<"tdget", 0xED51, null_frag, FP32>; + def TDGDT : TestRXE<"tdgdt", 0xED55, null_frag, FP64>; + def TDGXT : TestRXE<"tdgxt", 0xED59, null_frag, FP128>; +} + diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td index 364b81f98eed..10172bd45203 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td @@ -121,7 +121,8 @@ let canFoldAsLoad = 1, SimpleBDXLoad = 1 in { defm LD : UnaryRXPair<"ld", 0x68, 0xED65, load, FP64, 8>; // For z13 we prefer LDE over LE to avoid partial register dependencies. - def LDE32 : UnaryRXE<"lde", 0xED24, null_frag, FP32, 4>; + let isCodeGenOnly = 1 in + def LDE32 : UnaryRXE<"lde", 0xED24, null_frag, FP32, 4>; // These instructions are split after register allocation, so we don't // want a custom inserter. @@ -437,18 +438,18 @@ def : Pat<(fmul (f128 (fpextend FP64:$src1)), bdxaddr12only:$addr)>; // Fused multiply-add. -def MAEBR : TernaryRRD<"maebr", 0xB30E, z_fma, FP32>; -def MADBR : TernaryRRD<"madbr", 0xB31E, z_fma, FP64>; +def MAEBR : TernaryRRD<"maebr", 0xB30E, z_fma, FP32, FP32>; +def MADBR : TernaryRRD<"madbr", 0xB31E, z_fma, FP64, FP64>; -def MAEB : TernaryRXF<"maeb", 0xED0E, z_fma, FP32, load, 4>; -def MADB : TernaryRXF<"madb", 0xED1E, z_fma, FP64, load, 8>; +def MAEB : TernaryRXF<"maeb", 0xED0E, z_fma, FP32, FP32, load, 4>; +def MADB : TernaryRXF<"madb", 0xED1E, z_fma, FP64, FP64, load, 8>; // Fused multiply-subtract. -def MSEBR : TernaryRRD<"msebr", 0xB30F, z_fms, FP32>; -def MSDBR : TernaryRRD<"msdbr", 0xB31F, z_fms, FP64>; +def MSEBR : TernaryRRD<"msebr", 0xB30F, z_fms, FP32, FP32>; +def MSDBR : TernaryRRD<"msdbr", 0xB31F, z_fms, FP64, FP64>; -def MSEB : TernaryRXF<"mseb", 0xED0F, z_fms, FP32, load, 4>; -def MSDB : TernaryRXF<"msdb", 0xED1F, z_fms, FP64, load, 8>; +def MSEB : TernaryRXF<"mseb", 0xED0F, z_fms, FP32, FP32, load, 4>; +def MSDB : TernaryRXF<"msdb", 0xED1F, z_fms, FP64, FP64, load, 8>; // Division. def DEBR : BinaryRRE<"debr", 0xB30D, fdiv, FP32, FP32>; diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td index a37da2807854..5f6115ed86a4 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td @@ -527,6 +527,22 @@ class InstRRFc op, dag outs, dag ins, string asmstr, list pattern> let Inst{3-0} = R2; } +class InstRRFd op, dag outs, dag ins, string asmstr, list pattern> + : InstSystemZ<4, outs, ins, asmstr, pattern> { + field bits<32> Inst; + field bits<32> SoftFail = 0; + + bits<4> R1; + bits<4> R2; + bits<4> M4; + + let Inst{31-16} = op; + let Inst{15-12} = 0; + let Inst{11-8} = M4; + let Inst{7-4} = R1; + let Inst{3-0} = R2; +} + class InstRRFe op, dag outs, dag ins, string asmstr, list pattern> : InstSystemZ<4, outs, ins, asmstr, pattern> { field bits<32> Inst; @@ -725,6 +741,22 @@ class InstRSLa op, dag outs, dag ins, string asmstr, list pattern> let Inst{7-0} = op{7-0}; } +class InstRSLb op, dag outs, dag ins, string asmstr, list pattern> + : InstSystemZ<6, outs, ins, asmstr, pattern> { + field bits<48> Inst; + field bits<48> SoftFail = 0; + + bits<4> R1; + bits<24> BDL2; + bits<4> M3; + + let Inst{47-40} = op{15-8}; + let Inst{39-16} = BDL2; + let Inst{15-12} = R1; + let Inst{11-8} = M3; + let Inst{7-0} = op{7-0}; +} + class InstRSYa op, dag outs, dag ins, string asmstr, list pattern> : InstSystemZ<6, outs, ins, asmstr, pattern> { field bits<48> Inst; @@ -2752,6 +2784,15 @@ class BinaryRRE opcode, SDPatternOperator operator, let DisableEncoding = "$R1src"; } +class BinaryRRD opcode, SDPatternOperator operator, + RegisterOperand cls1, RegisterOperand cls2> + : InstRRD { + let OpKey = mnemonic#cls; + let OpType = "reg"; +} + class BinaryRRFa opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2, RegisterOperand cls3> @@ -2808,6 +2849,11 @@ multiclass BinaryMemRRFcOpt opcode, def Opt : UnaryMemRRFc; } +class BinaryRRFd opcode, RegisterOperand cls1, + RegisterOperand cls2> + : InstRRFd; + class BinaryRRFe opcode, RegisterOperand cls1, RegisterOperand cls2> : InstRRFe opcode1, bits<16> opcode2, } } +class BinaryRSL opcode, RegisterOperand cls> + : InstRSLb { + let mayLoad = 1; +} + class BinaryRX opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load, bits<5> bytes, AddressingMode mode = bdxaddr12only> @@ -2987,6 +3040,18 @@ class BinaryRXE opcode, SDPatternOperator operator, let M3 = 0; } +class BinaryRXF opcode, SDPatternOperator operator, + RegisterOperand cls1, RegisterOperand cls2, + SDPatternOperator load, bits<5> bytes> + : InstRXF { + let OpKey = mnemonic#"r"#cls; + let OpType = "mem"; + let mayLoad = 1; + let AccessBytes = bytes; +} + class BinaryRXY opcode, SDPatternOperator operator, RegisterOperand cls, SDPatternOperator load, bits<5> bytes, AddressingMode mode = bdxaddr20only> @@ -3294,6 +3359,13 @@ multiclass StoreBinaryRSPair rsOpcode, } } +class StoreBinaryRSL opcode, RegisterOperand cls> + : InstRSLb { + let mayStore = 1; +} + class StoreBinaryVRV opcode, bits<5> bytes, Immediate index> : InstVRV opcode, (ins bdaddr12only:$BD1, bdaddr12only:$BD2, cls:$R3), mnemonic#"\t$BD1, $BD2, $R3", []>; +class TernaryRRFa opcode, + RegisterOperand cls1, RegisterOperand cls2, + RegisterOperand cls3> + : InstRRFa; + class TernaryRRFb opcode, RegisterOperand cls1, RegisterOperand cls2, RegisterOperand cls3> @@ -3597,11 +3675,11 @@ class TernaryRRFe opcode, RegisterOperand cls1, (ins imm32zx4:$M3, cls2:$R2, imm32zx4:$M4), mnemonic#"\t$R1, $M3, $R2, $M4", []>; -class TernaryRRD opcode, - SDPatternOperator operator, RegisterOperand cls> - : InstRRD opcode, SDPatternOperator operator, + RegisterOperand cls1, RegisterOperand cls2> + : InstRRD { + [(set cls1:$R1, (operator cls2:$R1src, cls2:$R3, cls2:$R2))]> { let OpKey = mnemonic#cls; let OpType = "reg"; let Constraints = "$R1 = $R1src"; @@ -3661,12 +3739,13 @@ class SideEffectTernaryMemMemRSY opcode, } class TernaryRXF opcode, SDPatternOperator operator, - RegisterOperand cls, SDPatternOperator load, bits<5> bytes> - : InstRXF bytes> + : InstRXF { + [(set cls1:$R1, (operator cls2:$R1src, cls2:$R3, + (load bdxaddr12only:$XBD2)))]> { let OpKey = mnemonic#"r"#cls; let OpType = "mem"; let Constraints = "$R1 = $R1src"; diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZInstrHFP.td b/contrib/llvm/lib/Target/SystemZ/SystemZInstrHFP.td new file mode 100644 index 000000000000..6d5b4b92f650 --- /dev/null +++ b/contrib/llvm/lib/Target/SystemZ/SystemZInstrHFP.td @@ -0,0 +1,240 @@ +//==- SystemZInstrHFP.td - Floating-point SystemZ instructions -*- tblgen-*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The instructions in this file implement SystemZ hexadecimal floating-point +// arithmetic. Since this format is not mapped to any source-language data +// type, these instructions are not used for code generation, but are provided +// for use with the assembler and disassembler only. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Move instructions +//===----------------------------------------------------------------------===// + +// Load and test. +let Defs = [CC] in { + def LTER : UnaryRR <"lter", 0x32, null_frag, FP32, FP32>; + def LTDR : UnaryRR <"ltdr", 0x22, null_frag, FP64, FP64>; + def LTXR : UnaryRRE<"ltxr", 0xB362, null_frag, FP128, FP128>; +} + +//===----------------------------------------------------------------------===// +// Conversion instructions +//===----------------------------------------------------------------------===// + +// Convert floating-point values to narrower representations. +def LEDR : UnaryRR <"ledr", 0x35, null_frag, FP32, FP64>; +def LEXR : UnaryRRE<"lexr", 0xB366, null_frag, FP32, FP128>; +def LDXR : UnaryRR <"ldxr", 0x25, null_frag, FP64, FP128>; +let isAsmParserOnly = 1 in { + def LRER : UnaryRR <"lrer", 0x35, null_frag, FP32, FP64>; + def LRDR : UnaryRR <"lrdr", 0x25, null_frag, FP64, FP128>; +} + +// Extend floating-point values to wider representations. +def LDER : UnaryRRE<"lder", 0xB324, null_frag, FP64, FP32>; +def LXER : UnaryRRE<"lxer", 0xB326, null_frag, FP128, FP32>; +def LXDR : UnaryRRE<"lxdr", 0xB325, null_frag, FP128, FP64>; + +def LDE : UnaryRXE<"lde", 0xED24, null_frag, FP64, 4>; +def LXE : UnaryRXE<"lxe", 0xED26, null_frag, FP128, 4>; +def LXD : UnaryRXE<"lxd", 0xED25, null_frag, FP128, 8>; + +// Convert a signed integer register value to a floating-point one. +def CEFR : UnaryRRE<"cefr", 0xB3B4, null_frag, FP32, GR32>; +def CDFR : UnaryRRE<"cdfr", 0xB3B5, null_frag, FP64, GR32>; +def CXFR : UnaryRRE<"cxfr", 0xB3B6, null_frag, FP128, GR32>; + +def CEGR : UnaryRRE<"cegr", 0xB3C4, null_frag, FP32, GR64>; +def CDGR : UnaryRRE<"cdgr", 0xB3C5, null_frag, FP64, GR64>; +def CXGR : UnaryRRE<"cxgr", 0xB3C6, null_frag, FP128, GR64>; + +// Convert a floating-point register value to a signed integer value, +// with the second operand (modifier M3) specifying the rounding mode. +let Defs = [CC] in { + def CFER : BinaryRRFe<"cfer", 0xB3B8, GR32, FP32>; + def CFDR : BinaryRRFe<"cfdr", 0xB3B9, GR32, FP64>; + def CFXR : BinaryRRFe<"cfxr", 0xB3BA, GR32, FP128>; + + def CGER : BinaryRRFe<"cger", 0xB3C8, GR64, FP32>; + def CGDR : BinaryRRFe<"cgdr", 0xB3C9, GR64, FP64>; + def CGXR : BinaryRRFe<"cgxr", 0xB3CA, GR64, FP128>; +} + +// Convert BFP to HFP. +let Defs = [CC] in { + def THDER : UnaryRRE<"thder", 0xB358, null_frag, FP64, FP32>; + def THDR : UnaryRRE<"thdr", 0xB359, null_frag, FP64, FP64>; +} + +// Convert HFP to BFP. +let Defs = [CC] in { + def TBEDR : BinaryRRFe<"tbedr", 0xB350, FP32, FP64>; + def TBDR : BinaryRRFe<"tbdr", 0xB351, FP64, FP64>; +} + + +//===----------------------------------------------------------------------===// +// Unary arithmetic +//===----------------------------------------------------------------------===// + +// Negation (Load Complement). +let Defs = [CC] in { + def LCER : UnaryRR <"lcer", 0x33, null_frag, FP32, FP32>; + def LCDR : UnaryRR <"lcdr", 0x23, null_frag, FP64, FP64>; + def LCXR : UnaryRRE<"lcxr", 0xB363, null_frag, FP128, FP128>; +} + +// Absolute value (Load Positive). +let Defs = [CC] in { + def LPER : UnaryRR <"lper", 0x30, null_frag, FP32, FP32>; + def LPDR : UnaryRR <"lpdr", 0x20, null_frag, FP64, FP64>; + def LPXR : UnaryRRE<"lpxr", 0xB360, null_frag, FP128, FP128>; +} + +// Negative absolute value (Load Negative). +let Defs = [CC] in { + def LNER : UnaryRR <"lner", 0x31, null_frag, FP32, FP32>; + def LNDR : UnaryRR <"lndr", 0x21, null_frag, FP64, FP64>; + def LNXR : UnaryRRE<"lnxr", 0xB361, null_frag, FP128, FP128>; +} + +// Halve. +def HER : UnaryRR <"her", 0x34, null_frag, FP32, FP32>; +def HDR : UnaryRR <"hdr", 0x24, null_frag, FP64, FP64>; + +// Square root. +def SQER : UnaryRRE<"sqer", 0xB245, null_frag, FP32, FP32>; +def SQDR : UnaryRRE<"sqdr", 0xB244, null_frag, FP64, FP64>; +def SQXR : UnaryRRE<"sqxr", 0xB336, null_frag, FP128, FP128>; + +def SQE : UnaryRXE<"sqe", 0xED34, null_frag, FP32, 4>; +def SQD : UnaryRXE<"sqd", 0xED35, null_frag, FP64, 8>; + +// Round to an integer (rounding towards zero). +def FIER : UnaryRRE<"fier", 0xB377, null_frag, FP32, FP32>; +def FIDR : UnaryRRE<"fidr", 0xB37F, null_frag, FP64, FP64>; +def FIXR : UnaryRRE<"fixr", 0xB367, null_frag, FP128, FP128>; + + +//===----------------------------------------------------------------------===// +// Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition. +let Defs = [CC] in { + let isCommutable = 1 in { + def AER : BinaryRR<"aer", 0x3A, null_frag, FP32, FP32>; + def ADR : BinaryRR<"adr", 0x2A, null_frag, FP64, FP64>; + def AXR : BinaryRR<"axr", 0x36, null_frag, FP128, FP128>; + } + def AE : BinaryRX<"ae", 0x7A, null_frag, FP32, load, 4>; + def AD : BinaryRX<"ad", 0x6A, null_frag, FP64, load, 8>; +} + +// Addition (unnormalized). +let Defs = [CC] in { + let isCommutable = 1 in { + def AUR : BinaryRR<"aur", 0x3E, null_frag, FP32, FP32>; + def AWR : BinaryRR<"awr", 0x2E, null_frag, FP64, FP64>; + } + def AU : BinaryRX<"au", 0x7E, null_frag, FP32, load, 4>; + def AW : BinaryRX<"aw", 0x6E, null_frag, FP64, load, 8>; +} + +// Subtraction. +let Defs = [CC] in { + def SER : BinaryRR<"ser", 0x3B, null_frag, FP32, FP32>; + def SDR : BinaryRR<"sdr", 0x2B, null_frag, FP64, FP64>; + def SXR : BinaryRR<"sxr", 0x37, null_frag, FP128, FP128>; + + def SE : BinaryRX<"se", 0x7B, null_frag, FP32, load, 4>; + def SD : BinaryRX<"sd", 0x6B, null_frag, FP64, load, 8>; +} + +// Subtraction (unnormalized). +let Defs = [CC] in { + def SUR : BinaryRR<"sur", 0x3F, null_frag, FP32, FP32>; + def SWR : BinaryRR<"swr", 0x2F, null_frag, FP64, FP64>; + + def SU : BinaryRX<"su", 0x7F, null_frag, FP32, load, 4>; + def SW : BinaryRX<"sw", 0x6F, null_frag, FP64, load, 8>; +} + +// Multiplication. +let isCommutable = 1 in { + def MEER : BinaryRRE<"meer", 0xB337, null_frag, FP32, FP32>; + def MDR : BinaryRR <"mdr", 0x2C, null_frag, FP64, FP64>; + def MXR : BinaryRR <"mxr", 0x26, null_frag, FP128, FP128>; +} +def MEE : BinaryRXE<"mee", 0xED37, null_frag, FP32, load, 4>; +def MD : BinaryRX <"md", 0x6C, null_frag, FP64, load, 8>; + +// Extending multiplication (f32 x f32 -> f64). +def MDER : BinaryRR<"mder", 0x3C, null_frag, FP64, FP32>; +def MDE : BinaryRX<"mde", 0x7C, null_frag, FP64, load, 4>; +let isAsmParserOnly = 1 in { + def MER : BinaryRR<"mer", 0x3C, null_frag, FP64, FP32>; + def ME : BinaryRX<"me", 0x7C, null_frag, FP64, load, 4>; +} + +// Extending multiplication (f64 x f64 -> f128). +def MXDR : BinaryRR<"mxdr", 0x27, null_frag, FP128, FP64>; +def MXD : BinaryRX<"mxd", 0x67, null_frag, FP128, load, 8>; + +// Fused multiply-add. +def MAER : TernaryRRD<"maer", 0xB32E, null_frag, FP32, FP32>; +def MADR : TernaryRRD<"madr", 0xB33E, null_frag, FP64, FP64>; +def MAE : TernaryRXF<"mae", 0xED2E, null_frag, FP32, FP32, load, 4>; +def MAD : TernaryRXF<"mad", 0xED3E, null_frag, FP64, FP64, load, 8>; + +// Fused multiply-subtract. +def MSER : TernaryRRD<"mser", 0xB32F, null_frag, FP32, FP32>; +def MSDR : TernaryRRD<"msdr", 0xB33F, null_frag, FP64, FP64>; +def MSE : TernaryRXF<"mse", 0xED2F, null_frag, FP32, FP32, load, 4>; +def MSD : TernaryRXF<"msd", 0xED3F, null_frag, FP64, FP64, load, 8>; + +// Multiplication (unnormalized). +def MYR : BinaryRRD<"myr", 0xB33B, null_frag, FP128, FP64>; +def MYHR : BinaryRRD<"myhr", 0xB33D, null_frag, FP64, FP64>; +def MYLR : BinaryRRD<"mylr", 0xB339, null_frag, FP64, FP64>; +def MY : BinaryRXF<"my", 0xED3B, null_frag, FP128, FP64, load, 8>; +def MYH : BinaryRXF<"myh", 0xED3D, null_frag, FP64, FP64, load, 8>; +def MYL : BinaryRXF<"myl", 0xED39, null_frag, FP64, FP64, load, 8>; + +// Fused multiply-add (unnormalized). +def MAYR : TernaryRRD<"mayr", 0xB33A, null_frag, FP128, FP64>; +def MAYHR : TernaryRRD<"mayhr", 0xB33C, null_frag, FP64, FP64>; +def MAYLR : TernaryRRD<"maylr", 0xB338, null_frag, FP64, FP64>; +def MAY : TernaryRXF<"may", 0xED3A, null_frag, FP128, FP64, load, 8>; +def MAYH : TernaryRXF<"mayh", 0xED3C, null_frag, FP64, FP64, load, 8>; +def MAYL : TernaryRXF<"mayl", 0xED38, null_frag, FP64, FP64, load, 8>; + +// Division. +def DER : BinaryRR <"der", 0x3D, null_frag, FP32, FP32>; +def DDR : BinaryRR <"ddr", 0x2D, null_frag, FP64, FP64>; +def DXR : BinaryRRE<"dxr", 0xB22D, null_frag, FP128, FP128>; +def DE : BinaryRX <"de", 0x7D, null_frag, FP32, load, 4>; +def DD : BinaryRX <"dd", 0x6D, null_frag, FP64, load, 8>; + + +//===----------------------------------------------------------------------===// +// Comparisons +//===----------------------------------------------------------------------===// + +let Defs = [CC] in { + def CER : CompareRR <"cer", 0x39, null_frag, FP32, FP32>; + def CDR : CompareRR <"cdr", 0x29, null_frag, FP64, FP64>; + def CXR : CompareRRE<"cxr", 0xB369, null_frag, FP128, FP128>; + + def CE : CompareRX<"ce", 0x79, null_frag, FP32, load, 4>; + def CD : CompareRX<"cd", 0x69, null_frag, FP64, load, 8>; +} + diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td b/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td index 612c3b6cf96e..5f5f2f690e58 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td @@ -908,6 +908,238 @@ def : InstRW<[FXa, Lat30, GroupAlone], (instregex "SFASR$")>; def : InstRW<[FXa, LSU, Lat30, GroupAlone], (instregex "LFAS$")>; def : InstRW<[FXb, Lat3, GroupAlone], (instregex "SRNM(B|T)?$")>; + +// --------------------- Hexadecimal floating point ------------------------- // + +//===----------------------------------------------------------------------===// +// HFP: Move instructions +//===----------------------------------------------------------------------===// + +// Load and Test +def : InstRW<[VecXsPm, Lat4], (instregex "LT(D|E)R$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "LTXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Conversion instructions +//===----------------------------------------------------------------------===// + +// Load rounded +def : InstRW<[VecBF], (instregex "(LEDR|LRER)$")>; +def : InstRW<[VecBF], (instregex "LEXR$")>; +def : InstRW<[VecDF2, VecDF2], (instregex "(LDXR|LRDR)$")>; + +// Load lengthened +def : InstRW<[LSU], (instregex "LDE$")>; +def : InstRW<[FXb], (instregex "LDER$")>; +def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "LX(D|E)$")>; +def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "LX(D|E)R$")>; + +// Convert from fixed +def : InstRW<[FXb, VecBF, Lat9, BeginGroup], (instregex "CE(F|G)R$")>; +def : InstRW<[FXb, VecBF, Lat9, BeginGroup], (instregex "CD(F|G)R$")>; +def : InstRW<[FXb, VecDF2, VecDF2, Lat12, GroupAlone], (instregex "CX(F|G)R$")>; + +// Convert to fixed +def : InstRW<[FXb, VecBF, Lat11, BeginGroup], (instregex "CF(E|D)R$")>; +def : InstRW<[FXb, VecBF, Lat11, BeginGroup], (instregex "CG(E|D)R$")>; +def : InstRW<[FXb, VecDF, VecDF, Lat20, BeginGroup], (instregex "C(F|G)XR$")>; + +// Convert BFP to HFP / HFP to BFP. +def : InstRW<[VecBF], (instregex "THD(E)?R$")>; +def : InstRW<[VecBF], (instregex "TB(E)?DR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Unary arithmetic +//===----------------------------------------------------------------------===// + +// Load Complement / Negative / Positive +def : InstRW<[VecXsPm, Lat4], (instregex "L(C|N|P)DR$")>; +def : InstRW<[VecXsPm, Lat4], (instregex "L(C|N|P)ER$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "L(C|N|P)XR$")>; + +// Halve +def : InstRW<[VecBF], (instregex "H(E|D)R$")>; + +// Square root +def : InstRW<[VecFPd, LSU], (instregex "SQ(E|D)$")>; +def : InstRW<[VecFPd], (instregex "SQ(E|D)R$")>; +def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "SQXR$")>; + +// Load FP integer +def : InstRW<[VecBF], (instregex "FIER$")>; +def : InstRW<[VecBF], (instregex "FIDR$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "FIXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition +def : InstRW<[VecBF, LSU, Lat12], (instregex "A(E|D|U|W)$")>; +def : InstRW<[VecBF], (instregex "A(E|D|U|W)R$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "AXR$")>; + +// Subtraction +def : InstRW<[VecBF, LSU, Lat12], (instregex "S(E|D|U|W)$")>; +def : InstRW<[VecBF], (instregex "S(E|D|U|W)R$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "SXR$")>; + +// Multiply +def : InstRW<[VecBF, LSU, Lat12], (instregex "M(D|DE|E|EE)$")>; +def : InstRW<[VecBF], (instregex "M(D|DE|E|EE)R$")>; +def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MXD$")>; +def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MXDR$")>; +def : InstRW<[VecDF2, VecDF2, Lat20, GroupAlone], (instregex "MXR$")>; +def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MY(H|L)?$")>; +def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MY(H|L)?R$")>; + +// Multiply and add / subtract +def : InstRW<[VecBF, LSU, Lat12, GroupAlone], (instregex "M(A|S)E$")>; +def : InstRW<[VecBF, GroupAlone], (instregex "M(A|S)ER$")>; +def : InstRW<[VecBF, LSU, Lat12, GroupAlone], (instregex "M(A|S)D$")>; +def : InstRW<[VecBF], (instregex "M(A|S)DR$")>; +def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MAY(H|L)?$")>; +def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MAY(H|L)?R$")>; + +// Division +def : InstRW<[VecFPd, LSU], (instregex "D(E|D)$")>; +def : InstRW<[VecFPd], (instregex "D(E|D)R$")>; +def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "DXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Comparisons +//===----------------------------------------------------------------------===// + +// Compare +def : InstRW<[VecXsPm, LSU, Lat8], (instregex "C(E|D)$")>; +def : InstRW<[VecXsPm, Lat4], (instregex "C(E|D)R$")>; +def : InstRW<[VecDF, VecDF, Lat20, GroupAlone], (instregex "CXR$")>; + + +// ------------------------ Decimal floating point -------------------------- // + +//===----------------------------------------------------------------------===// +// DFP: Move instructions +//===----------------------------------------------------------------------===// + +// Load and Test +def : InstRW<[VecDF], (instregex "LTDTR$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "LTXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Conversion instructions +//===----------------------------------------------------------------------===// + +// Load rounded +def : InstRW<[VecDF, Lat15], (instregex "LEDTR$")>; +def : InstRW<[VecDF, VecDF, Lat20], (instregex "LDXTR$")>; + +// Load lengthened +def : InstRW<[VecDF], (instregex "LDETR$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "LXDTR$")>; + +// Convert from fixed / logical +def : InstRW<[FXb, VecDF, Lat30, BeginGroup], (instregex "CD(F|G)TR(A)?$")>; +def : InstRW<[FXb, VecDF2, VecDF2, Lat30, GroupAlone], (instregex "CX(F|G)TR(A)?$")>; +def : InstRW<[FXb, VecDF, Lat30, BeginGroup], (instregex "CDL(F|G)TR$")>; +def : InstRW<[FXb, VecDF2, VecDF2, Lat30, GroupAlone], (instregex "CXL(F|G)TR$")>; + +// Convert to fixed / logical +def : InstRW<[FXb, VecDF, Lat30, BeginGroup], (instregex "C(F|G)DTR(A)?$")>; +def : InstRW<[FXb, VecDF, VecDF, Lat30, BeginGroup], (instregex "C(F|G)XTR(A)?$")>; +def : InstRW<[FXb, VecDF, Lat30, BeginGroup], (instregex "CL(F|G)DTR$")>; +def : InstRW<[FXb, VecDF, VecDF, Lat30, BeginGroup], (instregex "CL(F|G)XTR$")>; + +// Convert from / to signed / unsigned packed +def : InstRW<[FXb, VecDF, Lat9, BeginGroup], (instregex "CD(S|U)TR$")>; +def : InstRW<[FXb, FXb, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "CX(S|U)TR$")>; +def : InstRW<[FXb, VecDF, Lat12, BeginGroup], (instregex "C(S|U)DTR$")>; +def : InstRW<[FXb, FXb, VecDF2, VecDF2, Lat15, BeginGroup], (instregex "C(S|U)XTR$")>; + +// Convert from / to zoned +def : InstRW<[LSU, VecDF, Lat11, BeginGroup], (instregex "CDZT$")>; +def : InstRW<[LSU, LSU, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "CXZT$")>; +def : InstRW<[FXb, LSU, VecDF, Lat11, BeginGroup], (instregex "CZDT$")>; +def : InstRW<[FXb, LSU, VecDF, VecDF, Lat15, GroupAlone], (instregex "CZXT$")>; + +// Convert from / to packed +def : InstRW<[LSU, VecDF, Lat11, BeginGroup], (instregex "CDPT$")>; +def : InstRW<[LSU, LSU, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "CXPT$")>; +def : InstRW<[FXb, LSU, VecDF, Lat11, BeginGroup], (instregex "CPDT$")>; +def : InstRW<[FXb, LSU, VecDF, VecDF, Lat15, GroupAlone], (instregex "CPXT$")>; + +// Perform floating-point operation +def : InstRW<[LSU, Lat30, GroupAlone], (instregex "PFPO$")>; + +//===----------------------------------------------------------------------===// +// DFP: Unary arithmetic +//===----------------------------------------------------------------------===// + +// Load FP integer +def : InstRW<[VecDF], (instregex "FIDTR$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "FIXTR$")>; + +// Extract biased exponent +def : InstRW<[FXb, VecDF, Lat12, BeginGroup], (instregex "EEDTR$")>; +def : InstRW<[FXb, VecDF, Lat12, BeginGroup], (instregex "EEXTR$")>; + +// Extract significance +def : InstRW<[FXb, VecDF, Lat12, BeginGroup], (instregex "ESDTR$")>; +def : InstRW<[FXb, VecDF, VecDF, Lat15, BeginGroup], (instregex "ESXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition +def : InstRW<[VecDF], (instregex "ADTR(A)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "AXTR(A)?$")>; + +// Subtraction +def : InstRW<[VecDF], (instregex "SDTR(A)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "SXTR(A)?$")>; + +// Multiply +def : InstRW<[VecDF, Lat30], (instregex "MDTR(A)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat30, GroupAlone], (instregex "MXTR(A)?$")>; + +// Division +def : InstRW<[VecDF, Lat30], (instregex "DDTR(A)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat30, GroupAlone], (instregex "DXTR(A)?$")>; + +// Quantize +def : InstRW<[VecDF], (instregex "QADTR$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "QAXTR$")>; + +// Reround +def : InstRW<[FXb, VecDF, Lat11], (instregex "RRDTR$")>; +def : InstRW<[FXb, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "RRXTR$")>; + +// Shift significand left/right +def : InstRW<[LSU, VecDF, Lat11], (instregex "S(L|R)DT$")>; +def : InstRW<[LSU, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "S(L|R)XT$")>; + +// Insert biased exponent +def : InstRW<[FXb, VecDF, Lat11], (instregex "IEDTR$")>; +def : InstRW<[FXb, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "IEXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Comparisons +//===----------------------------------------------------------------------===// + +// Compare +def : InstRW<[VecDF], (instregex "(K|C)DTR$")>; +def : InstRW<[VecDF, VecDF, Lat11, GroupAlone], (instregex "(K|C)XTR$")>; + +// Compare biased exponent +def : InstRW<[VecDF], (instregex "CEDTR$")>; +def : InstRW<[VecDF], (instregex "CEXTR$")>; + +// Test Data Class/Group +def : InstRW<[LSU, VecDF, Lat11], (instregex "TD(C|G)(E|D)T$")>; +def : InstRW<[LSU, VecDF2, VecDF2, Lat15, GroupAlone], (instregex "TD(C|G)XT$")>; + + // --------------------------------- Vector --------------------------------- // //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td b/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td index 670df8ff5541..126eac2e2072 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td @@ -839,5 +839,224 @@ def : InstRW<[FXU, Lat30, GroupAlone], (instregex "SFASR$")>; def : InstRW<[FXU, LSU, Lat30, GroupAlone], (instregex "LFAS$")>; def : InstRW<[FXU, Lat2, GroupAlone], (instregex "SRNM(B|T)?$")>; + +// --------------------- Hexadecimal floating point ------------------------- // + +//===----------------------------------------------------------------------===// +// HFP: Move instructions +//===----------------------------------------------------------------------===// + +// Load and Test +def : InstRW<[FPU], (instregex "LT(D|E)R$")>; +def : InstRW<[FPU2, FPU2, Lat9, GroupAlone], (instregex "LTXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Conversion instructions +//===----------------------------------------------------------------------===// + +// Load rounded +def : InstRW<[FPU], (instregex "(LEDR|LRER)$")>; +def : InstRW<[FPU], (instregex "LEXR$")>; +def : InstRW<[FPU], (instregex "(LDXR|LRDR)$")>; + +// Load lengthened +def : InstRW<[LSU], (instregex "LDE$")>; +def : InstRW<[FXU], (instregex "LDER$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "LX(D|E)$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "LX(D|E)R$")>; + +// Convert from fixed +def : InstRW<[FXU, FPU, Lat9, GroupAlone], (instregex "CE(F|G)R$")>; +def : InstRW<[FXU, FPU, Lat9, GroupAlone], (instregex "CD(F|G)R$")>; +def : InstRW<[FXU, FPU2, FPU2, Lat11, GroupAlone], (instregex "CX(F|G)R$")>; + +// Convert to fixed +def : InstRW<[FXU, FPU, Lat12, GroupAlone], (instregex "CF(E|D)R$")>; +def : InstRW<[FXU, FPU, Lat12, GroupAlone], (instregex "CG(E|D)R$")>; +def : InstRW<[FXU, FPU, FPU, Lat20, GroupAlone], (instregex "C(F|G)XR$")>; + +// Convert BFP to HFP / HFP to BFP. +def : InstRW<[FPU], (instregex "THD(E)?R$")>; +def : InstRW<[FPU], (instregex "TB(E)?DR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Unary arithmetic +//===----------------------------------------------------------------------===// + +// Load Complement / Negative / Positive +def : InstRW<[FPU], (instregex "L(C|N|P)DR$")>; +def : InstRW<[FPU], (instregex "L(C|N|P)ER$")>; +def : InstRW<[FPU2, FPU2, Lat9, GroupAlone], (instregex "L(C|N|P)XR$")>; + +// Halve +def : InstRW<[FPU], (instregex "H(E|D)R$")>; + +// Square root +def : InstRW<[FPU, LSU, Lat30], (instregex "SQ(E|D)$")>; +def : InstRW<[FPU, Lat30], (instregex "SQ(E|D)R$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "SQXR$")>; + +// Load FP integer +def : InstRW<[FPU], (instregex "FIER$")>; +def : InstRW<[FPU], (instregex "FIDR$")>; +def : InstRW<[FPU2, FPU2, Lat15, GroupAlone], (instregex "FIXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition +def : InstRW<[FPU, LSU, Lat12], (instregex "A(E|D|U|W)$")>; +def : InstRW<[FPU], (instregex "A(E|D|U|W)R$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "AXR$")>; + +// Subtraction +def : InstRW<[FPU, LSU, Lat12], (instregex "S(E|D|U|W)$")>; +def : InstRW<[FPU], (instregex "S(E|D|U|W)R$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "SXR$")>; + +// Multiply +def : InstRW<[FPU, LSU, Lat12], (instregex "M(D|DE|E|EE)$")>; +def : InstRW<[FPU], (instregex "M(D|DE|E|EE)R$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MXD$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MXDR$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "MXR$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MY(H|L)?$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MY(H|L)?R$")>; + +// Multiply and add / subtract +def : InstRW<[FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)E$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)ER$")>; +def : InstRW<[FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)D$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)DR$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat12, GroupAlone], (instregex "MAY(H|L)?$")>; +def : InstRW<[FPU2, FPU2, GroupAlone], (instregex "MAY(H|L)?R$")>; + +// Division +def : InstRW<[FPU, LSU, Lat30], (instregex "D(E|D)$")>; +def : InstRW<[FPU, Lat30], (instregex "D(E|D)R$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "DXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Comparisons +//===----------------------------------------------------------------------===// + +// Compare +def : InstRW<[FPU, LSU, Lat12], (instregex "C(E|D)$")>; +def : InstRW<[FPU], (instregex "C(E|D)R$")>; +def : InstRW<[FPU, FPU, Lat15], (instregex "CXR$")>; + + +// ------------------------ Decimal floating point -------------------------- // + +//===----------------------------------------------------------------------===// +// DFP: Move instructions +//===----------------------------------------------------------------------===// + +// Load and Test +def : InstRW<[DFU, Lat20], (instregex "LTDTR$")>; +def : InstRW<[DFU2, DFU2, Lat20, GroupAlone], (instregex "LTXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Conversion instructions +//===----------------------------------------------------------------------===// + +// Load rounded +def : InstRW<[DFU, Lat30], (instregex "LEDTR$")>; +def : InstRW<[DFU, DFU, Lat30], (instregex "LDXTR$")>; + +// Load lengthened +def : InstRW<[DFU, Lat20], (instregex "LDETR$")>; +def : InstRW<[DFU2, DFU2, Lat20, GroupAlone], (instregex "LXDTR$")>; + +// Convert from fixed / logical +def : InstRW<[FXU, DFU, Lat30, GroupAlone], (instregex "CD(F|G)TR(A)?$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat30, GroupAlone], (instregex "CX(F|G)TR(A)?$")>; +def : InstRW<[FXU, DFU, Lat11, GroupAlone], (instregex "CDL(F|G)TR$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat11, GroupAlone], (instregex "CXL(F|G)TR$")>; + +// Convert to fixed / logical +def : InstRW<[FXU, DFU, Lat30, GroupAlone], (instregex "C(F|G)DTR(A)?$")>; +def : InstRW<[FXU, DFU, DFU, Lat30, GroupAlone], (instregex "C(F|G)XTR(A)?$")>; +def : InstRW<[FXU, DFU, Lat30, GroupAlone], (instregex "CL(F|G)DTR$")>; +def : InstRW<[FXU, DFU, DFU, Lat30, GroupAlone], (instregex "CL(F|G)XTR$")>; + +// Convert from / to signed / unsigned packed +def : InstRW<[FXU, DFU, Lat12, GroupAlone], (instregex "CD(S|U)TR$")>; +def : InstRW<[FXU, FXU, DFU2, DFU2, Lat20, GroupAlone], (instregex "CX(S|U)TR$")>; +def : InstRW<[FXU, DFU, Lat12, GroupAlone], (instregex "C(S|U)DTR$")>; +def : InstRW<[FXU, FXU, DFU2, DFU2, Lat20, GroupAlone], (instregex "C(S|U)XTR$")>; + +// Perform floating-point operation +def : InstRW<[LSU, Lat30, GroupAlone], (instregex "PFPO$")>; + +//===----------------------------------------------------------------------===// +// DFP: Unary arithmetic +//===----------------------------------------------------------------------===// + +// Load FP integer +def : InstRW<[DFU, Lat20], (instregex "FIDTR$")>; +def : InstRW<[DFU2, DFU2, Lat20, GroupAlone], (instregex "FIXTR$")>; + +// Extract biased exponent +def : InstRW<[FXU, DFU, Lat15, GroupAlone], (instregex "EEDTR$")>; +def : InstRW<[FXU, DFU, Lat15, GroupAlone], (instregex "EEXTR$")>; + +// Extract significance +def : InstRW<[FXU, DFU, Lat15, GroupAlone], (instregex "ESDTR$")>; +def : InstRW<[FXU, DFU, DFU, Lat20, GroupAlone], (instregex "ESXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition +def : InstRW<[DFU, Lat30], (instregex "ADTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "AXTR(A)?$")>; + +// Subtraction +def : InstRW<[DFU, Lat30], (instregex "SDTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "SXTR(A)?$")>; + +// Multiply +def : InstRW<[DFU, Lat30], (instregex "MDTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "MXTR(A)?$")>; + +// Division +def : InstRW<[DFU, Lat30], (instregex "DDTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "DXTR(A)?$")>; + +// Quantize +def : InstRW<[DFU, Lat30], (instregex "QADTR$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "QAXTR$")>; + +// Reround +def : InstRW<[FXU, DFU, Lat30], (instregex "RRDTR$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat30, GroupAlone], (instregex "RRXTR$")>; + +// Shift significand left/right +def : InstRW<[LSU, DFU, Lat11], (instregex "S(L|R)DT$")>; +def : InstRW<[LSU, DFU2, DFU2, Lat15, GroupAlone], (instregex "S(L|R)XT$")>; + +// Insert biased exponent +def : InstRW<[FXU, DFU, Lat11], (instregex "IEDTR$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat15, GroupAlone], (instregex "IEXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Comparisons +//===----------------------------------------------------------------------===// + +// Compare +def : InstRW<[DFU, Lat11], (instregex "(K|C)DTR$")>; +def : InstRW<[DFU, DFU, Lat15, GroupAlone], (instregex "(K|C)XTR$")>; + +// Compare biased exponent +def : InstRW<[DFU, Lat8], (instregex "CEDTR$")>; +def : InstRW<[DFU, Lat9], (instregex "CEXTR$")>; + +// Test Data Class/Group +def : InstRW<[LSU, DFU, Lat15], (instregex "TD(C|G)(E|D)T$")>; +def : InstRW<[LSU, DFU2, DFU2, Lat15, GroupAlone], (instregex "TD(C|G)XT$")>; + } diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td b/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td index 1bdb8779dc72..d38ca64d2e9b 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td +++ b/contrib/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td @@ -877,5 +877,230 @@ def : InstRW<[FXU, Lat30, GroupAlone], (instregex "SFASR$")>; def : InstRW<[FXU, LSU, Lat30, GroupAlone], (instregex "LFAS$")>; def : InstRW<[FXU, Lat2, GroupAlone], (instregex "SRNM(B|T)?$")>; + +// --------------------- Hexadecimal floating point ------------------------- // + +//===----------------------------------------------------------------------===// +// HFP: Move instructions +//===----------------------------------------------------------------------===// + +// Load and Test +def : InstRW<[FPU], (instregex "LT(D|E)R$")>; +def : InstRW<[FPU2, FPU2, Lat9, GroupAlone], (instregex "LTXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Conversion instructions +//===----------------------------------------------------------------------===// + +// Load rounded +def : InstRW<[FPU], (instregex "(LEDR|LRER)$")>; +def : InstRW<[FPU], (instregex "LEXR$")>; +def : InstRW<[FPU], (instregex "(LDXR|LRDR)$")>; + +// Load lengthened +def : InstRW<[LSU], (instregex "LDE$")>; +def : InstRW<[FXU], (instregex "LDER$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "LX(D|E)$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "LX(D|E)R$")>; + +// Convert from fixed +def : InstRW<[FXU, FPU, Lat9, GroupAlone], (instregex "CE(F|G)R$")>; +def : InstRW<[FXU, FPU, Lat9, GroupAlone], (instregex "CD(F|G)R$")>; +def : InstRW<[FXU, FPU2, FPU2, Lat11, GroupAlone], (instregex "CX(F|G)R$")>; + +// Convert to fixed +def : InstRW<[FXU, FPU, Lat12, GroupAlone], (instregex "CF(E|D)R$")>; +def : InstRW<[FXU, FPU, Lat12, GroupAlone], (instregex "CG(E|D)R$")>; +def : InstRW<[FXU, FPU, FPU, Lat20, GroupAlone], (instregex "C(F|G)XR$")>; + +// Convert BFP to HFP / HFP to BFP. +def : InstRW<[FPU], (instregex "THD(E)?R$")>; +def : InstRW<[FPU], (instregex "TB(E)?DR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Unary arithmetic +//===----------------------------------------------------------------------===// + +// Load Complement / Negative / Positive +def : InstRW<[FPU], (instregex "L(C|N|P)DR$")>; +def : InstRW<[FPU], (instregex "L(C|N|P)ER$")>; +def : InstRW<[FPU2, FPU2, Lat9, GroupAlone], (instregex "L(C|N|P)XR$")>; + +// Halve +def : InstRW<[FPU], (instregex "H(E|D)R$")>; + +// Square root +def : InstRW<[FPU, LSU, Lat30], (instregex "SQ(E|D)$")>; +def : InstRW<[FPU, Lat30], (instregex "SQ(E|D)R$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "SQXR$")>; + +// Load FP integer +def : InstRW<[FPU], (instregex "FIER$")>; +def : InstRW<[FPU], (instregex "FIDR$")>; +def : InstRW<[FPU2, FPU2, Lat15, GroupAlone], (instregex "FIXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition +def : InstRW<[FPU, LSU, Lat12], (instregex "A(E|D|U|W)$")>; +def : InstRW<[FPU], (instregex "A(E|D|U|W)R$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "AXR$")>; + +// Subtraction +def : InstRW<[FPU, LSU, Lat12], (instregex "S(E|D|U|W)$")>; +def : InstRW<[FPU], (instregex "S(E|D|U|W)R$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "SXR$")>; + +// Multiply +def : InstRW<[FPU, LSU, Lat12], (instregex "M(D|DE|E|EE)$")>; +def : InstRW<[FPU], (instregex "M(D|DE|E|EE)R$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MXD$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MXDR$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "MXR$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MY(H|L)?$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MY(H|L)?R$")>; + +// Multiply and add / subtract +def : InstRW<[FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)E$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)ER$")>; +def : InstRW<[FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)D$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)DR$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat12, GroupAlone], (instregex "MAY(H|L)?$")>; +def : InstRW<[FPU2, FPU2, GroupAlone], (instregex "MAY(H|L)?R$")>; + +// Division +def : InstRW<[FPU, LSU, Lat30], (instregex "D(E|D)$")>; +def : InstRW<[FPU, Lat30], (instregex "D(E|D)R$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "DXR$")>; + +//===----------------------------------------------------------------------===// +// HFP: Comparisons +//===----------------------------------------------------------------------===// + +// Compare +def : InstRW<[FPU, LSU, Lat12], (instregex "C(E|D)$")>; +def : InstRW<[FPU], (instregex "C(E|D)R$")>; +def : InstRW<[FPU, FPU, Lat15], (instregex "CXR$")>; + + +// ------------------------ Decimal floating point -------------------------- // + +//===----------------------------------------------------------------------===// +// DFP: Move instructions +//===----------------------------------------------------------------------===// + +// Load and Test +def : InstRW<[DFU, Lat20], (instregex "LTDTR$")>; +def : InstRW<[DFU2, DFU2, Lat20, GroupAlone], (instregex "LTXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Conversion instructions +//===----------------------------------------------------------------------===// + +// Load rounded +def : InstRW<[DFU, Lat30], (instregex "LEDTR$")>; +def : InstRW<[DFU, DFU, Lat30], (instregex "LDXTR$")>; + +// Load lengthened +def : InstRW<[DFU, Lat20], (instregex "LDETR$")>; +def : InstRW<[DFU2, DFU2, Lat20, GroupAlone], (instregex "LXDTR$")>; + +// Convert from fixed / logical +def : InstRW<[FXU, DFU, Lat30, GroupAlone], (instregex "CD(F|G)TR(A)?$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat30, GroupAlone], (instregex "CX(F|G)TR(A)?$")>; +def : InstRW<[FXU, DFU, Lat11, GroupAlone], (instregex "CDL(F|G)TR$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat11, GroupAlone], (instregex "CXL(F|G)TR$")>; + +// Convert to fixed / logical +def : InstRW<[FXU, DFU, Lat30, GroupAlone], (instregex "C(F|G)DTR(A)?$")>; +def : InstRW<[FXU, DFU, DFU, Lat30, GroupAlone], (instregex "C(F|G)XTR(A)?$")>; +def : InstRW<[FXU, DFU, Lat30, GroupAlone], (instregex "CL(F|G)DTR$")>; +def : InstRW<[FXU, DFU, DFU, Lat30, GroupAlone], (instregex "CL(F|G)XTR$")>; + +// Convert from / to signed / unsigned packed +def : InstRW<[FXU, DFU, Lat12, GroupAlone], (instregex "CD(S|U)TR$")>; +def : InstRW<[FXU, FXU, DFU2, DFU2, Lat20, GroupAlone], (instregex "CX(S|U)TR$")>; +def : InstRW<[FXU, DFU, Lat12, GroupAlone], (instregex "C(S|U)DTR$")>; +def : InstRW<[FXU, FXU, DFU2, DFU2, Lat20, GroupAlone], (instregex "C(S|U)XTR$")>; + +// Convert from / to zoned +def : InstRW<[LSU, DFU2, Lat7, GroupAlone], (instregex "CDZT$")>; +def : InstRW<[LSU, LSU, DFU2, DFU2, Lat10, GroupAlone], (instregex "CXZT$")>; +def : InstRW<[FXU, LSU, DFU, Lat11, GroupAlone], (instregex "CZDT$")>; +def : InstRW<[FXU, LSU, DFU, DFU, Lat15, GroupAlone], (instregex "CZXT$")>; + +// Perform floating-point operation +def : InstRW<[LSU, Lat30, GroupAlone], (instregex "PFPO$")>; + +//===----------------------------------------------------------------------===// +// DFP: Unary arithmetic +//===----------------------------------------------------------------------===// + +// Load FP integer +def : InstRW<[DFU, Lat20], (instregex "FIDTR$")>; +def : InstRW<[DFU2, DFU2, Lat20, GroupAlone], (instregex "FIXTR$")>; + +// Extract biased exponent +def : InstRW<[FXU, DFU, Lat15, GroupAlone], (instregex "EEDTR$")>; +def : InstRW<[FXU, DFU, Lat15, GroupAlone], (instregex "EEXTR$")>; + +// Extract significance +def : InstRW<[FXU, DFU, Lat15, GroupAlone], (instregex "ESDTR$")>; +def : InstRW<[FXU, DFU, DFU, Lat20, GroupAlone], (instregex "ESXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Binary arithmetic +//===----------------------------------------------------------------------===// + +// Addition +def : InstRW<[DFU, Lat30], (instregex "ADTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "AXTR(A)?$")>; + +// Subtraction +def : InstRW<[DFU, Lat30], (instregex "SDTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "SXTR(A)?$")>; + +// Multiply +def : InstRW<[DFU, Lat30], (instregex "MDTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "MXTR(A)?$")>; + +// Division +def : InstRW<[DFU, Lat30], (instregex "DDTR(A)?$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "DXTR(A)?$")>; + +// Quantize +def : InstRW<[DFU, Lat30], (instregex "QADTR$")>; +def : InstRW<[DFU2, DFU2, Lat30, GroupAlone], (instregex "QAXTR$")>; + +// Reround +def : InstRW<[FXU, DFU, Lat30], (instregex "RRDTR$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat30, GroupAlone], (instregex "RRXTR$")>; + +// Shift significand left/right +def : InstRW<[LSU, DFU, Lat11], (instregex "S(L|R)DT$")>; +def : InstRW<[LSU, DFU2, DFU2, Lat15, GroupAlone], (instregex "S(L|R)XT$")>; + +// Insert biased exponent +def : InstRW<[FXU, DFU, Lat11], (instregex "IEDTR$")>; +def : InstRW<[FXU, DFU2, DFU2, Lat15, GroupAlone], (instregex "IEXTR$")>; + +//===----------------------------------------------------------------------===// +// DFP: Comparisons +//===----------------------------------------------------------------------===// + +// Compare +def : InstRW<[DFU, Lat11], (instregex "(K|C)DTR$")>; +def : InstRW<[DFU, DFU, Lat15, GroupAlone], (instregex "(K|C)XTR$")>; + +// Compare biased exponent +def : InstRW<[DFU, Lat8], (instregex "CEDTR$")>; +def : InstRW<[DFU, Lat9], (instregex "CEXTR$")>; + +// Test Data Class/Group +def : InstRW<[LSU, DFU, Lat15], (instregex "TD(C|G)(E|D)T$")>; +def : InstRW<[LSU, DFU2, DFU2, Lat15, GroupAlone], (instregex "TD(C|G)XT$")>; + } diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp index 022679a7bc18..0ab0c2f25915 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -42,8 +42,10 @@ SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU, HasMiscellaneousExtensions(false), HasExecutionHint(false), HasLoadAndTrap(false), HasTransactionalExecution(false), HasProcessorAssist(false), + HasDFPZonedConversion(false), HasVector(false), HasLoadStoreOnCond2(false), HasLoadAndZeroRightmostByte(false), HasMessageSecurityAssist5(false), + HasDFPPackedConversion(false), TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), TSInfo(), FrameLowering() {} diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h index 770dd7cd939f..36e51921bf2f 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h +++ b/contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h @@ -47,10 +47,12 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo { bool HasLoadAndTrap; bool HasTransactionalExecution; bool HasProcessorAssist; + bool HasDFPZonedConversion; bool HasVector; bool HasLoadStoreOnCond2; bool HasLoadAndZeroRightmostByte; bool HasMessageSecurityAssist5; + bool HasDFPPackedConversion; private: Triple TargetTriple; @@ -133,6 +135,9 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo { // Return true if the target has the processor-assist facility. bool hasProcessorAssist() const { return HasProcessorAssist; } + // Return true if the target has the DFP zoned-conversion facility. + bool hasDFPZonedConversion() const { return HasDFPZonedConversion; } + // Return true if the target has the load-and-zero-rightmost-byte facility. bool hasLoadAndZeroRightmostByte() const { return HasLoadAndZeroRightmostByte; @@ -142,6 +147,9 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo { // extension facility 5. bool hasMessageSecurityAssist5() const { return HasMessageSecurityAssist5; } + // Return true if the target has the DFP packed-conversion facility. + bool hasDFPPackedConversion() const { return HasDFPPackedConversion; } + // Return true if the target has the vector facility. bool hasVector() const { return HasVector; } diff --git a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 31a5ca1f4cc2..814377003cbc 100644 --- a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -84,8 +84,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE}) setCondCodeAction(CC, T, Expand); // Expand floating-point library function operators. - for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOWI, ISD::FPOW, - ISD::FREM, ISD::FMA}) + for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, + ISD::FMA}) setOperationAction(Op, T, Expand); // Note supported floating-point library function operators that otherwise // default to expand. diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp index 86744b064132..8d78308afe9d 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -80,6 +80,12 @@ static cl::opt ExperimentalPrefLoopAlignment( " of the loop header PC will be 0)."), cl::Hidden); +static cl::opt MulConstantOptimization( + "mul-constant-optimization", cl::init(true), + cl::desc("Replace 'mul x, Const' with more effective instructions like " + "SHIFT, LEA, etc."), + cl::Hidden); + /// Call this when the user attempts to do something unsupported, like /// returning a double without SSE2 enabled on x86_64. This is not fatal, unlike /// report_fatal_error, so calling code should attempt to recover without @@ -670,7 +676,6 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::FSINCOS, VT, Expand); setOperationAction(ISD::FCOS, VT, Expand); setOperationAction(ISD::FREM, VT, Expand); - setOperationAction(ISD::FPOWI, VT, Expand); setOperationAction(ISD::FCOPYSIGN, VT, Expand); setOperationAction(ISD::FPOW, VT, Expand); setOperationAction(ISD::FLOG, VT, Expand); @@ -30928,6 +30933,75 @@ static SDValue reduceVMULWidth(SDNode *N, SelectionDAG &DAG, } } +static SDValue combineMulSpecial(uint64_t MulAmt, SDNode *N, SelectionDAG &DAG, + EVT VT, SDLoc DL) { + + auto combineMulShlAddOrSub = [&](int Mult, int Shift, bool isAdd) { + SDValue Result = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(Mult, DL, VT)); + Result = DAG.getNode(ISD::SHL, DL, VT, Result, + DAG.getConstant(Shift, DL, MVT::i8)); + Result = DAG.getNode(isAdd ? ISD::ADD : ISD::SUB, DL, VT, N->getOperand(0), + Result); + return Result; + }; + + auto combineMulMulAddOrSub = [&](bool isAdd) { + SDValue Result = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(9, DL, VT)); + Result = DAG.getNode(ISD::MUL, DL, VT, Result, DAG.getConstant(3, DL, VT)); + Result = DAG.getNode(isAdd ? ISD::ADD : ISD::SUB, DL, VT, N->getOperand(0), + Result); + return Result; + }; + + switch (MulAmt) { + default: + break; + case 11: + // mul x, 11 => add ((shl (mul x, 5), 1), x) + return combineMulShlAddOrSub(5, 1, /*isAdd*/ true); + case 21: + // mul x, 21 => add ((shl (mul x, 5), 2), x) + return combineMulShlAddOrSub(5, 2, /*isAdd*/ true); + case 22: + // mul x, 22 => add (add ((shl (mul x, 5), 2), x), x) + return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), + combineMulShlAddOrSub(5, 2, /*isAdd*/ true)); + case 19: + // mul x, 19 => sub ((shl (mul x, 5), 2), x) + return combineMulShlAddOrSub(5, 2, /*isAdd*/ false); + case 13: + // mul x, 13 => add ((shl (mul x, 3), 2), x) + return combineMulShlAddOrSub(3, 2, /*isAdd*/ true); + case 23: + // mul x, 13 => sub ((shl (mul x, 3), 3), x) + return combineMulShlAddOrSub(3, 3, /*isAdd*/ false); + case 14: + // mul x, 14 => add (add ((shl (mul x, 3), 2), x), x) + return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), + combineMulShlAddOrSub(3, 2, /*isAdd*/ true)); + case 26: + // mul x, 26 => sub ((mul (mul x, 9), 3), x) + return combineMulMulAddOrSub(/*isAdd*/ false); + case 28: + // mul x, 28 => add ((mul (mul x, 9), 3), x) + return combineMulMulAddOrSub(/*isAdd*/ true); + case 29: + // mul x, 29 => add (add ((mul (mul x, 9), 3), x), x) + return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), + combineMulMulAddOrSub(/*isAdd*/ true)); + case 30: + // mul x, 30 => sub (sub ((shl x, 5), x), x) + return DAG.getNode( + ISD::SUB, DL, VT, N->getOperand(0), + DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0), + DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), + DAG.getConstant(5, DL, MVT::i8)))); + } + return SDValue(); +} + /// Optimize a single multiply with constant into two operations in order to /// implement it with two cheaper instructions, e.g. LEA + SHL, LEA + LEA. static SDValue combineMul(SDNode *N, SelectionDAG &DAG, @@ -30937,6 +31011,8 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG, if (DCI.isBeforeLegalize() && VT.isVector()) return reduceVMULWidth(N, DAG, Subtarget); + if (!MulConstantOptimization) + return SDValue(); // An imul is usually smaller than the alternative sequence. if (DAG.getMachineFunction().getFunction()->optForMinSize()) return SDValue(); @@ -30992,7 +31068,8 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG, else NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, NewMul, DAG.getConstant(MulAmt2, DL, VT)); - } + } else if (!Subtarget.slowLEA()) + NewMul = combineMulSpecial(MulAmt, N, DAG, VT, DL); if (!NewMul) { assert(MulAmt != 0 && diff --git a/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp b/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp index 67abc3116988..5e9f40019ce8 100644 --- a/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -377,7 +377,6 @@ class CongruenceClass { int StoreCount = 0; }; -struct HashedExpression; namespace llvm { template <> struct DenseMapInfo { static const Expression *getEmptyKey() { @@ -391,41 +390,25 @@ template <> struct DenseMapInfo { return reinterpret_cast(Val); } static unsigned getHashValue(const Expression *E) { - return static_cast(E->getHashValue()); + return static_cast(E->getComputedHash()); } - static unsigned getHashValue(const HashedExpression &HE); - static bool isEqual(const HashedExpression &LHS, const Expression *RHS); static bool isEqual(const Expression *LHS, const Expression *RHS) { if (LHS == RHS) return true; if (LHS == getTombstoneKey() || RHS == getTombstoneKey() || LHS == getEmptyKey() || RHS == getEmptyKey()) return false; + // Compare hashes before equality. This is *not* what the hashtable does, + // since it is computing it modulo the number of buckets, whereas we are + // using the full hash keyspace. Since the hashes are precomputed, this + // check is *much* faster than equality. + if (LHS->getComputedHash() != RHS->getComputedHash()) + return false; return *LHS == *RHS; } }; } // end namespace llvm -// This is just a wrapper around Expression that computes the hash value once at -// creation time. Hash values for an Expression can't change once they are -// inserted into the DenseMap (it breaks DenseMap), so they must be immutable at -// that point anyway. -struct HashedExpression { - const Expression *E; - unsigned HashVal; - HashedExpression(const Expression *E) - : E(E), HashVal(DenseMapInfo::getHashValue(E)) {} -}; - -unsigned -DenseMapInfo::getHashValue(const HashedExpression &HE) { - return HE.HashVal; -} -bool DenseMapInfo::isEqual(const HashedExpression &LHS, - const Expression *RHS) { - return isEqual(LHS.E, RHS); -} - namespace { class NewGVN { Function &F; @@ -707,7 +690,7 @@ class NewGVN { void markPredicateUsersTouched(Instruction *); void markValueLeaderChangeTouched(CongruenceClass *CC); void markMemoryLeaderChangeTouched(CongruenceClass *CC); - void markPhiOfOpsChanged(const HashedExpression &HE); + void markPhiOfOpsChanged(const Expression *E); void addPredicateUsers(const PredicateBase *, Instruction *) const; void addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const; void addAdditionalUsers(Value *To, Value *User) const; @@ -956,8 +939,12 @@ const Expression *NewGVN::checkSimplificationResults(Expression *E, if (CC && CC->getDefiningExpr()) { // If we simplified to something else, we need to communicate // that we're users of the value we simplified to. - if (I != V) - addAdditionalUsers(V, I); + if (I != V) { + // Don't add temporary instructions to the user lists. + if (!AllTempInstructions.count(I)) + addAdditionalUsers(V, I); + } + if (I) DEBUG(dbgs() << "Simplified " << *I << " to " << " expression " << *CC->getDefiningExpr() << "\n"); @@ -2195,8 +2182,8 @@ void NewGVN::moveValueToNewCongruenceClass(Instruction *I, const Expression *E, // For a given expression, mark the phi of ops instructions that could have // changed as a result. -void NewGVN::markPhiOfOpsChanged(const HashedExpression &HE) { - touchAndErase(ExpressionToPhiOfOps, HE); +void NewGVN::markPhiOfOpsChanged(const Expression *E) { + touchAndErase(ExpressionToPhiOfOps, E); } // Perform congruence finding on a given value numbering expression. @@ -2210,14 +2197,13 @@ void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) { assert(!IClass->isDead() && "Found a dead class"); CongruenceClass *EClass = nullptr; - HashedExpression HE(E); if (const auto *VE = dyn_cast(E)) { EClass = ValueToClass.lookup(VE->getVariableValue()); } else if (isa(E)) { EClass = TOPClass; } if (!EClass) { - auto lookupResult = ExpressionToClass.insert_as({E, nullptr}, HE); + auto lookupResult = ExpressionToClass.insert({E, nullptr}); // If it's not in the value table, create a new congruence class. if (lookupResult.second) { @@ -2268,7 +2254,7 @@ void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) { << "\n"); if (ClassChanged) { moveValueToNewCongruenceClass(I, E, IClass, EClass); - markPhiOfOpsChanged(HE); + markPhiOfOpsChanged(E); } markUsersTouched(I); @@ -2502,9 +2488,8 @@ NewGVN::makePossiblePhiOfOps(Instruction *I, bool HasBackedge, // Clone the instruction, create an expression from it, and see if we // have a leader. Instruction *ValueOp = I->clone(); - auto Iter = TempToMemory.end(); if (MemAccess) - Iter = TempToMemory.insert({ValueOp, MemAccess}).first; + TempToMemory.insert({ValueOp, MemAccess}); for (auto &Op : ValueOp->operands()) { Op = Op->DoPHITranslation(PHIBlock, PredBB); @@ -2523,7 +2508,7 @@ NewGVN::makePossiblePhiOfOps(Instruction *I, bool HasBackedge, AllTempInstructions.erase(ValueOp); ValueOp->deleteValue(); if (MemAccess) - TempToMemory.erase(Iter); + TempToMemory.erase(ValueOp); if (!E) return nullptr; FoundVal = findPhiOfOpsLeader(E, PredBB); diff --git a/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 3b036a6ac430..2b83b8426d14 100644 --- a/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -7173,7 +7173,7 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, unsigned VF) { // Note: Even if all instructions are scalarized, return true if any memory // accesses appear in the loop to get benefits from address folding etc. bool TypeNotScalarized = - VF > 1 && VectorTy->isVectorTy() && TTI.getNumberOfParts(VectorTy) < VF; + VF > 1 && !VectorTy->isVoidTy() && TTI.getNumberOfParts(VectorTy) < VF; return VectorizationCostTy(C, TypeNotScalarized); } @@ -7312,7 +7312,7 @@ unsigned LoopVectorizationCostModel::getInstructionCost(Instruction *I, Type *RetTy = I->getType(); if (canTruncateToMinimalBitwidth(I, VF)) RetTy = IntegerType::get(RetTy->getContext(), MinBWs[I]); - VectorTy = isScalarAfterVectorization(I, VF) ? RetTy : ToVectorTy(RetTy, VF); + VectorTy = ToVectorTy(RetTy, VF); auto SE = PSE.getSE(); // TODO: We need to estimate the cost of intrinsic calls. @@ -7445,10 +7445,9 @@ unsigned LoopVectorizationCostModel::getInstructionCost(Instruction *I, } else if (Legal->isUniform(Op2)) { Op2VK = TargetTransformInfo::OK_UniformValue; } - SmallVector Operands(I->operand_values()); - unsigned N = isScalarAfterVectorization(I, VF) ? VF : 1; - return N * TTI.getArithmeticInstrCost(I->getOpcode(), VectorTy, Op1VK, - Op2VK, Op1VP, Op2VP, Operands); + SmallVector Operands(I->operand_values()); + return TTI.getArithmeticInstrCost(I->getOpcode(), VectorTy, Op1VK, + Op2VK, Op1VP, Op2VP, Operands); } case Instruction::Select: { SelectInst *SI = cast(I); @@ -7471,15 +7470,7 @@ unsigned LoopVectorizationCostModel::getInstructionCost(Instruction *I, } case Instruction::Store: case Instruction::Load: { - unsigned Width = VF; - if (Width > 1) { - InstWidening Decision = getWideningDecision(I, Width); - assert(Decision != CM_Unknown && - "CM decision should be taken at this point"); - if (Decision == CM_Scalarize) - Width = 1; - } - VectorTy = ToVectorTy(getMemInstValueType(I), Width); + VectorTy = ToVectorTy(getMemInstValueType(I), VF); return getMemoryInstructionCost(I, VF); } case Instruction::ZExt: diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h index aeda39308f91..91b3d11a549a 100644 --- a/contrib/llvm/tools/clang/include/clang-c/Index.h +++ b/contrib/llvm/tools/clang/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 40 +#define CINDEX_VERSION_MINOR 41 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -1418,6 +1418,15 @@ CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName, unsigned options); +/** + * \brief Suspend a translation unit in order to free memory associated with it. + * + * A suspended translation unit uses significantly less memory but on the other + * side does not support any other calls than \c clang_reparseTranslationUnit + * to resume it or \c clang_disposeTranslationUnit to dispose it completely. + */ +CINDEX_LINKAGE unsigned clang_suspendTranslationUnit(CXTranslationUnit); + /** * \brief Destroy the specified CXTranslationUnit object. */ diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td index 77db8993f018..b393ce5f1545 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -525,6 +525,8 @@ def err_pp_module_begin_without_module_end : Error< def err_pp_module_end_without_module_begin : Error< "no matching '#pragma clang module begin' for this " "'#pragma clang module end'">; +def note_pp_module_begin_here : Note< + "entering module '%0' due to this pragma">; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_paste_at_start : Error< diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4934bcfa3890..629e8b837f59 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8312,8 +8312,13 @@ def err_opencl_bitfields : Error< "bit-fields are not supported in OpenCL">; def err_opencl_vla : Error< "variable length arrays are not supported in OpenCL">; +def err_opencl_scalar_type_rank_greater_than_vector_type : Error< + "scalar operand type has greater rank than the type of the vector " + "element. (%0 and %1)">; def err_bad_kernel_param_type : Error< "%0 cannot be used as the type of a kernel parameter">; +def err_opencl_implicit_function_decl : Error< + "implicit declaration of function %0 is invalid in OpenCL">; def err_record_with_pointers_kernel_param : Error< "%select{struct|union}0 kernel parameters may not contain pointers">; def note_within_field_of_type : Note< @@ -8744,8 +8749,8 @@ def err_omp_not_mappable_type : Error< "type %0 is not mappable to target">; def err_omp_invalid_map_type_for_directive : Error< "%select{map type '%1' is not allowed|map type must be specified}0 for '#pragma omp %2'">; -def err_omp_no_map_for_directive : Error< - "expected at least one map clause for '#pragma omp %0'">; +def err_omp_no_clause_for_directive : Error< + "expected at least one %0 clause for '#pragma omp %1'">; def note_omp_polymorphic_in_target : Note< "mappable type cannot be polymorphic">; def note_omp_static_member_in_target : Note< diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h index 7f70609efc97..fb0a5e8acd4a 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h @@ -878,6 +878,11 @@ class ASTUnit : public ModuleLoader { ArrayRef RemappedFiles = None, IntrusiveRefCntPtr VFS = nullptr); + /// \brief Free data that will be re-generated on the next parse. + /// + /// Preamble-related data is not affected. + void ResetForParse(); + /// \brief Perform code completion at the given file, line, and /// column within this translation unit. /// diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h index 9f015eaa230b..aeca83a90716 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h @@ -283,6 +283,44 @@ class Preprocessor { /// This is used when loading a precompiled preamble. std::pair SkipMainFilePreamble; + class PreambleConditionalStackStore { + enum State { + Off = 0, + Recording = 1, + Replaying = 2, + }; + + public: + PreambleConditionalStackStore() : ConditionalStackState(Off) {} + + void startRecording() { ConditionalStackState = Recording; } + void startReplaying() { ConditionalStackState = Replaying; } + bool isRecording() const { return ConditionalStackState == Recording; } + bool isReplaying() const { return ConditionalStackState == Replaying; } + + ArrayRef getStack() const { + return ConditionalStack; + } + + void doneReplaying() { + ConditionalStack.clear(); + ConditionalStackState = Off; + } + + void setStack(ArrayRef s) { + if (!isRecording() && !isReplaying()) + return; + ConditionalStack.clear(); + ConditionalStack.append(s.begin(), s.end()); + } + + bool hasRecordedPreamble() const { return !ConditionalStack.empty(); } + + private: + SmallVector ConditionalStack; + State ConditionalStackState; + } PreambleConditionalStack; + /// \brief The current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// @@ -1695,6 +1733,11 @@ class Preprocessor { /// \brief Return true if we're in the top-level file, not in a \#include. bool isInPrimaryFile() const; + /// \brief Return true if we're in the main file (specifically, if we are 0 + /// (zero) levels deep \#include. This is used by the lexer to determine if + /// it needs to generate errors about unterminated \#if directives. + bool isInMainFile() const; + /// \brief Handle cases where the \#include name is expanded /// from a macro as multiple tokens, which need to be glued together. /// @@ -1932,6 +1975,27 @@ class Preprocessor { Module *M, SourceLocation MLoc); + bool isRecordingPreamble() const { + return PreambleConditionalStack.isRecording(); + } + + bool hasRecordedPreamble() const { + return PreambleConditionalStack.hasRecordedPreamble(); + } + + ArrayRef getPreambleConditionalStack() const { + return PreambleConditionalStack.getStack(); + } + + void setRecordedPreambleConditionalStack(ArrayRef s) { + PreambleConditionalStack.setStack(s); + } + + void setReplayablePreambleConditionalStack(ArrayRef s) { + PreambleConditionalStack.startReplaying(); + PreambleConditionalStack.setStack(s); + } + private: // Macro handling. void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h index 6d6cf05a96c4..5c2e4d41454b 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h @@ -17,6 +17,7 @@ #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -176,6 +177,11 @@ class PreprocessorLexer { conditional_iterator conditional_end() const { return ConditionalStack.end(); } + + void setConditionalLevels(ArrayRef CL) { + ConditionalStack.clear(); + ConditionalStack.append(CL.begin(), CL.end()); + } }; } // end namespace clang diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h index 58d79f7ff81a..c85d2384fa47 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h @@ -80,7 +80,14 @@ class PreprocessorOptions { /// The boolean indicates whether the preamble ends at the start of a new /// line. std::pair PrecompiledPreambleBytes; - + + /// \brief True indicates that a preamble is being generated. + /// + /// When the lexer is done, one of the things that need to be preserved is the + /// conditional #if stack, so the ASTWriter/ASTReader can save/restore it when + /// processing the rest of the file. + bool GeneratePreamble; + /// The implicit PTH input included at the start of the translation unit, or /// empty. std::string ImplicitPTHInclude; @@ -144,6 +151,7 @@ class PreprocessorOptions { AllowPCHWithCompilerErrors(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), + GeneratePreamble(false), RemappedFilesKeepOriginalName(true), RetainRemappedFileBuffers(false), ObjCXXARCStandardLibrary(ARCXX_nolib) { } diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h index 823440b19713..6b40781a1239 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h @@ -607,6 +607,9 @@ namespace clang { /// \brief Record code for \#pragma pack options. PACK_PRAGMA_OPTIONS = 61, + + /// \brief The stack of open #ifs/#ifdefs recorded in a preamble. + PP_CONDITIONAL_STACK = 62, }; /// \brief Record types used within a source manager block. diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 790ba5c121c9..4171c685cb98 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -279,15 +279,15 @@ def VirtualCallChecker : Checker<"VirtualCall">, let ParentPackage = CplusplusAlpha in { +def IteratorRangeChecker : Checker<"IteratorRange">, + HelpText<"Check for iterators used outside their valid ranges">, + DescFile<"IteratorChecker.cpp">; + def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">, HelpText<"Method calls on a moved-from object and copying a moved-from " "object will be reported">, DescFile<"MisusedMovedObjectChecker.cpp">; -def IteratorPastEndChecker : Checker<"IteratorPastEnd">, - HelpText<"Check iterators used past end">, - DescFile<"IteratorPastEndChecker.cpp">; - } // end: "alpha.cplusplus" diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 2910ef4212cc..e3a2164b11ff 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -43,6 +43,7 @@ typedef std::unique_ptr(*ConstraintManagerCreator)( ProgramStateManager &, SubEngine *); typedef std::unique_ptr(*StoreManagerCreator)( ProgramStateManager &); +typedef llvm::ImmutableMap TaintedSubRegions; //===----------------------------------------------------------------------===// // ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState. @@ -343,6 +344,9 @@ class ProgramState : public llvm::FoldingSetNode { ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx, TaintTagType Kind = TaintTagGeneric) const; + /// Create a new state in which the value is marked as tainted. + ProgramStateRef addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; + /// Create a new state in which the symbol is marked as tainted. ProgramStateRef addTaint(SymbolRef S, TaintTagType Kind = TaintTagGeneric) const; @@ -351,6 +355,14 @@ class ProgramState : public llvm::FoldingSetNode { ProgramStateRef addTaint(const MemRegion *R, TaintTagType Kind = TaintTagGeneric) const; + /// Create a new state in a which a sub-region of a given symbol is tainted. + /// This might be necessary when referring to regions that can not have an + /// individual symbol, e.g. if they are represented by the default binding of + /// a LazyCompoundVal. + ProgramStateRef addPartialTaint(SymbolRef ParentSym, + const SubRegion *SubRegion, + TaintTagType Kind = TaintTagGeneric) const; + /// Check if the statement is tainted in the current state. bool isTainted(const Stmt *S, const LocationContext *LCtx, TaintTagType Kind = TaintTagGeneric) const; @@ -453,6 +465,7 @@ class ProgramStateManager { std::unique_ptr ConstraintMgr; ProgramState::GenericDataMap::Factory GDMFactory; + TaintedSubRegions::Factory TSRFactory; typedef llvm::DenseMap > GDMContextsTy; GDMContextsTy GDMContexts; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h index d39b5017d312..7b76263f040c 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -35,6 +35,16 @@ template<> struct ProgramStateTrait static void *GDMIndex() { static int index = 0; return &index; } }; +/// The GDM component mapping derived symbols' parent symbols to their +/// underlying regions. This is used to efficiently check whether a symbol is +/// tainted when it represents a sub-region of a tainted symbol. +struct DerivedSymTaint {}; +typedef llvm::ImmutableMap DerivedSymTaintImpl; +template<> struct ProgramStateTrait + : public ProgramStatePartialTrait { + static void *GDMIndex() { static int index; return &index; } +}; + class TaintManager { TaintManager() {} diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp index c468c1bb4b5f..f65fb5b9232a 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp @@ -578,8 +578,7 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitBlock(FinalBB); CurCoro.Data->CurrentAwaitKind = AwaitKind::Final; EmitStmt(S.getFinalSuspendStmt()); - } - else { + } else { // We don't need FinalBB. Emit it to make sure the block is deleted. EmitBlock(FinalBB, /*IsFinished=*/true); } diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp index d660638a1e8a..01f7ca8aba9b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp @@ -1036,8 +1036,6 @@ static void checkAndSanitizeDiags(SmallVectorImpl & bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, std::unique_ptr OverrideMainBuffer, IntrusiveRefCntPtr VFS) { - SavedMainFileBuffer.reset(); - if (!Invocation) return true; @@ -1090,17 +1088,11 @@ bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, Clang->createFileManager(); FileMgr = &Clang->getFileManager(); } + + ResetForParse(); + SourceMgr = new SourceManager(getDiagnostics(), *FileMgr, UserFilesAreVolatile); - TheSema.reset(); - Ctx = nullptr; - PP = nullptr; - Reader = nullptr; - - // Clear out old caches and data. - TopLevelDecls.clear(); - clearFileLevelDecls(); - if (!OverrideMainBuffer) { checkAndRemoveNonDriverDiags(StoredDiagnostics); TopLevelDeclsInPreamble.clear(); @@ -1999,6 +1991,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; + PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0; // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; @@ -2115,6 +2108,19 @@ bool ASTUnit::Reparse(std::shared_ptr PCHContainerOps, return Result; } +void ASTUnit::ResetForParse() { + SavedMainFileBuffer.reset(); + + SourceMgr.reset(); + TheSema.reset(); + Ctx.reset(); + PP.reset(); + Reader.reset(); + + TopLevelDecls.clear(); + clearFileLevelDecls(); +} + //----------------------------------------------------------------------------// // Code completion //----------------------------------------------------------------------------// diff --git a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp index 7f88c919e24a..b5a5acd8ad9a 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -506,7 +506,7 @@ void SDiagsWriter::EmitBlockInfoBlock() { Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size. - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time. + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modification time. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text. Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, diff --git a/contrib/llvm/tools/clang/lib/Headers/altivec.h b/contrib/llvm/tools/clang/lib/Headers/altivec.h index 957fd5f65e26..90fd477d9b98 100644 --- a/contrib/llvm/tools/clang/lib/Headers/altivec.h +++ b/contrib/llvm/tools/clang/lib/Headers/altivec.h @@ -2887,87 +2887,79 @@ static __inline__ vector double __ATTRS_o_ai vec_cpsgn(vector double __a, /* vec_ctf */ -static __inline__ vector float __ATTRS_o_ai vec_ctf(vector int __a, int __b) { - return __builtin_altivec_vcfsx(__a, __b); -} - -static __inline__ vector float __ATTRS_o_ai vec_ctf(vector unsigned int __a, - int __b) { - return __builtin_altivec_vcfux((vector int)__a, __b); -} - #ifdef __VSX__ -static __inline__ vector double __ATTRS_o_ai -vec_ctf(vector unsigned long long __a, int __b) { - vector double __ret = __builtin_convertvector(__a, vector double); - __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52); - return __ret; -} - -static __inline__ vector double __ATTRS_o_ai -vec_ctf(vector signed long long __a, int __b) { - vector double __ret = __builtin_convertvector(__a, vector double); - __ret *= (vector double)(vector unsigned long long)((0x3ffULL - __b) << 52); - return __ret; -} +#define vec_ctf(__a, __b) \ + _Generic((__a), vector int \ + : (vector float)__builtin_altivec_vcfsx((__a), (__b)), \ + vector unsigned int \ + : (vector float)__builtin_altivec_vcfux((vector int)(__a), (__b)), \ + vector unsigned long long \ + : (__builtin_convertvector((vector unsigned long long)(__a), \ + vector double) * \ + (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \ + << 52)), \ + vector signed long long \ + : (__builtin_convertvector((vector signed long long)(__a), \ + vector double) * \ + (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \ + << 52))) +#else +#define vec_ctf(__a, __b) \ + _Generic((__a), vector int \ + : (vector float)__builtin_altivec_vcfsx((__a), (__b)), \ + vector unsigned int \ + : (vector float)__builtin_altivec_vcfux((vector int)(__a), (__b))) #endif /* vec_vcfsx */ -static __inline__ vector float __attribute__((__always_inline__)) -vec_vcfsx(vector int __a, int __b) { - return __builtin_altivec_vcfsx(__a, __b); -} +#define vec_vcfux __builtin_altivec_vcfux /* vec_vcfux */ -static __inline__ vector float __attribute__((__always_inline__)) -vec_vcfux(vector unsigned int __a, int __b) { - return __builtin_altivec_vcfux((vector int)__a, __b); -} +#define vec_vcfsx(__a, __b) __builtin_altivec_vcfsx((vector int)(__a), (__b)) /* vec_cts */ -static __inline__ vector int __ATTRS_o_ai vec_cts(vector float __a, int __b) { - return __builtin_altivec_vctsxs(__a, __b); -} - #ifdef __VSX__ -static __inline__ vector signed long long __ATTRS_o_ai -vec_cts(vector double __a, int __b) { - __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52); - return __builtin_convertvector(__a, vector signed long long); -} +#define vec_cts(__a, __b) \ + _Generic((__a), vector float \ + : __builtin_altivec_vctsxs((__a), (__b)), vector double \ + : __extension__({ \ + vector double __ret = \ + (__a) * \ + (vector double)(vector unsigned long long)((0x3ffULL + (__b)) \ + << 52); \ + __builtin_convertvector(__ret, vector signed long long); \ + })) +#else +#define vec_cts __builtin_altivec_vctsxs #endif /* vec_vctsxs */ -static __inline__ vector int __attribute__((__always_inline__)) -vec_vctsxs(vector float __a, int __b) { - return __builtin_altivec_vctsxs(__a, __b); -} +#define vec_vctsxs __builtin_altivec_vctsxs /* vec_ctu */ -static __inline__ vector unsigned int __ATTRS_o_ai vec_ctu(vector float __a, - int __b) { - return __builtin_altivec_vctuxs(__a, __b); -} - #ifdef __VSX__ -static __inline__ vector unsigned long long __ATTRS_o_ai -vec_ctu(vector double __a, int __b) { - __a *= (vector double)(vector unsigned long long)((0x3ffULL + __b) << 52); - return __builtin_convertvector(__a, vector unsigned long long); -} +#define vec_ctu(__a, __b) \ + _Generic((__a), vector float \ + : __builtin_altivec_vctuxs((__a), (__b)), vector double \ + : __extension__({ \ + vector double __ret = \ + (__a) * \ + (vector double)(vector unsigned long long)((0x3ffULL + __b) \ + << 52); \ + __builtin_convertvector(__ret, vector unsigned long long); \ + })) +#else +#define vec_ctu __builtin_altivec_vctuxs #endif /* vec_vctuxs */ -static __inline__ vector unsigned int __attribute__((__always_inline__)) -vec_vctuxs(vector float __a, int __b) { - return __builtin_altivec_vctuxs(__a, __b); -} +#define vec_vctuxs __builtin_altivec_vctuxs /* vec_signed */ diff --git a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp index 92942fd09a0c..f5a35e97d6e1 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Lexer.cpp @@ -550,8 +550,6 @@ namespace { enum PreambleDirectiveKind { PDK_Skipped, - PDK_StartIf, - PDK_EndIf, PDK_Unknown }; @@ -574,8 +572,6 @@ std::pair Lexer::ComputePreamble(StringRef Buffer, bool InPreprocessorDirective = false; Token TheTok; - Token IfStartTok; - unsigned IfCount = 0; SourceLocation ActiveCommentLoc; unsigned MaxLineOffset = 0; @@ -658,33 +654,18 @@ std::pair Lexer::ComputePreamble(StringRef Buffer, .Case("sccs", PDK_Skipped) .Case("assert", PDK_Skipped) .Case("unassert", PDK_Skipped) - .Case("if", PDK_StartIf) - .Case("ifdef", PDK_StartIf) - .Case("ifndef", PDK_StartIf) + .Case("if", PDK_Skipped) + .Case("ifdef", PDK_Skipped) + .Case("ifndef", PDK_Skipped) .Case("elif", PDK_Skipped) .Case("else", PDK_Skipped) - .Case("endif", PDK_EndIf) + .Case("endif", PDK_Skipped) .Default(PDK_Unknown); switch (PDK) { case PDK_Skipped: continue; - case PDK_StartIf: - if (IfCount == 0) - IfStartTok = HashTok; - - ++IfCount; - continue; - - case PDK_EndIf: - // Mismatched #endif. The preamble ends here. - if (IfCount == 0) - break; - - --IfCount; - continue; - case PDK_Unknown: // We don't know what this directive is; stop at the '#'. break; @@ -705,16 +686,13 @@ std::pair Lexer::ComputePreamble(StringRef Buffer, } while (true); SourceLocation End; - if (IfCount) - End = IfStartTok.getLocation(); - else if (ActiveCommentLoc.isValid()) + if (ActiveCommentLoc.isValid()) End = ActiveCommentLoc; // don't truncate a decl comment. else End = TheTok.getLocation(); return std::make_pair(End.getRawEncoding() - StartLoc.getRawEncoding(), - IfCount? IfStartTok.isAtStartOfLine() - : TheTok.isAtStartOfLine()); + TheTok.isAtStartOfLine()); } /// AdvanceToTokenCharacter - Given a location that specifies the start of a @@ -2570,6 +2548,11 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) { return true; } + if (PP->isRecordingPreamble() && !PP->isInMainFile()) { + PP->setRecordedPreambleConditionalStack(ConditionalStack); + ConditionalStack.clear(); + } + // Issue diagnostics for unterminated #if and missing newline. // If we are in a #if directive, emit an error. diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 030717b8bd5c..8b5877934f61 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -1906,6 +1906,25 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } + // The #included file will be considered to be a system header if either it is + // in a system include directory, or if the #includer is a system include + // header. + SrcMgr::CharacteristicKind FileCharacter = + SourceMgr.getFileCharacteristic(FilenameTok.getLocation()); + if (File) + FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter); + + // Ask HeaderInfo if we should enter this #include file. If not, #including + // this file will have no effect. + bool SkipHeader = false; + if (ShouldEnter && File && + !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, + getLangOpts().Modules, + SuggestedModule.getModule())) { + ShouldEnter = false; + SkipHeader = true; + } + if (Callbacks) { // Notify the callback object that we've seen an inclusion directive. Callbacks->InclusionDirective( @@ -1913,18 +1932,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, FilenameRange, File, SearchPath, RelativePath, ShouldEnter ? nullptr : SuggestedModule.getModule()); + if (SkipHeader && !SuggestedModule.getModule()) + Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); } if (!File) return; - // The #included file will be considered to be a system header if either it is - // in a system include directory, or if the #includer is a system include - // header. - SrcMgr::CharacteristicKind FileCharacter = - std::max(HeaderInfo.getFileDirFlavor(File), - SourceMgr.getFileCharacteristic(FilenameTok.getLocation())); - // FIXME: If we have a suggested module, and we've already visited this file, // don't bother entering it again. We know it has no further effect. @@ -1964,19 +1978,6 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, } } - // Ask HeaderInfo if we should enter this #include file. If not, #including - // this file will have no effect. - bool SkipHeader = false; - if (ShouldEnter && - !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, - getLangOpts().Modules, - SuggestedModule.getModule())) { - ShouldEnter = false; - SkipHeader = true; - if (Callbacks) - Callbacks->FileSkipped(*File, FilenameTok, FileCharacter); - } - // If we don't need to enter the file, stop now. if (!ShouldEnter) { // If this is a module import, make it visible if needed. diff --git a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp index 5a589d6a17b3..1c0cd5636835 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp @@ -46,6 +46,12 @@ bool Preprocessor::isInPrimaryFile() const { }); } +bool Preprocessor::isInMainFile() const { + if (IsFileLexer()) + return IncludeMacroStack.size() == 0; + return true; +} + /// getCurrentLexer - Return the current file lexer being lexed from. Note /// that this ignores any potentially active macro expansions and _Pragma /// expansions going on at the time. diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index 2d078a4e7603..e1d981527bec 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -1407,6 +1407,24 @@ struct PragmaModuleBeginHandler : public PragmaHandler { M = NewM; } + // If the module isn't available, it doesn't make sense to enter it. + if (!M->isAvailable()) { + Module::Requirement Requirement; + Module::UnresolvedHeaderDirective MissingHeader; + (void)M->isAvailable(PP.getLangOpts(), PP.getTargetInfo(), + Requirement, MissingHeader); + if (MissingHeader.FileNameLoc.isValid()) { + PP.Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + } else { + PP.Diag(M->DefinitionLoc, diag::err_module_unavailable) + << M->getFullModuleName() << Requirement.second << Requirement.first; + } + PP.Diag(BeginLoc, diag::note_pp_module_begin_here) + << M->getTopLevelModuleName(); + return; + } + // Enter the scope of the submodule. PP.EnterSubmodule(M, BeginLoc, /*ForPragma*/true); PP.EnterAnnotationToken(SourceRange(BeginLoc, ModuleName.back().second), diff --git a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp index dce8c1efda23..3596337c245e 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp @@ -150,6 +150,9 @@ Preprocessor::Preprocessor(std::shared_ptr PPOpts, Ident_GetExceptionInfo = Ident_GetExceptionCode = nullptr; Ident_AbnormalTermination = nullptr; } + + if (this->PPOpts->GeneratePreamble) + PreambleConditionalStack.startRecording(); } Preprocessor::~Preprocessor() { @@ -532,6 +535,12 @@ void Preprocessor::EnterMainSourceFile() { // Start parsing the predefines. EnterSourceFile(FID, nullptr, SourceLocation()); + + // Restore the conditional stack from the preamble, if there is one. + if (PreambleConditionalStack.isReplaying()) { + CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack()); + PreambleConditionalStack.doneReplaying(); + } } void Preprocessor::EndSourceFile() { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index 96fd952c81c7..a9adbec4f842 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -12509,6 +12509,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, unsigned diag_id; if (II.getName().startswith("__builtin_")) diag_id = diag::warn_builtin_unknown; + // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. + else if (getLangOpts().OpenCL) + diag_id = diag::err_opencl_implicit_function_decl; else if (getLangOpts().C99) diag_id = diag::ext_implicit_function_decl; else diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 759c82eeaa07..b1a07ffb7206 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -8074,28 +8074,38 @@ QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, /// rank; for C, Obj-C, and C++ we allow any real scalar conversion except /// for float->int. /// +/// OpenCL V2.0 6.2.6.p2: +/// An error shall occur if any scalar operand type has greater rank +/// than the type of the vector element. +/// /// \param scalar - if non-null, actually perform the conversions /// \return true if the operation fails (but without diagnosing the failure) static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar, QualType scalarTy, QualType vectorEltTy, - QualType vectorTy) { + QualType vectorTy, + unsigned &DiagID) { // The conversion to apply to the scalar before splatting it, // if necessary. CastKind scalarCast = CK_Invalid; if (vectorEltTy->isIntegralType(S.Context)) { - if (!scalarTy->isIntegralType(S.Context)) + if (S.getLangOpts().OpenCL && (scalarTy->isRealFloatingType() || + (scalarTy->isIntegerType() && + S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0))) { + DiagID = diag::err_opencl_scalar_type_rank_greater_than_vector_type; return true; - if (S.getLangOpts().OpenCL && - S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0) + } + if (!scalarTy->isIntegralType(S.Context)) return true; scalarCast = CK_IntegralCast; } else if (vectorEltTy->isRealFloatingType()) { if (scalarTy->isRealFloatingType()) { if (S.getLangOpts().OpenCL && - S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy) < 0) + S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy) < 0) { + DiagID = diag::err_opencl_scalar_type_rank_greater_than_vector_type; return true; + } scalarCast = CK_FloatingCast; } else if (scalarTy->isIntegralType(S.Context)) @@ -8341,10 +8351,12 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, // If there's a vector type and a scalar, try to convert the scalar to // the vector element type and splat. + unsigned DiagID = diag::err_typecheck_vector_not_convertable; if (!RHSVecType) { if (isa(LHSVecType)) { if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, - LHSVecType->getElementType(), LHSType)) + LHSVecType->getElementType(), LHSType, + DiagID)) return LHSType; } else { if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS)) @@ -8355,7 +8367,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, if (isa(RHSVecType)) { if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), LHSType, RHSVecType->getElementType(), - RHSType)) + RHSType, DiagID)) return RHSType; } else { if (LHS.get()->getValueKind() == VK_LValue || @@ -8431,7 +8443,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, } // Otherwise, use the generic diagnostic. - Diag(Loc, diag::err_typecheck_vector_not_convertable) + Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); return QualType(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp index 43fd055bbc56..2b7733d2adbd 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp @@ -5929,16 +5929,17 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective( B, DSAStack->isCancelRegion()); } -/// \brief Check for existence of a map clause in the list of clauses. -static bool HasMapClause(ArrayRef Clauses) { - for (ArrayRef::iterator I = Clauses.begin(), E = Clauses.end(); - I != E; ++I) { - if (*I != nullptr && (*I)->getClauseKind() == OMPC_map) { - return true; - } - } +/// Check for existence of a map clause in the list of clauses. +static bool hasClauses(ArrayRef Clauses, + const OpenMPClauseKind K) { + return llvm::any_of( + Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; }); +} - return false; +template +static bool hasClauses(ArrayRef Clauses, const OpenMPClauseKind K, + const Params... ClauseTypes) { + return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...); } StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef Clauses, @@ -5952,8 +5953,9 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef Clauses, // OpenMP [2.10.1, Restrictions, p. 97] // At least one map clause must appear on the directive. - if (!HasMapClause(Clauses)) { - Diag(StartLoc, diag::err_omp_no_map_for_directive) + if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr)) { + Diag(StartLoc, diag::err_omp_no_clause_for_directive) + << "'map' or 'use_device_ptr'" << getOpenMPDirectiveName(OMPD_target_data); return StmtError(); } @@ -5970,9 +5972,9 @@ Sema::ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses, SourceLocation EndLoc) { // OpenMP [2.10.2, Restrictions, p. 99] // At least one map clause must appear on the directive. - if (!HasMapClause(Clauses)) { - Diag(StartLoc, diag::err_omp_no_map_for_directive) - << getOpenMPDirectiveName(OMPD_target_enter_data); + if (!hasClauses(Clauses, OMPC_map)) { + Diag(StartLoc, diag::err_omp_no_clause_for_directive) + << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data); return StmtError(); } @@ -5986,9 +5988,9 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, SourceLocation EndLoc) { // OpenMP [2.10.3, Restrictions, p. 102] // At least one map clause must appear on the directive. - if (!HasMapClause(Clauses)) { - Diag(StartLoc, diag::err_omp_no_map_for_directive) - << getOpenMPDirectiveName(OMPD_target_exit_data); + if (!hasClauses(Clauses, OMPC_map)) { + Diag(StartLoc, diag::err_omp_no_clause_for_directive) + << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data); return StmtError(); } @@ -5998,12 +6000,7 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { - bool seenMotionClause = false; - for (auto *C : Clauses) { - if (C->getClauseKind() == OMPC_to || C->getClauseKind() == OMPC_from) - seenMotionClause = true; - } - if (!seenMotionClause) { + if (!hasClauses(Clauses, OMPC_to, OMPC_from)) { Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required); return StmtError(); } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index 55cb670f427e..b7bbb9dc7be1 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -2925,6 +2925,21 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { } break; + case PP_CONDITIONAL_STACK: + if (!Record.empty()) { + SmallVector ConditionalStack; + for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) { + auto Loc = ReadSourceLocation(F, Record, Idx); + bool WasSkipping = Record[Idx++]; + bool FoundNonSkip = Record[Idx++]; + bool FoundElse = Record[Idx++]; + ConditionalStack.push_back( + {Loc, WasSkipping, FoundNonSkip, FoundElse}); + } + PP.setReplayablePreambleConditionalStack(ConditionalStack); + } + break; + case PP_COUNTER_VALUE: if (!Record.empty() && Listener) Listener->ReadCounter(F, Record[0]); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index b3556371c9b8..c931b13f65f3 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -1093,6 +1093,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES); RECORD(DELETE_EXPRS_TO_ANALYZE); RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH); + RECORD(PP_CONDITIONAL_STACK); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -2302,6 +2303,18 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { Stream.EmitRecord(PP_COUNTER_VALUE, Record); } + if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) { + assert(!IsModule); + for (const auto &Cond : PP.getPreambleConditionalStack()) { + AddSourceLocation(Cond.IfLoc, Record); + Record.push_back(Cond.WasSkipping); + Record.push_back(Cond.FoundNonSkip); + Record.push_back(Cond.FoundElse); + } + Stream.EmitRecord(PP_CONDITIONAL_STACK, Record); + Record.clear(); + } + // Enter the preprocessor block. Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index b1a54e77951b..883c6a663291 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -65,21 +65,8 @@ class GenericTaintChecker : public Checker< check::PostStmt, /// and thus, is tainted. static bool isStdin(const Expr *E, CheckerContext &C); - /// This is called from getPointedToSymbol() to resolve symbol references for - /// the region underlying a LazyCompoundVal. This is the default binding - /// for the LCV, which could be a conjured symbol from a function call that - /// initialized the region. It only returns the conjured symbol if the LCV - /// covers the entire region, e.g. we avoid false positives by not returning - /// a default bindingc for an entire struct if the symbol for only a single - /// field or element within it is requested. - // TODO: Return an appropriate symbol for sub-fields/elements of an LCV so - // that they are also appropriately tainted. - static SymbolRef getLCVSymbol(CheckerContext &C, - nonloc::LazyCompoundVal &LCV); - - /// \brief Given a pointer argument, get the symbol of the value it contains - /// (points to). - static SymbolRef getPointedToSymbol(CheckerContext &C, const Expr *Arg); + /// \brief Given a pointer argument, return the value it points to. + static Optional getPointedToSVal(CheckerContext &C, const Expr *Arg); /// Functions defining the attack surface. typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *, @@ -186,9 +173,14 @@ class GenericTaintChecker : public Checker< check::PostStmt, static inline bool isTaintedOrPointsToTainted(const Expr *E, ProgramStateRef State, CheckerContext &C) { - return (State->isTainted(E, C.getLocationContext()) || isStdin(E, C) || - (E->getType().getTypePtr()->isPointerType() && - State->isTainted(getPointedToSymbol(C, E)))); + if (State->isTainted(E, C.getLocationContext()) || isStdin(E, C)) + return true; + + if (!E->getType().getTypePtr()->isPointerType()) + return false; + + Optional V = getPointedToSVal(C, E); + return (V && State->isTainted(*V)); } /// \brief Pre-process a function which propagates taint according to the @@ -400,9 +392,9 @@ bool GenericTaintChecker::propagateFromPre(const CallExpr *CE, if (CE->getNumArgs() < (ArgNum + 1)) return false; const Expr* Arg = CE->getArg(ArgNum); - SymbolRef Sym = getPointedToSymbol(C, Arg); - if (Sym) - State = State->addTaint(Sym); + Optional V = getPointedToSVal(C, Arg); + if (V) + State = State->addTaint(*V); } // Clear up the taint info from the state. @@ -473,47 +465,20 @@ bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{ return false; } -SymbolRef GenericTaintChecker::getLCVSymbol(CheckerContext &C, - nonloc::LazyCompoundVal &LCV) { - StoreManager &StoreMgr = C.getStoreManager(); - - // getLCVSymbol() is reached in a PostStmt so we can always expect a default - // binding to exist if one is present. - if (Optional binding = StoreMgr.getDefaultBinding(LCV)) { - SymbolRef Sym = binding->getAsSymbol(); - if (!Sym) - return nullptr; - - // If the LCV covers an entire base region return the default conjured symbol. - if (LCV.getRegion() == LCV.getRegion()->getBaseRegion()) - return Sym; - } - - // Otherwise, return a nullptr as there's not yet a functional way to taint - // sub-regions of LCVs. - return nullptr; -} - -SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C, - const Expr* Arg) { +Optional GenericTaintChecker::getPointedToSVal(CheckerContext &C, + const Expr* Arg) { ProgramStateRef State = C.getState(); SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext()); if (AddrVal.isUnknownOrUndef()) - return nullptr; + return None; Optional AddrLoc = AddrVal.getAs(); if (!AddrLoc) - return nullptr; + return None; const PointerType *ArgTy = dyn_cast(Arg->getType().getCanonicalType().getTypePtr()); - SVal Val = State->getSVal(*AddrLoc, - ArgTy ? ArgTy->getPointeeType(): QualType()); - - if (auto LCV = Val.getAs()) - return getLCVSymbol(C, *LCV); - - return Val.getAsSymbol(); + return State->getSVal(*AddrLoc, ArgTy ? ArgTy->getPointeeType(): QualType()); } ProgramStateRef @@ -633,9 +598,9 @@ ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE, // The arguments are pointer arguments. The data they are pointing at is // tainted after the call. const Expr* Arg = CE->getArg(i); - SymbolRef Sym = getPointedToSymbol(C, Arg); - if (Sym) - State = State->addTaint(Sym); + Optional V = getPointedToSVal(C, Arg); + if (V) + State = State->addTaint(*V); } return State; } @@ -710,10 +675,10 @@ bool GenericTaintChecker::generateReportIfTainted(const Expr *E, // Check for taint. ProgramStateRef State = C.getState(); - const SymbolRef PointedToSym = getPointedToSymbol(C, E); + Optional PointedToSVal = getPointedToSVal(C, E); SVal TaintedSVal; - if (State->isTainted(PointedToSym)) - TaintedSVal = nonloc::SymbolVal(PointedToSym); + if (PointedToSVal && State->isTainted(*PointedToSVal)) + TaintedSVal = *PointedToSVal; else if (State->isTainted(E, C.getLocationContext())) TaintedSVal = C.getSVal(E); else diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp new file mode 100644 index 000000000000..0f9b749506fa --- /dev/null +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -0,0 +1,833 @@ +//===-- IteratorChecker.cpp ---------------------------------------*- C++ -*--// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a checker for using iterators outside their range (past end). Usage +// means here dereferencing, incrementing etc. +// +//===----------------------------------------------------------------------===// +// +// In the code, iterator can be represented as a: +// * type-I: typedef-ed pointer. Operations over such iterator, such as +// comparisons or increments, are modeled straightforwardly by the +// analyzer. +// * type-II: structure with its method bodies available. Operations over such +// iterator are inlined by the analyzer, and results of modeling +// these operations are exposing implementation details of the +// iterators, which is not necessarily helping. +// * type-III: completely opaque structure. Operations over such iterator are +// modeled conservatively, producing conjured symbols everywhere. +// +// To handle all these types in a common way we introduce a structure called +// IteratorPosition which is an abstraction of the position the iterator +// represents using symbolic expressions. The checker handles all the +// operations on this structure. +// +// Additionally, depending on the circumstances, operators of types II and III +// can be represented as: +// * type-IIa, type-IIIa: conjured structure symbols - when returned by value +// from conservatively evaluated methods such as +// `.begin()`. +// * type-IIb, type-IIIb: memory regions of iterator-typed objects, such as +// variables or temporaries, when the iterator object is +// currently treated as an lvalue. +// * type-IIc, type-IIIc: compound values of iterator-typed objects, when the +// iterator object is treated as an rvalue taken of a +// particular lvalue, eg. a copy of "type-a" iterator +// object, or an iterator that existed before the +// analysis has started. +// +// To handle any of these three different representations stored in an SVal we +// use setter and getters functions which separate the three cases. To store +// them we use a pointer union of symbol and memory region. +// +// The checker works the following way: We record the past-end iterator for +// all containers whenever their `.end()` is called. Since the Constraint +// Manager cannot handle SVals we need to take over its role. We post-check +// equality and non-equality comparisons and propagate the position of the +// iterator to the other side of the comparison if it is past-end and we are in +// the 'equal' branch (true-branch for `==` and false-branch for `!=`). +// +// In case of type-I or type-II iterators we get a concrete integer as a result +// of the comparison (1 or 0) but in case of type-III we only get a Symbol. In +// this latter case we record the symbol and reload it in evalAssume() and do +// the propagation there. We also handle (maybe double) negated comparisons +// which are represented in the form of (x == 0 or x !=0 ) where x is the +// comparison itself. + +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" + +using namespace clang; +using namespace ento; + +namespace { + +// Abstract position of an iterator. This helps to handle all three kinds +// of operators in a common way by using a symbolic position. +struct IteratorPosition { +private: + + // Container the iterator belongs to + const MemRegion *Cont; + + // Abstract offset + SymbolRef Offset; + + IteratorPosition(const MemRegion *C, SymbolRef Of) + : Cont(C), Offset(Of) {} + +public: + const MemRegion *getContainer() const { return Cont; } + SymbolRef getOffset() const { return Offset; } + + static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of) { + return IteratorPosition(C, Of); + } + + IteratorPosition setTo(SymbolRef NewOf) const { + return IteratorPosition(Cont, NewOf); + } + + bool operator==(const IteratorPosition &X) const { + return Cont == X.Cont && Offset == X.Offset; + } + + bool operator!=(const IteratorPosition &X) const { + return Cont != X.Cont || Offset != X.Offset; + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(Cont); + ID.Add(Offset); + } +}; + +typedef llvm::PointerUnion RegionOrSymbol; + +// Structure to record the symbolic end position of a container +struct ContainerData { +private: + SymbolRef End; + + ContainerData(SymbolRef E) : End(E) {} + +public: + static ContainerData fromEnd(SymbolRef E) { + return ContainerData(E); + } + + SymbolRef getEnd() const { return End; } + + ContainerData newEnd(SymbolRef E) const { return ContainerData(E); } + + bool operator==(const ContainerData &X) const { + return End == X.End; + } + + bool operator!=(const ContainerData &X) const { + return End != X.End; + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.Add(End); + } +}; + +// Structure fo recording iterator comparisons. We needed to retrieve the +// original comparison expression in assumptions. +struct IteratorComparison { +private: + RegionOrSymbol Left, Right; + bool Equality; + +public: + IteratorComparison(RegionOrSymbol L, RegionOrSymbol R, bool Eq) + : Left(L), Right(R), Equality(Eq) {} + + RegionOrSymbol getLeft() const { return Left; } + RegionOrSymbol getRight() const { return Right; } + bool isEquality() const { return Equality; } + bool operator==(const IteratorComparison &X) const { + return Left == X.Left && Right == X.Right && Equality == X.Equality; + } + bool operator!=(const IteratorComparison &X) const { + return Left != X.Left || Right != X.Right || Equality != X.Equality; + } + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Equality); } +}; + +class IteratorChecker + : public Checker, + check::DeadSymbols, + eval::Assume> { + + std::unique_ptr OutOfRangeBugType; + + void handleComparison(CheckerContext &C, const SVal &RetVal, const SVal &LVal, + const SVal &RVal, OverloadedOperatorKind Op) const; + void verifyDereference(CheckerContext &C, const SVal &Val) const; + void handleEnd(CheckerContext &C, const Expr *CE, const SVal &RetVal, + const SVal &Cont) const; + void assignToContainer(CheckerContext &C, const Expr *CE, const SVal &RetVal, + const MemRegion *Cont) const; + void reportOutOfRangeBug(const StringRef &Message, const SVal &Val, + CheckerContext &C, ExplodedNode *ErrNode) const; + +public: + IteratorChecker(); + + enum CheckKind { + CK_IteratorRangeChecker, + CK_NumCheckKinds + }; + + DefaultBool ChecksEnabled[CK_NumCheckKinds]; + CheckName CheckNames[CK_NumCheckKinds]; + + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; + void checkPostStmt(const MaterializeTemporaryExpr *MTE, + CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; + ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond, + bool Assumption) const; +}; +} // namespace + +REGISTER_MAP_WITH_PROGRAMSTATE(IteratorSymbolMap, SymbolRef, IteratorPosition) +REGISTER_MAP_WITH_PROGRAMSTATE(IteratorRegionMap, const MemRegion *, + IteratorPosition) + +REGISTER_MAP_WITH_PROGRAMSTATE(ContainerMap, const MemRegion *, ContainerData) + +REGISTER_MAP_WITH_PROGRAMSTATE(IteratorComparisonMap, const SymExpr *, + IteratorComparison) + +namespace { + +bool isIteratorType(const QualType &Type); +bool isIterator(const CXXRecordDecl *CRD); +bool isEndCall(const FunctionDecl *Func); +bool isSimpleComparisonOperator(OverloadedOperatorKind OK); +bool isDereferenceOperator(OverloadedOperatorKind OK); +BinaryOperator::Opcode getOpcode(const SymExpr *SE); +const RegionOrSymbol getRegionOrSymbol(const SVal &Val); +const ProgramStateRef processComparison(ProgramStateRef State, + RegionOrSymbol LVal, + RegionOrSymbol RVal, bool Equal); +const ProgramStateRef saveComparison(ProgramStateRef State, + const SymExpr *Condition, const SVal &LVal, + const SVal &RVal, bool Eq); +const IteratorComparison *loadComparison(ProgramStateRef State, + const SymExpr *Condition); +SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont); +ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, + const SymbolRef Sym); +const IteratorPosition *getIteratorPosition(ProgramStateRef State, + const SVal &Val); +const IteratorPosition *getIteratorPosition(ProgramStateRef State, + RegionOrSymbol RegOrSym); +ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, + const IteratorPosition &Pos); +ProgramStateRef setIteratorPosition(ProgramStateRef State, + RegionOrSymbol RegOrSym, + const IteratorPosition &Pos); +ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val); +ProgramStateRef adjustIteratorPosition(ProgramStateRef State, + RegionOrSymbol RegOrSym, + const IteratorPosition &Pos, bool Equal); +ProgramStateRef relateIteratorPositions(ProgramStateRef State, + const IteratorPosition &Pos1, + const IteratorPosition &Pos2, + bool Equal); +const ContainerData *getContainerData(ProgramStateRef State, + const MemRegion *Cont); +ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont, + const ContainerData &CData); +bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos); +} // namespace + +IteratorChecker::IteratorChecker() { + OutOfRangeBugType.reset( + new BugType(this, "Iterator out of range", "Misuse of STL APIs")); + OutOfRangeBugType->setSuppressOnSink(true); +} + +void IteratorChecker::checkPreCall(const CallEvent &Call, + CheckerContext &C) const { + // Check for out of range access + const auto *Func = dyn_cast_or_null(Call.getDecl()); + if (!Func) + return; + + if (Func->isOverloadedOperator()) { + if (ChecksEnabled[CK_IteratorRangeChecker] && + isDereferenceOperator(Func->getOverloadedOperator())) { + // Check for dereference of out-of-range iterators + if (const auto *InstCall = dyn_cast(&Call)) { + verifyDereference(C, InstCall->getCXXThisVal()); + } else { + verifyDereference(C, Call.getArgSVal(0)); + } + } + } +} + +void IteratorChecker::checkPostCall(const CallEvent &Call, + CheckerContext &C) const { + // Record new iterator positions and iterator position changes + const auto *Func = dyn_cast_or_null(Call.getDecl()); + if (!Func) + return; + + if (Func->isOverloadedOperator()) { + const auto Op = Func->getOverloadedOperator(); + if (isSimpleComparisonOperator(Op)) { + if (const auto *InstCall = dyn_cast(&Call)) { + handleComparison(C, Call.getReturnValue(), InstCall->getCXXThisVal(), + Call.getArgSVal(0), Op); + } else { + handleComparison(C, Call.getReturnValue(), Call.getArgSVal(0), + Call.getArgSVal(1), Op); + } + } + } else { + const auto *OrigExpr = Call.getOriginExpr(); + if (!OrigExpr) + return; + + if (!isIteratorType(Call.getResultType())) + return; + + auto State = C.getState(); + // Already bound to container? + if (getIteratorPosition(State, Call.getReturnValue())) + return; + + if (const auto *InstCall = dyn_cast(&Call)) { + if (isEndCall(Func)) { + handleEnd(C, OrigExpr, Call.getReturnValue(), + InstCall->getCXXThisVal()); + return; + } + } + + // Copy-like and move constructors + if (isa(&Call) && Call.getNumArgs() == 1) { + if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) { + State = setIteratorPosition(State, Call.getReturnValue(), *Pos); + if (cast(Func)->isMoveConstructor()) { + State = removeIteratorPosition(State, Call.getArgSVal(0)); + } + C.addTransition(State); + return; + } + } + + // Assumption: if return value is an iterator which is not yet bound to a + // container, then look for the first iterator argument, and + // bind the return value to the same container. This approach + // works for STL algorithms. + // FIXME: Add a more conservative mode + for (unsigned i = 0; i < Call.getNumArgs(); ++i) { + if (isIteratorType(Call.getArgExpr(i)->getType())) { + if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(i))) { + assignToContainer(C, OrigExpr, Call.getReturnValue(), + Pos->getContainer()); + return; + } + } + } + } +} + +void IteratorChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE, + CheckerContext &C) const { + /* Transfer iterator state to temporary objects */ + auto State = C.getState(); + const auto *LCtx = C.getLocationContext(); + const auto *Pos = + getIteratorPosition(State, State->getSVal(MTE->GetTemporaryExpr(), LCtx)); + if (!Pos) + return; + State = setIteratorPosition(State, State->getSVal(MTE, LCtx), *Pos); + C.addTransition(State); +} + +void IteratorChecker::checkDeadSymbols(SymbolReaper &SR, + CheckerContext &C) const { + // Cleanup + auto State = C.getState(); + + auto RegionMap = State->get(); + for (const auto Reg : RegionMap) { + if (!SR.isLiveRegion(Reg.first)) { + State = State->remove(Reg.first); + } + } + + auto SymbolMap = State->get(); + for (const auto Sym : SymbolMap) { + if (!SR.isLive(Sym.first)) { + State = State->remove(Sym.first); + } + } + + auto ContMap = State->get(); + for (const auto Cont : ContMap) { + if (!SR.isLiveRegion(Cont.first)) { + State = State->remove(Cont.first); + } + } + + auto ComparisonMap = State->get(); + for (const auto Comp : ComparisonMap) { + if (!SR.isLive(Comp.first)) { + State = State->remove(Comp.first); + } + } +} + +ProgramStateRef IteratorChecker::evalAssume(ProgramStateRef State, SVal Cond, + bool Assumption) const { + // Load recorded comparison and transfer iterator state between sides + // according to comparison operator and assumption + const auto *SE = Cond.getAsSymExpr(); + if (!SE) + return State; + + auto Opc = getOpcode(SE); + if (Opc != BO_EQ && Opc != BO_NE) + return State; + + bool Negated = false; + const auto *Comp = loadComparison(State, SE); + if (!Comp) { + // Try negated comparison, which is a SymExpr to 0 integer comparison + const auto *SIE = dyn_cast(SE); + if (!SIE) + return State; + + if (SIE->getRHS() != 0) + return State; + + SE = SIE->getLHS(); + Negated = SIE->getOpcode() == BO_EQ; // Equal to zero means negation + Opc = getOpcode(SE); + if (Opc != BO_EQ && Opc != BO_NE) + return State; + + Comp = loadComparison(State, SE); + if (!Comp) + return State; + } + + return processComparison(State, Comp->getLeft(), Comp->getRight(), + (Comp->isEquality() == Assumption) != Negated); +} + +void IteratorChecker::handleComparison(CheckerContext &C, const SVal &RetVal, + const SVal &LVal, const SVal &RVal, + OverloadedOperatorKind Op) const { + // Record the operands and the operator of the comparison for the next + // evalAssume, if the result is a symbolic expression. If it is a concrete + // value (only one branch is possible), then transfer the state between + // the operands according to the operator and the result + auto State = C.getState(); + if (const auto *Condition = RetVal.getAsSymbolicExpression()) { + const auto *LPos = getIteratorPosition(State, LVal); + const auto *RPos = getIteratorPosition(State, RVal); + if (!LPos && !RPos) + return; + State = saveComparison(State, Condition, LVal, RVal, Op == OO_EqualEqual); + C.addTransition(State); + } else if (const auto TruthVal = RetVal.getAs()) { + if ((State = processComparison( + State, getRegionOrSymbol(LVal), getRegionOrSymbol(RVal), + (Op == OO_EqualEqual) == (TruthVal->getValue() != 0)))) { + C.addTransition(State); + } else { + C.generateSink(State, C.getPredecessor()); + } + } +} + +void IteratorChecker::verifyDereference(CheckerContext &C, + const SVal &Val) const { + auto State = C.getState(); + const auto *Pos = getIteratorPosition(State, Val); + if (Pos && isOutOfRange(State, *Pos)) { + // If I do not put a tag here, some range tests will fail + static CheckerProgramPointTag Tag("IteratorRangeChecker", + "IteratorOutOfRange"); + auto *N = C.generateNonFatalErrorNode(State, &Tag); + if (!N) { + return; + } + reportOutOfRangeBug("Iterator accessed outside of its range.", Val, C, N); + } +} + +void IteratorChecker::handleEnd(CheckerContext &C, const Expr *CE, + const SVal &RetVal, const SVal &Cont) const { + const auto *ContReg = Cont.getAsRegion(); + if (!ContReg) + return; + + while (const auto *CBOR = ContReg->getAs()) { + ContReg = CBOR->getSuperRegion(); + } + + // If the container already has an end symbol then use it. Otherwise first + // create a new one. + auto State = C.getState(); + auto EndSym = getContainerEnd(State, ContReg); + if (!EndSym) { + auto &SymMgr = C.getSymbolManager(); + EndSym = SymMgr.conjureSymbol(CE, C.getLocationContext(), + C.getASTContext().LongTy, C.blockCount()); + State = createContainerEnd(State, ContReg, EndSym); + } + State = setIteratorPosition(State, RetVal, + IteratorPosition::getPosition(ContReg, EndSym)); + C.addTransition(State); +} + +void IteratorChecker::assignToContainer(CheckerContext &C, const Expr *CE, + const SVal &RetVal, + const MemRegion *Cont) const { + while (const auto *CBOR = Cont->getAs()) { + Cont = CBOR->getSuperRegion(); + } + + auto State = C.getState(); + auto &SymMgr = C.getSymbolManager(); + auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(), + C.getASTContext().LongTy, C.blockCount()); + State = setIteratorPosition(State, RetVal, + IteratorPosition::getPosition(Cont, Sym)); + C.addTransition(State); +} + +void IteratorChecker::reportOutOfRangeBug(const StringRef &Message, + const SVal &Val, CheckerContext &C, + ExplodedNode *ErrNode) const { + auto R = llvm::make_unique(*OutOfRangeBugType, Message, ErrNode); + R->markInteresting(Val); + C.emitReport(std::move(R)); +} + +namespace { + +bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2); +bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, + BinaryOperator::Opcode Opc); + +bool isIteratorType(const QualType &Type) { + if (Type->isPointerType()) + return true; + + const auto *CRD = Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl(); + return isIterator(CRD); +} + +bool isIterator(const CXXRecordDecl *CRD) { + if (!CRD) + return false; + + const auto Name = CRD->getName(); + if (!(Name.endswith_lower("iterator") || Name.endswith_lower("iter") || + Name.endswith_lower("it"))) + return false; + + bool HasCopyCtor = false, HasCopyAssign = true, HasDtor = false, + HasPreIncrOp = false, HasPostIncrOp = false, HasDerefOp = false; + for (const auto *Method : CRD->methods()) { + if (const auto *Ctor = dyn_cast(Method)) { + if (Ctor->isCopyConstructor()) { + HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() == AS_public; + } + continue; + } + if (const auto *Dtor = dyn_cast(Method)) { + HasDtor = !Dtor->isDeleted() && Dtor->getAccess() == AS_public; + continue; + } + if (Method->isCopyAssignmentOperator()) { + HasCopyAssign = !Method->isDeleted() && Method->getAccess() == AS_public; + continue; + } + if (!Method->isOverloadedOperator()) + continue; + const auto OPK = Method->getOverloadedOperator(); + if (OPK == OO_PlusPlus) { + HasPreIncrOp = HasPreIncrOp || (Method->getNumParams() == 0); + HasPostIncrOp = HasPostIncrOp || (Method->getNumParams() == 1); + continue; + } + if (OPK == OO_Star) { + HasDerefOp = (Method->getNumParams() == 0); + continue; + } + } + + return HasCopyCtor && HasCopyAssign && HasDtor && HasPreIncrOp && + HasPostIncrOp && HasDerefOp; +} + +bool isEndCall(const FunctionDecl *Func) { + const auto *IdInfo = Func->getIdentifier(); + if (!IdInfo) + return false; + return IdInfo->getName().endswith_lower("end"); +} + +bool isSimpleComparisonOperator(OverloadedOperatorKind OK) { + return OK == OO_EqualEqual || OK == OO_ExclaimEqual; +} + +bool isDereferenceOperator(OverloadedOperatorKind OK) { + return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar || + OK == OO_Subscript; +} + +BinaryOperator::Opcode getOpcode(const SymExpr *SE) { + if (const auto *BSE = dyn_cast(SE)) { + return BSE->getOpcode(); + } else if (const auto *SC = dyn_cast(SE)) { + const auto *COE = dyn_cast(SC->getStmt()); + if (!COE) + return BO_Comma; // Extremal value, neither EQ nor NE + if (COE->getOperator() == OO_EqualEqual) { + return BO_EQ; + } else if (COE->getOperator() == OO_ExclaimEqual) { + return BO_NE; + } + return BO_Comma; // Extremal value, neither EQ nor NE + } + return BO_Comma; // Extremal value, neither EQ nor NE +} + +const RegionOrSymbol getRegionOrSymbol(const SVal &Val) { + if (const auto Reg = Val.getAsRegion()) { + return Reg; + } else if (const auto Sym = Val.getAsSymbol()) { + return Sym; + } else if (const auto LCVal = Val.getAs()) { + return LCVal->getRegion(); + } + return RegionOrSymbol(); +} + +const ProgramStateRef processComparison(ProgramStateRef State, + RegionOrSymbol LVal, + RegionOrSymbol RVal, bool Equal) { + const auto *LPos = getIteratorPosition(State, LVal); + const auto *RPos = getIteratorPosition(State, RVal); + if (LPos && !RPos) { + State = adjustIteratorPosition(State, RVal, *LPos, Equal); + } else if (!LPos && RPos) { + State = adjustIteratorPosition(State, LVal, *RPos, Equal); + } else if (LPos && RPos) { + State = relateIteratorPositions(State, *LPos, *RPos, Equal); + } + return State; +} + +const ProgramStateRef saveComparison(ProgramStateRef State, + const SymExpr *Condition, const SVal &LVal, + const SVal &RVal, bool Eq) { + const auto Left = getRegionOrSymbol(LVal); + const auto Right = getRegionOrSymbol(RVal); + if (!Left || !Right) + return State; + return State->set(Condition, + IteratorComparison(Left, Right, Eq)); +} + +const IteratorComparison *loadComparison(ProgramStateRef State, + const SymExpr *Condition) { + return State->get(Condition); +} + +SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) { + const auto *CDataPtr = getContainerData(State, Cont); + if (!CDataPtr) + return nullptr; + + return CDataPtr->getEnd(); +} + +ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, + const SymbolRef Sym) { + // Only create if it does not exist + const auto *CDataPtr = getContainerData(State, Cont); + if (CDataPtr) { + if (CDataPtr->getEnd()) { + return State; + } else { + const auto CData = CDataPtr->newEnd(Sym); + return setContainerData(State, Cont, CData); + } + } else { + const auto CData = ContainerData::fromEnd(Sym); + return setContainerData(State, Cont, CData); + } +} + +const ContainerData *getContainerData(ProgramStateRef State, + const MemRegion *Cont) { + return State->get(Cont); +} + +ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont, + const ContainerData &CData) { + return State->set(Cont, CData); +} + +const IteratorPosition *getIteratorPosition(ProgramStateRef State, + const SVal &Val) { + if (const auto Reg = Val.getAsRegion()) { + return State->get(Reg); + } else if (const auto Sym = Val.getAsSymbol()) { + return State->get(Sym); + } else if (const auto LCVal = Val.getAs()) { + return State->get(LCVal->getRegion()); + } + return nullptr; +} + +const IteratorPosition *getIteratorPosition(ProgramStateRef State, + RegionOrSymbol RegOrSym) { + if (RegOrSym.is()) { + return State->get(RegOrSym.get()); + } else if (RegOrSym.is()) { + return State->get(RegOrSym.get()); + } + return nullptr; +} + +ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, + const IteratorPosition &Pos) { + if (const auto Reg = Val.getAsRegion()) { + return State->set(Reg, Pos); + } else if (const auto Sym = Val.getAsSymbol()) { + return State->set(Sym, Pos); + } else if (const auto LCVal = Val.getAs()) { + return State->set(LCVal->getRegion(), Pos); + } + return nullptr; +} + +ProgramStateRef setIteratorPosition(ProgramStateRef State, + RegionOrSymbol RegOrSym, + const IteratorPosition &Pos) { + if (RegOrSym.is()) { + return State->set(RegOrSym.get(), + Pos); + } else if (RegOrSym.is()) { + return State->set(RegOrSym.get(), Pos); + } + return nullptr; +} + +ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val) { + if (const auto Reg = Val.getAsRegion()) { + return State->remove(Reg); + } else if (const auto Sym = Val.getAsSymbol()) { + return State->remove(Sym); + } else if (const auto LCVal = Val.getAs()) { + return State->remove(LCVal->getRegion()); + } + return nullptr; +} + +ProgramStateRef adjustIteratorPosition(ProgramStateRef State, + RegionOrSymbol RegOrSym, + const IteratorPosition &Pos, + bool Equal) { + if (Equal) { + return setIteratorPosition(State, RegOrSym, Pos); + } else { + return State; + } +} + +ProgramStateRef relateIteratorPositions(ProgramStateRef State, + const IteratorPosition &Pos1, + const IteratorPosition &Pos2, + bool Equal) { + // Try to compare them and get a defined value + auto &SVB = State->getStateManager().getSValBuilder(); + const auto comparison = + SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(Pos1.getOffset()), + nonloc::SymbolVal(Pos2.getOffset()), SVB.getConditionType()) + .getAs(); + if (comparison) { + return State->assume(*comparison, Equal); + } + + return State; +} + +bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos) { + const auto *Cont = Pos.getContainer(); + const auto *CData = getContainerData(State, Cont); + if (!CData) + return false; + + // Out of range means less than the begin symbol or greater or equal to the + // end symbol. + + const auto End = CData->getEnd(); + if (End) { + if (isGreaterOrEqual(State, Pos.getOffset(), End)) { + return true; + } + } + + return false; +} + +bool isGreaterOrEqual(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2) { + return compare(State, Sym1, Sym2, BO_GE); +} + +bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, + BinaryOperator::Opcode Opc) { + auto &SMgr = State->getStateManager(); + auto &SVB = SMgr.getSValBuilder(); + + const auto comparison = + SVB.evalBinOp(State, Opc, nonloc::SymbolVal(Sym1), + nonloc::SymbolVal(Sym2), SVB.getConditionType()) + .getAs(); + + if(comparison) { + return !!State->assume(*comparison, true); + } + + return false; +} + +} // namespace + +#define REGISTER_CHECKER(name) \ + void ento::register##name(CheckerManager &Mgr) { \ + auto *checker = Mgr.registerChecker(); \ + checker->ChecksEnabled[IteratorChecker::CK_##name] = true; \ + checker->CheckNames[IteratorChecker::CK_##name] = \ + Mgr.getCurrentCheckName(); \ + } + +REGISTER_CHECKER(IteratorRangeChecker) diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp deleted file mode 100644 index f0f7c98c9640..000000000000 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp +++ /dev/null @@ -1,840 +0,0 @@ -//===-- IteratorPastEndChecker.cpp --------------------------------*- C++ -*--// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines a checker for using iterators outside their range (past end). Usage -// means here dereferencing, incrementing etc. -// -//===----------------------------------------------------------------------===// - -#include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" - -#include - -using namespace clang; -using namespace ento; - -namespace { -struct IteratorPosition { -private: - enum Kind { InRange, OutofRange } K; - IteratorPosition(Kind InK) : K(InK) {} - -public: - bool isInRange() const { return K == InRange; } - bool isOutofRange() const { return K == OutofRange; } - - static IteratorPosition getInRange() { return IteratorPosition(InRange); } - static IteratorPosition getOutofRange() { - return IteratorPosition(OutofRange); - } - - bool operator==(const IteratorPosition &X) const { return K == X.K; } - bool operator!=(const IteratorPosition &X) const { return K != X.K; } - void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); } -}; - -typedef llvm::PointerUnion RegionOrSymbol; - -struct IteratorComparison { -private: - RegionOrSymbol Left, Right; - bool Equality; - -public: - IteratorComparison(RegionOrSymbol L, RegionOrSymbol R, bool Eq) - : Left(L), Right(R), Equality(Eq) {} - - RegionOrSymbol getLeft() const { return Left; } - RegionOrSymbol getRight() const { return Right; } - bool isEquality() const { return Equality; } - bool operator==(const IteratorComparison &X) const { - return Left == X.Left && Right == X.Right && Equality == X.Equality; - } - bool operator!=(const IteratorComparison &X) const { - return Left != X.Left || Right != X.Right || Equality != X.Equality; - } - void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Equality); } -}; - -class IteratorPastEndChecker - : public Checker< - check::PreCall, check::PostCall, check::PreStmt, - check::PostStmt, check::PostStmt, - check::PostStmt, check::BeginFunction, - check::DeadSymbols, eval::Assume, eval::Call> { - mutable IdentifierInfo *II_find = nullptr, - *II_find_end = nullptr, *II_find_first_of = nullptr, - *II_find_if = nullptr, *II_find_if_not = nullptr, - *II_lower_bound = nullptr, *II_upper_bound = nullptr, - *II_search = nullptr, *II_search_n = nullptr; - - std::unique_ptr PastEndBugType; - - void handleComparison(CheckerContext &C, const SVal &RetVal, const SVal &LVal, - const SVal &RVal, OverloadedOperatorKind Op) const; - void handleAccess(CheckerContext &C, const SVal &Val) const; - void handleDecrement(CheckerContext &C, const SVal &Val) const; - void handleEnd(CheckerContext &C, const SVal &RetVal) const; - - bool evalFind(CheckerContext &C, const CallExpr *CE) const; - bool evalFindEnd(CheckerContext &C, const CallExpr *CE) const; - bool evalFindFirstOf(CheckerContext &C, const CallExpr *CE) const; - bool evalFindIf(CheckerContext &C, const CallExpr *CE) const; - bool evalFindIfNot(CheckerContext &C, const CallExpr *CE) const; - bool evalLowerBound(CheckerContext &C, const CallExpr *CE) const; - bool evalUpperBound(CheckerContext &C, const CallExpr *CE) const; - bool evalSearch(CheckerContext &C, const CallExpr *CE) const; - bool evalSearchN(CheckerContext &C, const CallExpr *CE) const; - void Find(CheckerContext &C, const CallExpr *CE) const; - - void reportPastEndBug(const StringRef &Message, const SVal &Val, - CheckerContext &C, ExplodedNode *ErrNode) const; - void initIdentifiers(ASTContext &Ctx) const; - -public: - IteratorPastEndChecker(); - - void checkPreCall(const CallEvent &Call, CheckerContext &C) const; - void checkPostCall(const CallEvent &Call, CheckerContext &C) const; - void checkPreStmt(const CXXOperatorCallExpr *COCE, CheckerContext &C) const; - void checkBeginFunction(CheckerContext &C) const; - void checkPostStmt(const CXXConstructExpr *CCE, CheckerContext &C) const; - void checkPostStmt(const DeclStmt *DS, CheckerContext &C) const; - void checkPostStmt(const MaterializeTemporaryExpr *MTE, - CheckerContext &C) const; - void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; - ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond, - bool Assumption) const; - bool evalCall(const CallExpr *CE, CheckerContext &C) const; -}; -} - -REGISTER_MAP_WITH_PROGRAMSTATE(IteratorSymbolMap, SymbolRef, IteratorPosition) -REGISTER_MAP_WITH_PROGRAMSTATE(IteratorRegionMap, const MemRegion *, - IteratorPosition) - -REGISTER_MAP_WITH_PROGRAMSTATE(IteratorComparisonMap, const SymExpr *, - IteratorComparison) - -#define INIT_ID(Id) \ - if (!II_##Id) \ - II_##Id = &Ctx.Idents.get(#Id) - -namespace { - -bool isIteratorType(const QualType &Type); -bool isIterator(const CXXRecordDecl *CRD); -bool isEndCall(const FunctionDecl *Func); -bool isSimpleComparisonOperator(OverloadedOperatorKind OK); -bool isAccessOperator(OverloadedOperatorKind OK); -bool isDecrementOperator(OverloadedOperatorKind OK); -BinaryOperator::Opcode getOpcode(const SymExpr *SE); -const RegionOrSymbol getRegionOrSymbol(const SVal &Val); -const ProgramStateRef processComparison(ProgramStateRef State, - RegionOrSymbol LVal, - RegionOrSymbol RVal, bool Equal); -const ProgramStateRef saveComparison(ProgramStateRef State, - const SymExpr *Condition, const SVal &LVal, - const SVal &RVal, bool Eq); -const IteratorComparison *loadComparison(ProgramStateRef State, - const SymExpr *Condition); -const IteratorPosition *getIteratorPosition(ProgramStateRef State, - const SVal &Val); -const IteratorPosition *getIteratorPosition(ProgramStateRef State, - RegionOrSymbol RegOrSym); -ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, - IteratorPosition Pos); -ProgramStateRef setIteratorPosition(ProgramStateRef State, - RegionOrSymbol RegOrSym, - IteratorPosition Pos); -ProgramStateRef adjustIteratorPosition(ProgramStateRef State, - RegionOrSymbol RegOrSym, - IteratorPosition Pos, bool Equal); -bool contradictingIteratorPositions(IteratorPosition Pos1, - IteratorPosition Pos2, bool Equal); -} - -IteratorPastEndChecker::IteratorPastEndChecker() { - PastEndBugType.reset( - new BugType(this, "Iterator Past End", "Misuse of STL APIs")); - PastEndBugType->setSuppressOnSink(true); -} - -void IteratorPastEndChecker::checkPreCall(const CallEvent &Call, - CheckerContext &C) const { - // Check for access past end - const auto *Func = Call.getDecl()->getAsFunction(); - if (!Func) - return; - if (Func->isOverloadedOperator()) { - if (isAccessOperator(Func->getOverloadedOperator())) { - if (const auto *InstCall = dyn_cast(&Call)) { - handleAccess(C, InstCall->getCXXThisVal()); - } else { - handleAccess(C, Call.getArgSVal(0)); - } - } - } -} - -void IteratorPastEndChecker::checkPostCall(const CallEvent &Call, - CheckerContext &C) const { - // Record end() iterators, iterator decrementation and comparison - const auto *Func = Call.getDecl()->getAsFunction(); - if (!Func) - return; - if (Func->isOverloadedOperator()) { - const auto Op = Func->getOverloadedOperator(); - if (isSimpleComparisonOperator(Op)) { - if (Func->isCXXInstanceMember()) { - const auto &InstCall = static_cast(Call); - handleComparison(C, InstCall.getReturnValue(), InstCall.getCXXThisVal(), - InstCall.getArgSVal(0), Op); - } else { - handleComparison(C, Call.getReturnValue(), Call.getArgSVal(0), - Call.getArgSVal(1), Op); - } - } else if (isDecrementOperator(Func->getOverloadedOperator())) { - if (Func->isCXXInstanceMember()) { - const auto &InstCall = static_cast(Call); - handleDecrement(C, InstCall.getCXXThisVal()); - } else { - handleDecrement(C, Call.getArgSVal(0)); - } - } - } else if (Func->isCXXInstanceMember()) { - if (!isEndCall(Func)) - return; - if (!isIteratorType(Call.getResultType())) - return; - handleEnd(C, Call.getReturnValue()); - } -} - -void IteratorPastEndChecker::checkPreStmt(const CXXOperatorCallExpr *COCE, - CheckerContext &C) const { - const auto *ThisExpr = COCE->getArg(0); - - auto State = C.getState(); - const auto *LCtx = C.getPredecessor()->getLocationContext(); - - const auto CurrentThis = State->getSVal(ThisExpr, LCtx); - if (const auto *Reg = CurrentThis.getAsRegion()) { - if (!Reg->getAs()) - return; - const auto OldState = C.getPredecessor()->getFirstPred()->getState(); - const auto OldThis = OldState->getSVal(ThisExpr, LCtx); - const auto *Pos = getIteratorPosition(OldState, OldThis); - if (!Pos) - return; - State = setIteratorPosition(State, CurrentThis, *Pos); - C.addTransition(State); - } -} - -void IteratorPastEndChecker::checkBeginFunction(CheckerContext &C) const { - // Copy state of iterator arguments to iterator parameters - auto State = C.getState(); - const auto *LCtx = C.getLocationContext(); - - const auto *Site = cast(LCtx)->getCallSite(); - if (!Site) - return; - - const auto *FD = dyn_cast(LCtx->getDecl()); - if (!FD) - return; - - const auto *CE = dyn_cast(Site); - if (!CE) - return; - - bool Change = false; - int idx = 0; - for (const auto P : FD->parameters()) { - auto Param = State->getLValue(P, LCtx); - auto Arg = State->getSVal(CE->getArg(idx++), LCtx->getParent()); - const auto *Pos = getIteratorPosition(State, Arg); - if (!Pos) - continue; - State = setIteratorPosition(State, Param, *Pos); - Change = true; - } - if (Change) { - C.addTransition(State); - } -} - -void IteratorPastEndChecker::checkPostStmt(const CXXConstructExpr *CCE, - CheckerContext &C) const { - // Transfer iterator state in case of copy or move by constructor - const auto *ctr = CCE->getConstructor(); - if (!ctr->isCopyOrMoveConstructor()) - return; - const auto *RHSExpr = CCE->getArg(0); - - auto State = C.getState(); - const auto *LCtx = C.getLocationContext(); - - const auto RetVal = State->getSVal(CCE, LCtx); - - const auto RHSVal = State->getSVal(RHSExpr, LCtx); - const auto *RHSPos = getIteratorPosition(State, RHSVal); - if (!RHSPos) - return; - State = setIteratorPosition(State, RetVal, *RHSPos); - C.addTransition(State); -} - -void IteratorPastEndChecker::checkPostStmt(const DeclStmt *DS, - CheckerContext &C) const { - // Transfer iterator state to new variable declaration - for (const auto *D : DS->decls()) { - const auto *VD = dyn_cast(D); - if (!VD || !VD->hasInit()) - continue; - - auto State = C.getState(); - const auto *LCtx = C.getPredecessor()->getLocationContext(); - const auto *Pos = - getIteratorPosition(State, State->getSVal(VD->getInit(), LCtx)); - if (!Pos) - continue; - State = setIteratorPosition(State, State->getLValue(VD, LCtx), *Pos); - C.addTransition(State); - } -} - -void IteratorPastEndChecker::checkPostStmt(const MaterializeTemporaryExpr *MTE, - CheckerContext &C) const { - /* Transfer iterator state for to temporary objects */ - auto State = C.getState(); - const auto *LCtx = C.getPredecessor()->getLocationContext(); - const auto *Pos = - getIteratorPosition(State, State->getSVal(MTE->GetTemporaryExpr(), LCtx)); - if (!Pos) - return; - State = setIteratorPosition(State, State->getSVal(MTE, LCtx), *Pos); - C.addTransition(State); -} - -void IteratorPastEndChecker::checkDeadSymbols(SymbolReaper &SR, - CheckerContext &C) const { - auto State = C.getState(); - - auto RegionMap = State->get(); - for (const auto Reg : RegionMap) { - if (!SR.isLiveRegion(Reg.first)) { - State = State->remove(Reg.first); - } - } - - auto SymbolMap = State->get(); - for (const auto Sym : SymbolMap) { - if (SR.isDead(Sym.first)) { - State = State->remove(Sym.first); - } - } - - auto ComparisonMap = State->get(); - for (const auto Comp : ComparisonMap) { - if (SR.isDead(Comp.first)) { - State = State->remove(Comp.first); - } - } -} - -ProgramStateRef IteratorPastEndChecker::evalAssume(ProgramStateRef State, - SVal Cond, - bool Assumption) const { - // Load recorded comparison and transfer iterator state between sides - // according to comparison operator and assumption - const auto *SE = Cond.getAsSymExpr(); - if (!SE) - return State; - - auto Opc = getOpcode(SE); - if (Opc != BO_EQ && Opc != BO_NE) - return State; - - bool Negated = false; - const auto *Comp = loadComparison(State, SE); - if (!Comp) { - // Try negated comparison, which is a SymExpr to 0 integer comparison - const auto *SIE = dyn_cast(SE); - if (!SIE) - return State; - - if (SIE->getRHS() != 0) - return State; - - SE = SIE->getLHS(); - Negated = SIE->getOpcode() == BO_EQ; // Equal to zero means negation - Opc = getOpcode(SE); - if (Opc != BO_EQ && Opc != BO_NE) - return State; - - Comp = loadComparison(State, SE); - if (!Comp) - return State; - } - - return processComparison(State, Comp->getLeft(), Comp->getRight(), - (Comp->isEquality() == Assumption) != Negated); -} - -// FIXME: Evaluation of these STL calls should be moved to StdCLibraryFunctions -// checker (see patch r284960) or another similar checker for C++ STL -// functions (e.g. StdCXXLibraryFunctions or StdCppLibraryFunctions). -bool IteratorPastEndChecker::evalCall(const CallExpr *CE, - CheckerContext &C) const { - const FunctionDecl *FD = C.getCalleeDecl(CE); - if (!FD) - return false; - - ASTContext &Ctx = C.getASTContext(); - initIdentifiers(Ctx); - - if (FD->getKind() == Decl::Function) { - if (FD->isInStdNamespace()) { - if (FD->getIdentifier() == II_find) { - return evalFind(C, CE); - } else if (FD->getIdentifier() == II_find_end) { - return evalFindEnd(C, CE); - } else if (FD->getIdentifier() == II_find_first_of) { - return evalFindFirstOf(C, CE); - } else if (FD->getIdentifier() == II_find_if) { - return evalFindIf(C, CE); - } else if (FD->getIdentifier() == II_find_if_not) { - return evalFindIfNot(C, CE); - } else if (FD->getIdentifier() == II_upper_bound) { - return evalUpperBound(C, CE); - } else if (FD->getIdentifier() == II_lower_bound) { - return evalLowerBound(C, CE); - } else if (FD->getIdentifier() == II_search) { - return evalSearch(C, CE); - } else if (FD->getIdentifier() == II_search_n) { - return evalSearchN(C, CE); - } - } - } - - return false; -} - -void IteratorPastEndChecker::handleComparison(CheckerContext &C, - const SVal &RetVal, - const SVal &LVal, - const SVal &RVal, - OverloadedOperatorKind Op) const { - // Record the operands and the operator of the comparison for the next - // evalAssume, if the result is a symbolic expression. If it is a concrete - // value (only one branch is possible), then transfer the state between - // the operands according to the operator and the result - auto State = C.getState(); - if (const auto *Condition = RetVal.getAsSymbolicExpression()) { - const auto *LPos = getIteratorPosition(State, LVal); - const auto *RPos = getIteratorPosition(State, RVal); - if (!LPos && !RPos) - return; - State = saveComparison(State, Condition, LVal, RVal, Op == OO_EqualEqual); - C.addTransition(State); - } else if (const auto TruthVal = RetVal.getAs()) { - if ((State = processComparison( - State, getRegionOrSymbol(LVal), getRegionOrSymbol(RVal), - (Op == OO_EqualEqual) == (TruthVal->getValue() != 0)))) { - C.addTransition(State); - } else { - C.generateSink(State, C.getPredecessor()); - } - } -} - -void IteratorPastEndChecker::handleAccess(CheckerContext &C, - const SVal &Val) const { - auto State = C.getState(); - const auto *Pos = getIteratorPosition(State, Val); - if (Pos && Pos->isOutofRange()) { - auto *N = C.generateNonFatalErrorNode(State); - if (!N) { - return; - } - reportPastEndBug("Iterator accessed past its end.", Val, C, N); - } -} - -void IteratorPastEndChecker::handleDecrement(CheckerContext &C, - const SVal &Val) const { - auto State = C.getState(); - const auto *Pos = getIteratorPosition(State, Val); - if (Pos && Pos->isOutofRange()) { - State = setIteratorPosition(State, Val, IteratorPosition::getInRange()); - // FIXME: We could also check for iterators ahead of their beginnig in the - // future, but currently we do not care for such errors. We also - // assume that the iterator is not past its end by more then one - // position. - C.addTransition(State); - } -} - -void IteratorPastEndChecker::handleEnd(CheckerContext &C, - const SVal &RetVal) const { - auto State = C.getState(); - State = setIteratorPosition(State, RetVal, IteratorPosition::getOutofRange()); - C.addTransition(State); -} - -bool IteratorPastEndChecker::evalFind(CheckerContext &C, - const CallExpr *CE) const { - if (CE->getNumArgs() == 3 && isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalFindEnd(CheckerContext &C, - const CallExpr *CE) const { - if ((CE->getNumArgs() == 4 || CE->getNumArgs() == 5) && - isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType()) && - isIteratorType(CE->getArg(2)->getType()) && - isIteratorType(CE->getArg(3)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalFindFirstOf(CheckerContext &C, - const CallExpr *CE) const { - if ((CE->getNumArgs() == 4 || CE->getNumArgs() == 5) && - isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType()) && - isIteratorType(CE->getArg(2)->getType()) && - isIteratorType(CE->getArg(3)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalFindIf(CheckerContext &C, - const CallExpr *CE) const { - if (CE->getNumArgs() == 3 && isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalFindIfNot(CheckerContext &C, - const CallExpr *CE) const { - if (CE->getNumArgs() == 3 && isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalLowerBound(CheckerContext &C, - const CallExpr *CE) const { - if ((CE->getNumArgs() == 3 || CE->getNumArgs() == 4) && - isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalUpperBound(CheckerContext &C, - const CallExpr *CE) const { - if ((CE->getNumArgs() == 3 || CE->getNumArgs() == 4) && - isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalSearch(CheckerContext &C, - const CallExpr *CE) const { - if ((CE->getNumArgs() == 4 || CE->getNumArgs() == 5) && - isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType()) && - isIteratorType(CE->getArg(2)->getType()) && - isIteratorType(CE->getArg(3)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -bool IteratorPastEndChecker::evalSearchN(CheckerContext &C, - const CallExpr *CE) const { - if ((CE->getNumArgs() == 4 || CE->getNumArgs() == 5) && - isIteratorType(CE->getArg(0)->getType()) && - isIteratorType(CE->getArg(1)->getType())) { - Find(C, CE); - return true; - } - return false; -} - -void IteratorPastEndChecker::Find(CheckerContext &C, const CallExpr *CE) const { - auto state = C.getState(); - auto &svalBuilder = C.getSValBuilder(); - const auto *LCtx = C.getLocationContext(); - - auto RetVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()); - auto SecondParam = state->getSVal(CE->getArg(1), LCtx); - - auto stateFound = state->BindExpr(CE, LCtx, RetVal); - auto stateNotFound = state->BindExpr(CE, LCtx, SecondParam); - - C.addTransition(stateFound); - C.addTransition(stateNotFound); -} - -void IteratorPastEndChecker::reportPastEndBug(const StringRef &Message, - const SVal &Val, - CheckerContext &C, - ExplodedNode *ErrNode) const { - auto R = llvm::make_unique(*PastEndBugType, Message, ErrNode); - R->markInteresting(Val); - C.emitReport(std::move(R)); -} - -void IteratorPastEndChecker::initIdentifiers(ASTContext &Ctx) const { - INIT_ID(find); - INIT_ID(find_end); - INIT_ID(find_first_of); - INIT_ID(find_if); - INIT_ID(find_if_not); - INIT_ID(lower_bound); - INIT_ID(upper_bound); - INIT_ID(search); - INIT_ID(search_n); -} - -namespace { - -bool isIteratorType(const QualType &Type) { - if (Type->isPointerType()) - return true; - - const auto *CRD = Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl(); - return isIterator(CRD); -} - -bool isIterator(const CXXRecordDecl *CRD) { - if (!CRD) - return false; - - const auto Name = CRD->getName(); - if (!(Name.endswith_lower("iterator") || Name.endswith_lower("iter") || - Name.endswith_lower("it"))) - return false; - - bool HasCopyCtor = false, HasCopyAssign = true, HasDtor = false, - HasPreIncrOp = false, HasPostIncrOp = false, HasDerefOp = false; - for (const auto *Method : CRD->methods()) { - if (const auto *Ctor = dyn_cast(Method)) { - if (Ctor->isCopyConstructor()) { - HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() == AS_public; - } - continue; - } - if (const auto *Dtor = dyn_cast(Method)) { - HasDtor = !Dtor->isDeleted() && Dtor->getAccess() == AS_public; - continue; - } - if (Method->isCopyAssignmentOperator()) { - HasCopyAssign = !Method->isDeleted() && Method->getAccess() == AS_public; - continue; - } - if (!Method->isOverloadedOperator()) - continue; - const auto OPK = Method->getOverloadedOperator(); - if (OPK == OO_PlusPlus) { - HasPreIncrOp = HasPreIncrOp || (Method->getNumParams() == 0); - HasPostIncrOp = HasPostIncrOp || (Method->getNumParams() == 1); - continue; - } - if (OPK == OO_Star) { - HasDerefOp = (Method->getNumParams() == 0); - continue; - } - } - - return HasCopyCtor && HasCopyAssign && HasDtor && HasPreIncrOp && - HasPostIncrOp && HasDerefOp; -} - -bool isEndCall(const FunctionDecl *Func) { - const auto *IdInfo = Func->getIdentifier(); - if (!IdInfo) - return false; - return IdInfo->getName().endswith_lower("end"); -} - -bool isSimpleComparisonOperator(OverloadedOperatorKind OK) { - return OK == OO_EqualEqual || OK == OO_ExclaimEqual; -} - -bool isAccessOperator(OverloadedOperatorKind OK) { - return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar || - OK == OO_Plus || OK == OO_PlusEqual || OK == OO_PlusPlus || - OK == OO_Subscript; -} - -bool isDecrementOperator(OverloadedOperatorKind OK) { - return OK == OO_MinusEqual || OK == OO_MinusMinus; -} - -BinaryOperator::Opcode getOpcode(const SymExpr *SE) { - if (const auto *BSE = dyn_cast(SE)) { - return BSE->getOpcode(); - } else if (const auto *SC = dyn_cast(SE)) { - const auto *COE = dyn_cast(SC->getStmt()); - if (!COE) - return BO_Comma; // Extremal value, neither EQ nor NE - if (COE->getOperator() == OO_EqualEqual) { - return BO_EQ; - } else if (COE->getOperator() == OO_ExclaimEqual) { - return BO_NE; - } - return BO_Comma; // Extremal value, neither EQ nor NE - } - return BO_Comma; // Extremal value, neither EQ nor NE -} - -const RegionOrSymbol getRegionOrSymbol(const SVal &Val) { - if (const auto Reg = Val.getAsRegion()) { - return Reg; - } else if (const auto Sym = Val.getAsSymbol()) { - return Sym; - } else if (const auto LCVal = Val.getAs()) { - return LCVal->getRegion(); - } - return RegionOrSymbol(); -} - -const ProgramStateRef processComparison(ProgramStateRef State, - RegionOrSymbol LVal, - RegionOrSymbol RVal, bool Equal) { - const auto *LPos = getIteratorPosition(State, LVal); - const auto *RPos = getIteratorPosition(State, RVal); - if (LPos && !RPos) { - State = adjustIteratorPosition(State, RVal, *LPos, Equal); - } else if (!LPos && RPos) { - State = adjustIteratorPosition(State, LVal, *RPos, Equal); - } else if (LPos && RPos) { - if (contradictingIteratorPositions(*LPos, *RPos, Equal)) { - return nullptr; - } - } - return State; -} - -const ProgramStateRef saveComparison(ProgramStateRef State, - const SymExpr *Condition, const SVal &LVal, - const SVal &RVal, bool Eq) { - const auto Left = getRegionOrSymbol(LVal); - const auto Right = getRegionOrSymbol(RVal); - if (!Left || !Right) - return State; - return State->set(Condition, - IteratorComparison(Left, Right, Eq)); -} - -const IteratorComparison *loadComparison(ProgramStateRef State, - const SymExpr *Condition) { - return State->get(Condition); -} - -const IteratorPosition *getIteratorPosition(ProgramStateRef State, - const SVal &Val) { - if (const auto Reg = Val.getAsRegion()) { - return State->get(Reg); - } else if (const auto Sym = Val.getAsSymbol()) { - return State->get(Sym); - } else if (const auto LCVal = Val.getAs()) { - return State->get(LCVal->getRegion()); - } - return nullptr; -} - -const IteratorPosition *getIteratorPosition(ProgramStateRef State, - RegionOrSymbol RegOrSym) { - if (RegOrSym.is()) { - return State->get(RegOrSym.get()); - } else if (RegOrSym.is()) { - return State->get(RegOrSym.get()); - } - return nullptr; -} - -ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, - IteratorPosition Pos) { - if (const auto Reg = Val.getAsRegion()) { - return State->set(Reg, Pos); - } else if (const auto Sym = Val.getAsSymbol()) { - return State->set(Sym, Pos); - } else if (const auto LCVal = Val.getAs()) { - return State->set(LCVal->getRegion(), Pos); - } - return nullptr; -} - -ProgramStateRef setIteratorPosition(ProgramStateRef State, - RegionOrSymbol RegOrSym, - IteratorPosition Pos) { - if (RegOrSym.is()) { - return State->set(RegOrSym.get(), - Pos); - } else if (RegOrSym.is()) { - return State->set(RegOrSym.get(), Pos); - } - return nullptr; -} - -ProgramStateRef adjustIteratorPosition(ProgramStateRef State, - RegionOrSymbol RegOrSym, - IteratorPosition Pos, bool Equal) { - - if ((Pos.isInRange() && Equal) || (Pos.isOutofRange() && !Equal)) { - return setIteratorPosition(State, RegOrSym, IteratorPosition::getInRange()); - } else if (Pos.isOutofRange() && Equal) { - return setIteratorPosition(State, RegOrSym, - IteratorPosition::getOutofRange()); - } else { - return State; - } -} - -bool contradictingIteratorPositions(IteratorPosition Pos1, - IteratorPosition Pos2, bool Equal) { - return ((Pos1 != Pos2) && Equal) || - ((Pos1.isOutofRange() && Pos2.isOutofRange()) && !Equal); -} -} - -void ento::registerIteratorPastEndChecker(CheckerManager &Mgr) { - Mgr.registerChecker(); -} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 7ef79c683c49..0e3a649e88f7 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -25,7 +25,13 @@ using namespace ento; namespace { struct LockState { - enum Kind { Destroyed, Locked, Unlocked } K; + enum Kind { + Destroyed, + Locked, + Unlocked, + UntouchedAndPossiblyDestroyed, + UnlockedAndPossiblyDestroyed + } K; private: LockState(Kind K) : K(K) {} @@ -34,6 +40,12 @@ struct LockState { static LockState getLocked() { return LockState(Locked); } static LockState getUnlocked() { return LockState(Unlocked); } static LockState getDestroyed() { return LockState(Destroyed); } + static LockState getUntouchedAndPossiblyDestroyed() { + return LockState(UntouchedAndPossiblyDestroyed); + } + static LockState getUnlockedAndPossiblyDestroyed() { + return LockState(UnlockedAndPossiblyDestroyed); + } bool operator==(const LockState &X) const { return K == X.K; @@ -42,13 +54,20 @@ struct LockState { bool isLocked() const { return K == Locked; } bool isUnlocked() const { return K == Unlocked; } bool isDestroyed() const { return K == Destroyed; } + bool isUntouchedAndPossiblyDestroyed() const { + return K == UntouchedAndPossiblyDestroyed; + } + bool isUnlockedAndPossiblyDestroyed() const { + return K == UnlockedAndPossiblyDestroyed; + } void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); } }; -class PthreadLockChecker : public Checker< check::PostStmt > { +class PthreadLockChecker + : public Checker, check::DeadSymbols> { mutable std::unique_ptr BT_doublelock; mutable std::unique_ptr BT_doubleunlock; mutable std::unique_ptr BT_destroylock; @@ -61,22 +80,31 @@ class PthreadLockChecker : public Checker< check::PostStmt > { }; public: void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; void AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock, bool isTryLock, enum LockingSemantics semantics) const; void ReleaseLock(CheckerContext &C, const CallExpr *CE, SVal lock) const; - void DestroyLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const; + void DestroyLock(CheckerContext &C, const CallExpr *CE, SVal Lock, + enum LockingSemantics semantics) const; void InitLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const; void reportUseDestroyedBug(CheckerContext &C, const CallExpr *CE) const; + ProgramStateRef resolvePossiblyDestroyedMutex(ProgramStateRef state, + const MemRegion *lockR, + const SymbolRef *sym) const; }; } // end anonymous namespace -// GDM Entry for tracking lock state. +// A stack of locks for tracking lock-unlock order. REGISTER_LIST_WITH_PROGRAMSTATE(LockSet, const MemRegion *) +// An entry for tracking lock states. REGISTER_MAP_WITH_PROGRAMSTATE(LockMap, const MemRegion *, LockState) +// Return values for unresolved calls to pthread_mutex_destroy(). +REGISTER_MAP_WITH_PROGRAMSTATE(DestroyRetVal, const MemRegion *, SymbolRef) + void PthreadLockChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { ProgramStateRef state = C.getState(); @@ -113,13 +141,49 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE, FName == "lck_mtx_unlock" || FName == "lck_rw_done") ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); - else if (FName == "pthread_mutex_destroy" || - FName == "lck_mtx_destroy") - DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); + else if (FName == "pthread_mutex_destroy") + DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx), PthreadSemantics); + else if (FName == "lck_mtx_destroy") + DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx), XNUSemantics); else if (FName == "pthread_mutex_init") InitLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); } +// When a lock is destroyed, in some semantics(like PthreadSemantics) we are not +// sure if the destroy call has succeeded or failed, and the lock enters one of +// the 'possibly destroyed' state. There is a short time frame for the +// programmer to check the return value to see if the lock was successfully +// destroyed. Before we model the next operation over that lock, we call this +// function to see if the return value was checked by now and set the lock state +// - either to destroyed state or back to its previous state. + +// In PthreadSemantics, pthread_mutex_destroy() returns zero if the lock is +// successfully destroyed and it returns a non-zero value otherwise. +ProgramStateRef PthreadLockChecker::resolvePossiblyDestroyedMutex( + ProgramStateRef state, const MemRegion *lockR, const SymbolRef *sym) const { + const LockState *lstate = state->get(lockR); + // Existence in DestroyRetVal ensures existence in LockMap. + // Existence in Destroyed also ensures that the lock state for lockR is either + // UntouchedAndPossiblyDestroyed or UnlockedAndPossiblyDestroyed. + assert(lstate->isUntouchedAndPossiblyDestroyed() || + lstate->isUnlockedAndPossiblyDestroyed()); + + ConstraintManager &CMgr = state->getConstraintManager(); + ConditionTruthVal retZero = CMgr.isNull(state, *sym); + if (retZero.isConstrainedFalse()) { + if (lstate->isUntouchedAndPossiblyDestroyed()) + state = state->remove(lockR); + else if (lstate->isUnlockedAndPossiblyDestroyed()) + state = state->set(lockR, LockState::getUnlocked()); + } else + state = state->set(lockR, LockState::getDestroyed()); + + // Removing the map entry (lockR, sym) from DestroyRetVal as the lock state is + // now resolved. + state = state->remove(lockR); + return state; +} + void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, SVal lock, bool isTryLock, enum LockingSemantics semantics) const { @@ -129,6 +193,9 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, return; ProgramStateRef state = C.getState(); + const SymbolRef *sym = state->get(lockR); + if (sym) + state = resolvePossiblyDestroyedMutex(state, lockR, sym); SVal X = state->getSVal(CE, C.getLocationContext()); if (X.isUnknownOrUndef()) @@ -197,6 +264,9 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE, return; ProgramStateRef state = C.getState(); + const SymbolRef *sym = state->get(lockR); + if (sym) + state = resolvePossiblyDestroyedMutex(state, lockR, sym); if (const LockState *LState = state->get(lockR)) { if (LState->isUnlocked()) { @@ -245,7 +315,8 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE, } void PthreadLockChecker::DestroyLock(CheckerContext &C, const CallExpr *CE, - SVal Lock) const { + SVal Lock, + enum LockingSemantics semantics) const { const MemRegion *LockR = Lock.getAsRegion(); if (!LockR) @@ -253,13 +324,38 @@ void PthreadLockChecker::DestroyLock(CheckerContext &C, const CallExpr *CE, ProgramStateRef State = C.getState(); - const LockState *LState = State->get(LockR); - if (!LState || LState->isUnlocked()) { - State = State->set(LockR, LockState::getDestroyed()); - C.addTransition(State); - return; - } + const SymbolRef *sym = State->get(LockR); + if (sym) + State = resolvePossiblyDestroyedMutex(State, LockR, sym); + const LockState *LState = State->get(LockR); + // Checking the return value of the destroy method only in the case of + // PthreadSemantics + if (semantics == PthreadSemantics) { + if (!LState || LState->isUnlocked()) { + SymbolRef sym = C.getSVal(CE).getAsSymbol(); + if (!sym) { + State = State->remove(LockR); + C.addTransition(State); + return; + } + State = State->set(LockR, sym); + if (LState && LState->isUnlocked()) + State = State->set( + LockR, LockState::getUnlockedAndPossiblyDestroyed()); + else + State = State->set( + LockR, LockState::getUntouchedAndPossiblyDestroyed()); + C.addTransition(State); + return; + } + } else { + if (!LState || LState->isUnlocked()) { + State = State->set(LockR, LockState::getDestroyed()); + C.addTransition(State); + return; + } + } StringRef Message; if (LState->isLocked()) { @@ -288,6 +384,10 @@ void PthreadLockChecker::InitLock(CheckerContext &C, const CallExpr *CE, ProgramStateRef State = C.getState(); + const SymbolRef *sym = State->get(LockR); + if (sym) + State = resolvePossiblyDestroyedMutex(State, LockR, sym); + const struct LockState *LState = State->get(LockR); if (!LState || LState->isDestroyed()) { State = State->set(LockR, LockState::getUnlocked()); @@ -328,6 +428,26 @@ void PthreadLockChecker::reportUseDestroyedBug(CheckerContext &C, C.emitReport(std::move(Report)); } +void PthreadLockChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + + // TODO: Clean LockMap when a mutex region dies. + + DestroyRetValTy TrackedSymbols = State->get(); + for (DestroyRetValTy::iterator I = TrackedSymbols.begin(), + E = TrackedSymbols.end(); + I != E; ++I) { + const SymbolRef Sym = I->second; + const MemRegion *lockR = I->first; + bool IsSymDead = SymReaper.isDead(Sym); + // Remove the dead symbol from the return value symbols map. + if (IsSymDead) + State = resolvePossiblyDestroyedMutex(State, lockR, &Sym); + } + C.addTransition(State); +} + void ento::registerPthreadLockChecker(CheckerManager &mgr) { mgr.registerChecker(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 31556c792fc5..3215c3ccd21e 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -644,15 +644,33 @@ ProgramStateRef ProgramState::addTaint(const Stmt *S, if (const Expr *E = dyn_cast_or_null(S)) S = E->IgnoreParens(); - SymbolRef Sym = getSVal(S, LCtx).getAsSymbol(); + return addTaint(getSVal(S, LCtx), Kind); +} + +ProgramStateRef ProgramState::addTaint(SVal V, + TaintTagType Kind) const { + SymbolRef Sym = V.getAsSymbol(); if (Sym) return addTaint(Sym, Kind); - const MemRegion *R = getSVal(S, LCtx).getAsRegion(); - addTaint(R, Kind); + // If the SVal represents a structure, try to mass-taint all values within the + // structure. For now it only works efficiently on lazy compound values that + // were conjured during a conservative evaluation of a function - either as + // return values of functions that return structures or arrays by value, or as + // values of structures or arrays passed into the function by reference, + // directly or through pointer aliasing. Such lazy compound values are + // characterized by having exactly one binding in their captured store within + // their parent region, which is a conjured symbol default-bound to the base + // region of the parent region. + if (auto LCV = V.getAs()) { + if (Optional binding = getStateManager().StoreMgr->getDefaultBinding(*LCV)) { + if (SymbolRef Sym = binding->getAsSymbol()) + return addPartialTaint(Sym, LCV->getRegion(), Kind); + } + } - // Cannot add taint, so just return the state. - return this; + const MemRegion *R = V.getAsRegion(); + return addTaint(R, Kind); } ProgramStateRef ProgramState::addTaint(const MemRegion *R, @@ -674,6 +692,27 @@ ProgramStateRef ProgramState::addTaint(SymbolRef Sym, return NewState; } +ProgramStateRef ProgramState::addPartialTaint(SymbolRef ParentSym, + const SubRegion *SubRegion, + TaintTagType Kind) const { + // Ignore partial taint if the entire parent symbol is already tainted. + if (contains(ParentSym) && *get(ParentSym) == Kind) + return this; + + // Partial taint applies if only a portion of the symbol is tainted. + if (SubRegion == SubRegion->getBaseRegion()) + return addTaint(ParentSym, Kind); + + const TaintedSubRegions *SavedRegs = get(ParentSym); + TaintedSubRegions Regs = + SavedRegs ? *SavedRegs : stateMgr->TSRFactory.getEmptyMap(); + + Regs = stateMgr->TSRFactory.add(Regs, SubRegion, Kind); + ProgramStateRef NewState = set(ParentSym, Regs); + assert(NewState); + return NewState; +} + bool ProgramState::isTainted(const Stmt *S, const LocationContext *LCtx, TaintTagType Kind) const { if (const Expr *E = dyn_cast_or_null(S)) @@ -714,31 +753,52 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const { return false; // Traverse all the symbols this symbol depends on to see if any are tainted. - bool Tainted = false; for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end(); SI != SE; ++SI) { if (!isa(*SI)) continue; - const TaintTagType *Tag = get(*SI); - Tainted = (Tag && *Tag == Kind); + if (const TaintTagType *Tag = get(*SI)) { + if (*Tag == Kind) + return true; + } - // If this is a SymbolDerived with a tainted parent, it's also tainted. - if (const SymbolDerived *SD = dyn_cast(*SI)) - Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind); + if (const SymbolDerived *SD = dyn_cast(*SI)) { + // If this is a SymbolDerived with a tainted parent, it's also tainted. + if (isTainted(SD->getParentSymbol(), Kind)) + return true; + + // If this is a SymbolDerived with the same parent symbol as another + // tainted SymbolDerived and a region that's a sub-region of that tainted + // symbol, it's also tainted. + if (const TaintedSubRegions *Regs = + get(SD->getParentSymbol())) { + const TypedValueRegion *R = SD->getRegion(); + for (auto I : *Regs) { + // FIXME: The logic to identify tainted regions could be more + // complete. For example, this would not currently identify + // overlapping fields in a union as tainted. To identify this we can + // check for overlapping/nested byte offsets. + if (Kind == I.second && + (R == I.first || R->isSubRegionOf(I.first))) + return true; + } + } + } // If memory region is tainted, data is also tainted. - if (const SymbolRegionValue *SRV = dyn_cast(*SI)) - Tainted = Tainted || isTainted(SRV->getRegion(), Kind); + if (const SymbolRegionValue *SRV = dyn_cast(*SI)) { + if (isTainted(SRV->getRegion(), Kind)) + return true; + } - // If If this is a SymbolCast from a tainted value, it's also tainted. - if (const SymbolCast *SC = dyn_cast(*SI)) - Tainted = Tainted || isTainted(SC->getOperand(), Kind); - - if (Tainted) - return true; + // If this is a SymbolCast from a tainted value, it's also tainted. + if (const SymbolCast *SC = dyn_cast(*SI)) { + if (isTainted(SC->getOperand(), Kind)) + return true; + } } - return Tainted; + return false; } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 3000e13d32c6..28f78fa3ff5e 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -496,7 +496,10 @@ class RegionStoreManager : public StoreManager { Optional getDefaultBinding(Store S, const MemRegion *R) override { RegionBindingsRef B = getRegionBindings(S); - return B.getDefaultBinding(R); + // Default bindings are always applied over a base region so look up the + // base region's default binding, otherwise the lookup will fail when R + // is at an offset from R->getBaseRegion(). + return B.getDefaultBinding(R->getBaseRegion()); } SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType()); diff --git a/contrib/llvm/tools/lld/ELF/LinkerScript.cpp b/contrib/llvm/tools/lld/ELF/LinkerScript.cpp index 492b81c1fa76..99c464e3714c 100644 --- a/contrib/llvm/tools/lld/ELF/LinkerScript.cpp +++ b/contrib/llvm/tools/lld/ELF/LinkerScript.cpp @@ -52,11 +52,12 @@ LinkerScript *elf::Script; uint64_t ExprValue::getValue() const { if (Sec) { if (Sec->getOutputSection()) - return Sec->getOffset(Val) + Sec->getOutputSection()->Addr; + return alignTo(Sec->getOffset(Val) + Sec->getOutputSection()->Addr, + Alignment); error("unable to evaluate expression: input section " + Sec->Name + " has no output section assigned"); } - return Val; + return alignTo(Val, Alignment); } uint64_t ExprValue::getSecAddr() const { @@ -143,7 +144,7 @@ void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { } else { Sym->Section = V.Sec; if (Sym->Section->Flags & SHF_ALLOC) - Sym->Value = V.Val; + Sym->Value = alignTo(V.Val, V.Alignment); else Sym->Value = V.getValue(); } @@ -290,6 +291,9 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { size_t SizeBefore = Ret.size(); for (InputSectionBase *Sec : InputSections) { + if (!isa(Sec)) + continue; + if (Sec->Assigned) continue; @@ -1076,6 +1080,9 @@ template void OutputSectionCommand::writeTo(uint8_t *Buf) { return; } + if (Sec->Type == SHT_NOBITS) + return; + // Write leading padding. ArrayRef Sections = Sec->Sections; uint32_t Filler = getFiller(); diff --git a/contrib/llvm/tools/lld/ELF/LinkerScript.h b/contrib/llvm/tools/lld/ELF/LinkerScript.h index e56e569d4e72..08f60f4517a7 100644 --- a/contrib/llvm/tools/lld/ELF/LinkerScript.h +++ b/contrib/llvm/tools/lld/ELF/LinkerScript.h @@ -41,7 +41,12 @@ struct ExprValue { SectionBase *Sec; uint64_t Val; bool ForceAbsolute; + uint64_t Alignment = 1; + ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val, + uint64_t Alignment) + : Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Alignment(Alignment) { + } ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val) : Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {} ExprValue(SectionBase *Sec, uint64_t Val) : ExprValue(Sec, false, Val) {} diff --git a/contrib/llvm/tools/lld/ELF/MapFile.cpp b/contrib/llvm/tools/lld/ELF/MapFile.cpp index 806e99e3d9dd..e0c7d8cd8b1b 100644 --- a/contrib/llvm/tools/lld/ELF/MapFile.cpp +++ b/contrib/llvm/tools/lld/ELF/MapFile.cpp @@ -100,7 +100,7 @@ getSymbolStrings(ArrayRef Syms) { } template -void elf::writeMapFile(llvm::ArrayRef Script) { +void elf::writeMapFile(llvm::ArrayRef Script) { if (Config->MapFile.empty()) return; @@ -123,10 +123,7 @@ void elf::writeMapFile(llvm::ArrayRef Script) { << " Align Out In Symbol\n"; // Print out file contents. - for (BaseCommand *Base : Script) { - auto *Cmd = dyn_cast(Base); - if (!Cmd) - continue; + for (OutputSectionCommand *Cmd : Script) { OutputSection *OSec = Cmd->Sec; writeHeader(OS, OSec->Addr, OSec->Size, OSec->Alignment); OS << OSec->Name << '\n'; @@ -147,7 +144,7 @@ void elf::writeMapFile(llvm::ArrayRef Script) { } } -template void elf::writeMapFile(ArrayRef); -template void elf::writeMapFile(ArrayRef); -template void elf::writeMapFile(ArrayRef); -template void elf::writeMapFile(ArrayRef); +template void elf::writeMapFile(ArrayRef); +template void elf::writeMapFile(ArrayRef); +template void elf::writeMapFile(ArrayRef); +template void elf::writeMapFile(ArrayRef); diff --git a/contrib/llvm/tools/lld/ELF/MapFile.h b/contrib/llvm/tools/lld/ELF/MapFile.h index f50ef00061ff..68d8ba8d4a04 100644 --- a/contrib/llvm/tools/lld/ELF/MapFile.h +++ b/contrib/llvm/tools/lld/ELF/MapFile.h @@ -14,8 +14,9 @@ namespace lld { namespace elf { -struct BaseCommand; -template void writeMapFile(llvm::ArrayRef Script); +struct OutputSectionCommand; +template +void writeMapFile(llvm::ArrayRef Script); } } diff --git a/contrib/llvm/tools/lld/ELF/OutputSections.cpp b/contrib/llvm/tools/lld/ELF/OutputSections.cpp index d82fdcdc31ba..f117690c3828 100644 --- a/contrib/llvm/tools/lld/ELF/OutputSections.cpp +++ b/contrib/llvm/tools/lld/ELF/OutputSections.cpp @@ -117,7 +117,7 @@ template static void finalizeShtGroup(OutputSection *Sec) { // the symbol table. Sec->Link = InX::SymTab->OutSec->SectionIndex; - // sh_link then contain index of an entry in symbol table section which + // sh_info then contain index of an entry in symbol table section which // provides signature of the section group. elf::ObjectFile *Obj = Sec->Sections[0]->getFile(); assert(Config->Relocatable && Sec->Sections.size() == 1); diff --git a/contrib/llvm/tools/lld/ELF/ScriptParser.cpp b/contrib/llvm/tools/lld/ELF/ScriptParser.cpp index f1bc245c9256..4b77e35b9bae 100644 --- a/contrib/llvm/tools/lld/ELF/ScriptParser.cpp +++ b/contrib/llvm/tools/lld/ELF/ScriptParser.cpp @@ -859,7 +859,11 @@ Expr ScriptParser::readPrimary() { expect(","); Expr E2 = readExpr(); expect(")"); - return [=] { return alignTo(E().getValue(), E2().getValue()); }; + return [=] { + ExprValue V = E(); + V.Alignment = E2().getValue(); + return V; + }; } if (Tok == "ALIGNOF") { StringRef Name = readParenLiteral(); diff --git a/contrib/llvm/tools/lld/ELF/Writer.cpp b/contrib/llvm/tools/lld/ELF/Writer.cpp index 0764d159edba..77ffe055b2de 100644 --- a/contrib/llvm/tools/lld/ELF/Writer.cpp +++ b/contrib/llvm/tools/lld/ELF/Writer.cpp @@ -74,6 +74,7 @@ template class Writer { std::unique_ptr Buffer; std::vector OutputSections; + std::vector OutputSectionCommands; OutputSectionFactory Factory{OutputSections}; void addRelIpltSymbols(); @@ -262,6 +263,10 @@ template void Writer::run() { Script->fabricateDefaultCommands(); } + for (BaseCommand *Base : Script->Opt.Commands) + if (auto *Cmd = dyn_cast(Base)) + OutputSectionCommands.push_back(Cmd); + // If -compressed-debug-sections is specified, we need to compress // .debug_* sections. Do it right now because it changes the size of // output sections. @@ -311,7 +316,7 @@ template void Writer::run() { // Handle -Map option. - writeMapFile(Script->Opt.Commands); + writeMapFile(OutputSectionCommands); if (ErrorCount) return; @@ -1201,8 +1206,6 @@ template void Writer::finalizeSections() { if (ErrorCount) return; - // So far we have added sections from input object files. - // This function adds linker-created Out::* sections. addPredefinedSections(); removeUnusedSyntheticSections(OutputSections); @@ -1270,8 +1273,20 @@ template void Writer::addPredefinedSections() { // ARM ABI requires .ARM.exidx to be terminated by some piece of data. // We have the terminater synthetic section class. Add that at the end. auto *OS = dyn_cast_or_null(findSection(".ARM.exidx")); - if (OS && !OS->Sections.empty() && !Config->Relocatable) - OS->addSection(make()); + if (!OS || OS->Sections.empty() || Config->Relocatable) + return; + + auto *Sentinel = make(); + OS->addSection(Sentinel); + // If there are linker script commands existing at this point then add the + // sentinel to the last of these too. + if (OutputSectionCommand *C = Script->getCmd(OS)) { + auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(), + [](const BaseCommand *Base) { + return isa(Base); + }); + cast(*ISD)->Sections.push_back(Sentinel); + } } // The linker is expected to define SECNAME_start and SECNAME_end @@ -1315,10 +1330,9 @@ void Writer::addStartStopSymbols(OutputSection *Sec) { template OutputSectionCommand *Writer::findSectionCommand(StringRef Name) { - for (BaseCommand *Base : Script->Opt.Commands) - if (auto *Cmd = dyn_cast(Base)) - if (Cmd->Name == Name) - return Cmd; + for (OutputSectionCommand *Cmd : OutputSectionCommands) + if (Cmd->Name == Name) + return Cmd; return nullptr; } @@ -1708,7 +1722,7 @@ template void Writer::writeHeader() { EHdr->e_ehsize = sizeof(Elf_Ehdr); EHdr->e_phnum = Phdrs.size(); EHdr->e_shentsize = sizeof(Elf_Shdr); - EHdr->e_shnum = OutputSections.size() + 1; + EHdr->e_shnum = OutputSectionCommands.size() + 1; EHdr->e_shstrndx = InX::ShStrTab->OutSec->SectionIndex; if (Config->EMachine == EM_ARM) @@ -1740,8 +1754,8 @@ template void Writer::writeHeader() { // Write the section header table. Note that the first table entry is null. auto *SHdrs = reinterpret_cast(Buf + EHdr->e_shoff); - for (OutputSection *Sec : OutputSections) - Sec->writeHeaderTo(++SHdrs); + for (OutputSectionCommand *Cmd : OutputSectionCommands) + Cmd->Sec->writeHeaderTo(++SHdrs); } // Open a result file. @@ -1764,10 +1778,7 @@ template void Writer::openFile() { template void Writer::writeSectionsBinary() { uint8_t *Buf = Buffer->getBufferStart(); - for (BaseCommand *Base : Script->Opt.Commands) { - auto *Cmd = dyn_cast(Base); - if (!Cmd) - continue; + for (OutputSectionCommand *Cmd : OutputSectionCommands) { OutputSection *Sec = Cmd->Sec; if (Sec->Flags & SHF_ALLOC) Cmd->writeTo(Buf + Sec->Offset); @@ -1794,19 +1805,13 @@ template void Writer::writeSections() { // In -r or -emit-relocs mode, write the relocation sections first as in // ELf_Rel targets we might find out that we need to modify the relocated // section while doing it. - for (BaseCommand *Base : Script->Opt.Commands) { - auto *Cmd = dyn_cast(Base); - if (!Cmd) - continue; + for (OutputSectionCommand *Cmd : OutputSectionCommands) { OutputSection *Sec = Cmd->Sec; if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) Cmd->writeTo(Buf + Sec->Offset); } - for (BaseCommand *Base : Script->Opt.Commands) { - auto *Cmd = dyn_cast(Base); - if (!Cmd) - continue; + for (OutputSectionCommand *Cmd : OutputSectionCommands) { OutputSection *Sec = Cmd->Sec; if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL && Sec->Type != SHT_RELA) diff --git a/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h b/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h index bfc0f4c9590a..d856fc81eb0d 100644 --- a/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h +++ b/contrib/llvm/tools/lldb/include/lldb/Utility/Log.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" // for StringMap #include "llvm/ADT/StringRef.h" // for StringRef, StringLiteral #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/RWMutex.h" #include @@ -30,9 +31,6 @@ namespace llvm { class raw_ostream; } -namespace llvm { -template class ManagedStatic; -} //---------------------------------------------------------------------- // Logging Options //---------------------------------------------------------------------- diff --git a/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp index b38b36532a71..78971eb5879a 100644 --- a/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp @@ -9,9 +9,9 @@ #include "C13DebugFragmentVisitor.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" @@ -25,25 +25,25 @@ C13DebugFragmentVisitor::C13DebugFragmentVisitor(PDBFile &F) : F(F) {} C13DebugFragmentVisitor::~C13DebugFragmentVisitor() {} Error C13DebugFragmentVisitor::visitUnknown( - codeview::ModuleDebugUnknownFragmentRef &Fragment) { + codeview::DebugUnknownSubsectionRef &Fragment) { return Error::success(); } Error C13DebugFragmentVisitor::visitFileChecksums( - codeview::ModuleDebugFileChecksumFragmentRef &Checksums) { + codeview::DebugChecksumsSubsectionRef &Checksums) { assert(!this->Checksums.hasValue()); this->Checksums = Checksums; return Error::success(); } Error C13DebugFragmentVisitor::visitLines( - codeview::ModuleDebugLineFragmentRef &Lines) { + codeview::DebugLinesSubsectionRef &Lines) { this->Lines.push_back(Lines); return Error::success(); } Error C13DebugFragmentVisitor::visitInlineeLines( - codeview::ModuleDebugInlineeLineFragmentRef &Lines) { + codeview::DebugInlineeLinesSubsectionRef &Lines) { this->InlineeLines.push_back(Lines); return Error::success(); } diff --git a/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h b/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h index 1054b0c9f6e0..a12f282c4c5c 100644 --- a/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h +++ b/contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h @@ -11,8 +11,8 @@ #define LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H #include "llvm/ADT/Optional.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" #include "llvm/Support/Error.h" #include @@ -23,20 +23,20 @@ namespace pdb { class PDBFile; -class C13DebugFragmentVisitor : public codeview::ModuleDebugFragmentVisitor { +class C13DebugFragmentVisitor : public codeview::DebugSubsectionVisitor { public: C13DebugFragmentVisitor(PDBFile &F); ~C13DebugFragmentVisitor(); - Error visitUnknown(codeview::ModuleDebugUnknownFragmentRef &Fragment) final; - - Error visitFileChecksums( - codeview::ModuleDebugFileChecksumFragmentRef &Checksums) final; - - Error visitLines(codeview::ModuleDebugLineFragmentRef &Lines) final; + Error visitUnknown(codeview::DebugUnknownSubsectionRef &Fragment) final; Error - visitInlineeLines(codeview::ModuleDebugInlineeLineFragmentRef &Lines) final; + visitFileChecksums(codeview::DebugChecksumsSubsectionRef &Checksums) final; + + Error visitLines(codeview::DebugLinesSubsectionRef &Lines) final; + + Error + visitInlineeLines(codeview::DebugInlineeLinesSubsectionRef &Lines) final; Error finished() final; @@ -48,9 +48,9 @@ class C13DebugFragmentVisitor : public codeview::ModuleDebugFragmentVisitor { Expected getNameFromStringTable(uint32_t Offset); Expected getNameFromChecksumsBuffer(uint32_t Offset); - Optional Checksums; - std::vector InlineeLines; - std::vector Lines; + Optional Checksums; + std::vector InlineeLines; + std::vector Lines; PDBFile &F; }; diff --git a/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 07d3b226d7c6..d95eca1aeddb 100644 --- a/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -15,14 +15,14 @@ #include "llvm-pdbdump.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" @@ -830,8 +830,8 @@ Error LLVMOutputStyle::dumpDbiStream() { return ExpectedTypes.takeError(); auto &IpiItems = *ExpectedTypes; C13RawVisitor V(P, File, IpiItems); - if (auto EC = codeview::visitModuleDebugFragments( - ModS.linesAndChecksums(), V)) + if (auto EC = + codeview::visitDebugSubsections(ModS.linesAndChecksums(), V)) return EC; } } diff --git a/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp index 652182e8e9b3..7aa68dee7d47 100644 --- a/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -13,13 +13,13 @@ #include "PdbYaml.h" #include "llvm-pdbdump.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" @@ -207,8 +207,8 @@ YAMLOutputStyle::getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS) { yaml::PdbSourceFileInfo Info; C13YamlVisitor Visitor(Info, File); - if (auto EC = codeview::visitModuleDebugFragments(ModS.linesAndChecksums(), - Visitor)) + if (auto EC = + codeview::visitDebugSubsections(ModS.linesAndChecksums(), Visitor)) return std::move(EC); return Info; diff --git a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index ff14c39cbaab..baba862ae663 100644 --- a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -31,10 +31,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" @@ -543,8 +543,7 @@ static void yamlToPdb(StringRef Path) { // File Checksums must be emitted before line information, because line // info records use offsets into the checksum buffer to reference a file's // source file name. - auto Checksums = - llvm::make_unique(Strings); + auto Checksums = llvm::make_unique(Strings); auto &ChecksumRef = *Checksums; if (!FLI.FileChecksums.empty()) { for (auto &FC : FLI.FileChecksums) @@ -554,7 +553,7 @@ static void yamlToPdb(StringRef Path) { for (const auto &Fragment : FLI.LineFragments) { auto Lines = - llvm::make_unique(ChecksumRef, Strings); + llvm::make_unique(ChecksumRef, Strings); Lines->setCodeSize(Fragment.CodeSize); Lines->setRelocationAddress(Fragment.RelocSegment, Fragment.RelocOffset); @@ -582,7 +581,7 @@ static void yamlToPdb(StringRef Path) { } for (const auto &Inlinee : FLI.Inlinees) { - auto Inlinees = llvm::make_unique( + auto Inlinees = llvm::make_unique( ChecksumRef, Inlinee.HasExtraFiles); for (const auto &Site : Inlinee.Sites) { Inlinees->addInlineSite(Site.Inlinee, Site.FileName, diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp index a59caa351e72..663f7b4c8a82 100644 --- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "ARMWinEHPrinter.h" -#include "CodeView.h" #include "Error.h" #include "ObjDumper.h" #include "StackMapPrinter.h" @@ -24,13 +23,14 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" @@ -157,9 +157,9 @@ class COFFDumper : public ObjDumper { bool RelocCached = false; RelocMapTy RelocMap; - VarStreamArray CVFileChecksumTable; + DebugChecksumsSubsectionRef CVFileChecksumTable; - StringTableRef CVStringTable; + DebugStringTableSubsectionRef CVStringTable; ScopedPrinter &Writer; BinaryByteStream TypeContents; @@ -200,7 +200,9 @@ class COFFObjectDumpDelegate : public SymbolDumpDelegate { return CD.getFileNameForFileOffset(FileOffset); } - StringTableRef getStringTable() override { return CD.CVStringTable; } + DebugStringTableSubsectionRef getStringTable() override { + return CD.CVStringTable; + } private: COFFDumper &CD; @@ -515,19 +517,19 @@ WeakExternalCharacteristics[] = { }; static const EnumEntry SubSectionTypes[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Symbols), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Lines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, StringTable), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FileChecksums), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FrameData), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, InlineeLines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeImports), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeExports), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, ILLines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FuncMDTokenMap), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, TypeMDTokenMap), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, MergedAssemblyInput), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CoffSymbolRVA), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, Symbols), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, Lines), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, StringTable), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FileChecksums), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FrameData), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, InlineeLines), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeImports), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeExports), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, ILLines), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FuncMDTokenMap), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, TypeMDTokenMap), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, MergedAssemblyInput), + LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CoffSymbolRVA), }; static const EnumEntry FrameDataFlags[] = { @@ -774,16 +776,14 @@ void COFFDumper::initializeFileAndStringTables(BinaryStreamReader &Reader) { StringRef Contents; error(Reader.readFixedString(Contents, SubSectionSize)); - switch (ModuleDebugFragmentKind(SubType)) { - case ModuleDebugFragmentKind::FileChecksums: { - BinaryStreamReader CSR(Contents, support::little); - error(CSR.readArray(CVFileChecksumTable, CSR.getLength())); + BinaryStreamRef ST(Contents, support::little); + switch (DebugSubsectionKind(SubType)) { + case DebugSubsectionKind::FileChecksums: + error(CVFileChecksumTable.initialize(ST)); break; - } - case ModuleDebugFragmentKind::StringTable: { - BinaryStreamRef ST(Contents, support::little); + case DebugSubsectionKind::StringTable: error(CVStringTable.initialize(ST)); - } break; + break; default: break; } @@ -847,20 +847,20 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, printBinaryBlockWithRelocs("SubSectionContents", Section, SectionContents, Contents); - switch (ModuleDebugFragmentKind(SubType)) { - case ModuleDebugFragmentKind::Symbols: + switch (DebugSubsectionKind(SubType)) { + case DebugSubsectionKind::Symbols: printCodeViewSymbolsSubsection(Contents, Section, SectionContents); break; - case ModuleDebugFragmentKind::InlineeLines: + case DebugSubsectionKind::InlineeLines: printCodeViewInlineeLines(Contents); break; - case ModuleDebugFragmentKind::FileChecksums: + case DebugSubsectionKind::FileChecksums: printCodeViewFileChecksums(Contents); break; - case ModuleDebugFragmentKind::Lines: { + case DebugSubsectionKind::Lines: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the // pointers for deferred processing. @@ -886,34 +886,33 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, FunctionNames.push_back(LinkageName); break; } - case ModuleDebugFragmentKind::FrameData: { + case DebugSubsectionKind::FrameData: { // First four bytes is a relocation against the function. BinaryStreamReader SR(Contents, llvm::support::little); - const uint32_t *CodePtr; - error(SR.readObject(CodePtr)); + + DebugFrameDataSubsectionRef FrameData; + error(FrameData.initialize(SR)); + StringRef LinkageName; error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents, - CodePtr, LinkageName)); + FrameData.getRelocPtr(), LinkageName)); W.printString("LinkageName", LinkageName); // To find the active frame description, search this array for the // smallest PC range that includes the current PC. - while (!SR.empty()) { - const FrameData *FD; - error(SR.readObject(FD)); - - StringRef FrameFunc = error(CVStringTable.getString(FD->FrameFunc)); + for (const auto &FD : FrameData) { + StringRef FrameFunc = error(CVStringTable.getString(FD.FrameFunc)); DictScope S(W, "FrameData"); - W.printHex("RvaStart", FD->RvaStart); - W.printHex("CodeSize", FD->CodeSize); - W.printHex("LocalSize", FD->LocalSize); - W.printHex("ParamsSize", FD->ParamsSize); - W.printHex("MaxStackSize", FD->MaxStackSize); + W.printHex("RvaStart", FD.RvaStart); + W.printHex("CodeSize", FD.CodeSize); + W.printHex("LocalSize", FD.LocalSize); + W.printHex("ParamsSize", FD.ParamsSize); + W.printHex("MaxStackSize", FD.MaxStackSize); W.printString("FrameFunc", FrameFunc); - W.printHex("PrologSize", FD->PrologSize); - W.printHex("SavedRegsSize", FD->SavedRegsSize); - W.printFlags("Flags", FD->Flags, makeArrayRef(FrameDataFlags)); + W.printHex("PrologSize", FD.PrologSize); + W.printHex("SavedRegsSize", FD.SavedRegsSize); + W.printFlags("Flags", FD.Flags, makeArrayRef(FrameDataFlags)); } break; } @@ -934,7 +933,7 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, BinaryStreamReader Reader(FunctionLineTables[Name], support::little); - ModuleDebugLineFragmentRef LineInfo; + DebugLinesSubsectionRef LineInfo; error(LineInfo.initialize(Reader)); W.printHex("Flags", LineInfo.header()->Flags); @@ -996,9 +995,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, } void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { - BinaryStreamReader SR(Subsection, llvm::support::little); - ModuleDebugFileChecksumFragmentRef Checksums; - error(Checksums.initialize(SR)); + BinaryStreamRef Stream(Subsection, llvm::support::little); + DebugChecksumsSubsectionRef Checksums; + error(Checksums.initialize(Stream)); for (auto &FC : Checksums) { DictScope S(W, "FileChecksum"); @@ -1015,7 +1014,7 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { BinaryStreamReader SR(Subsection, llvm::support::little); - ModuleDebugInlineeLineFragmentRef Lines; + DebugInlineeLinesSubsectionRef Lines; error(Lines.initialize(SR)); for (auto &Line : Lines) { @@ -1039,7 +1038,7 @@ StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) { if (!CVFileChecksumTable.valid() || !CVStringTable.valid()) error(object_error::parse_failed); - auto Iter = CVFileChecksumTable.at(FileOffset); + auto Iter = CVFileChecksumTable.getArray().at(FileOffset); // Check if the file checksum table offset is valid. if (Iter == CVFileChecksumTable.end()) diff --git a/contrib/llvm/tools/llvm-readobj/CodeView.h b/contrib/llvm/tools/llvm-readobj/CodeView.h deleted file mode 100644 index cf713962eb7f..000000000000 --- a/contrib/llvm/tools/llvm-readobj/CodeView.h +++ /dev/null @@ -1,54 +0,0 @@ -//===-- CodeView.h - On-disk record types for CodeView ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file provides data structures useful for consuming on-disk -/// CodeView. It is based on information published by Microsoft at -/// https://github.com/Microsoft/microsoft-pdb/. -/// -//===----------------------------------------------------------------------===// - -// FIXME: Find a home for this in include/llvm/DebugInfo/CodeView/. - -#ifndef LLVM_READOBJ_CODEVIEW_H -#define LLVM_READOBJ_CODEVIEW_H - -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/Support/Endian.h" - -namespace llvm { -namespace codeview { - -using llvm::support::ulittle16_t; -using llvm::support::ulittle32_t; - -/// Data in the the SUBSEC_FRAMEDATA subection. -struct FrameData { - ulittle32_t RvaStart; - ulittle32_t CodeSize; - ulittle32_t LocalSize; - ulittle32_t ParamsSize; - ulittle32_t MaxStackSize; - ulittle32_t FrameFunc; - ulittle16_t PrologSize; - ulittle16_t SavedRegsSize; - ulittle32_t Flags; - enum : uint32_t { - HasSEH = 1 << 0, - HasEH = 1 << 1, - IsFunctionStart = 1 << 2, - }; -}; - - -} // namespace codeview -} // namespace llvm - -#endif // LLVM_READOBJ_CODEVIEW_H diff --git a/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp index 185119c2ca43..e0303b7b1ab4 100644 --- a/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -1602,7 +1602,7 @@ Expected GlobalISelEmitter::createAndImportInstructionRenderer( Error GlobalISelEmitter::importDefaultOperandRenderers( BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const { - for (const auto *DefaultOp : DefaultOps->args()) { + for (const auto *DefaultOp : DefaultOps->getArgs()) { // Look through ValueType operators. if (const DagInit *DefaultDagOp = dyn_cast(DefaultOp)) { if (const DefInit *DefaultDagOperator = diff --git a/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp index f211a8fab975..99429c5f96a2 100644 --- a/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp @@ -77,7 +77,14 @@ const char *const NoFoldSet[] = { "TCRETURNri64", "TCRETURNmi64", // Special dealing (in X86InstrCompiler.td under "TCRETURNri", // "tailcall stuff" section). - "TCRETURNmi" + "TCRETURNmi", + + // Never fold XCHG, the register and memory forms have different locking + // semantics. + "XCHG8rr", "XCHG8rm", + "XCHG16rr", "XCHG16rm", + "XCHG32rr", "XCHG32rm", + "XCHG64rr", "XCHG64rm", // Different calculations of the folded operand between // memory and register forms (folding is illegal). diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc index 8582fb633217..9dbc027a199e 100644 --- a/lib/clang/include/clang/Basic/Version.inc +++ b/lib/clang/include/clang/Basic/Version.inc @@ -8,4 +8,4 @@ #define CLANG_VENDOR "FreeBSD " -#define SVN_REVISION "304149" +#define SVN_REVISION "304222" diff --git a/lib/clang/include/lld/Config/Version.inc b/lib/clang/include/lld/Config/Version.inc index 38c939fa0f02..15c946554a54 100644 --- a/lib/clang/include/lld/Config/Version.inc +++ b/lib/clang/include/lld/Config/Version.inc @@ -4,5 +4,5 @@ #define LLD_VERSION_STRING "5.0.0" #define LLD_VERSION_MAJOR 5 #define LLD_VERSION_MINOR 0 -#define LLD_REVISION_STRING "304149" +#define LLD_REVISION_STRING "304222" #define LLD_REPOSITORY_STRING "FreeBSD" diff --git a/lib/clang/include/llvm/Support/VCSRevision.h b/lib/clang/include/llvm/Support/VCSRevision.h index b1f0f34b4cb8..dabb12fee8d0 100644 --- a/lib/clang/include/llvm/Support/VCSRevision.h +++ b/lib/clang/include/llvm/Support/VCSRevision.h @@ -1,2 +1,2 @@ /* $FreeBSD$ */ -#define LLVM_REVISION "svn-r304149" +#define LLVM_REVISION "svn-r304222" diff --git a/lib/clang/libclang/Makefile b/lib/clang/libclang/Makefile index 76730e156e2c..4c5ec9d27f2c 100644 --- a/lib/clang/libclang/Makefile +++ b/lib/clang/libclang/Makefile @@ -466,7 +466,7 @@ SRCS_FUL+= StaticAnalyzer/Checkers/FixedAddressChecker.cpp SRCS_FUL+= StaticAnalyzer/Checkers/GTestChecker.cpp SRCS_FUL+= StaticAnalyzer/Checkers/GenericTaintChecker.cpp SRCS_FUL+= StaticAnalyzer/Checkers/IdenticalExprChecker.cpp -SRCS_FUL+= StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp +SRCS_FUL+= StaticAnalyzer/Checkers/IteratorChecker.cpp SRCS_FUL+= StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp SRCS_FUL+= StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp SRCS_FUL+= StaticAnalyzer/Checkers/LocalizationChecker.cpp diff --git a/lib/clang/libllvm/Makefile b/lib/clang/libllvm/Makefile index 028458907136..9aed261278f0 100644 --- a/lib/clang/libllvm/Makefile +++ b/lib/clang/libllvm/Makefile @@ -328,18 +328,20 @@ SRCS_MIN+= DebugInfo/CodeView/CVSymbolVisitor.cpp SRCS_MIN+= DebugInfo/CodeView/CVTypeVisitor.cpp SRCS_MIN+= DebugInfo/CodeView/CodeViewError.cpp SRCS_MIN+= DebugInfo/CodeView/CodeViewRecordIO.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugChecksumsSubsection.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugFrameDataSubsection.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugLinesSubsection.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugStringTableSubsection.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugSubsection.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugSubsectionRecord.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugSubsectionVisitor.cpp +SRCS_EXT+= DebugInfo/CodeView/DebugSymbolsSubsection.cpp SRCS_EXT+= DebugInfo/CodeView/EnumTables.cpp SRCS_MIN+= DebugInfo/CodeView/Formatters.cpp SRCS_EXT+= DebugInfo/CodeView/LazyRandomTypeCollection.cpp SRCS_MIN+= DebugInfo/CodeView/Line.cpp -SRCS_EXT+= DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp -SRCS_EXT+= DebugInfo/CodeView/ModuleDebugFragment.cpp -SRCS_EXT+= DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp -SRCS_EXT+= DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp -SRCS_EXT+= DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp -SRCS_EXT+= DebugInfo/CodeView/ModuleDebugLineFragment.cpp SRCS_MIN+= DebugInfo/CodeView/RecordSerialization.cpp -SRCS_EXT+= DebugInfo/CodeView/StringTable.cpp SRCS_MIN+= DebugInfo/CodeView/SymbolDumper.cpp SRCS_MIN+= DebugInfo/CodeView/SymbolRecordMapping.cpp SRCS_EXT+= DebugInfo/CodeView/SymbolSerializer.cpp