aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/libc++/include/experimental/coroutine30
-rw-r--r--contrib/libc++/include/module.modulemap1
-rw-r--r--contrib/llvm/include/llvm/Analysis/ScalarEvolution.h3
-rw-r--r--contrib/llvm/include/llvm/CodeGen/DIE.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h22
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h)37
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h59
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h)37
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h)32
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/StringTable.h)39
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsection.h52
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h)39
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h)34
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h53
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h (renamed from contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h)11
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h48
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h23
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h7
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h4
-rw-r--r--contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h10
-rw-r--r--contrib/llvm/include/llvm/MC/ConstantPools.h3
-rw-r--r--contrib/llvm/include/llvm/Support/ManagedStatic.h20
-rw-r--r--contrib/llvm/include/llvm/TableGen/Record.h18
-rw-r--r--contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h11
-rw-r--r--contrib/llvm/lib/Analysis/ScalarEvolution.cpp7
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp17
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h2
-rw-r--r--contrib/llvm/lib/CodeGen/GlobalISel/Localizer.cpp2
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp3
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp5
-rw-r--r--contrib/llvm/lib/CodeGen/TargetLoweringBase.cpp1
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp)33
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp44
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.cpp)38
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp)52
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/StringTable.cpp)27
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp (renamed from contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp)8
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp81
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp52
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp34
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/EnumTables.cpp28
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp84
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp52
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp6
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp18
-rw-r--r--contrib/llvm/lib/MC/MCCodeView.cpp6
-rw-r--r--contrib/llvm/lib/Support/APFloat.cpp2
-rw-r--r--contrib/llvm/lib/Support/Timer.cpp13
-rw-r--r--contrib/llvm/lib/TableGen/Record.cpp28
-rw-r--r--contrib/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp35
-rw-r--r--contrib/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp3
-rw-r--r--contrib/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h2
-rw-r--r--contrib/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp3
-rw-r--r--contrib/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp7
-rw-r--r--contrib/llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp49
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp4
-rw-r--r--contrib/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp2
-rw-r--r--contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp387
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp1
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsInstrFPU.td23
-rw-r--r--contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td27
-rw-r--r--contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp3
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZ.td2
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZFeatures.td14
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp60
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrDFP.td231
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrFP.td19
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrFormats.td97
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZInstrHFP.td240
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ13.td232
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZScheduleZ196.td219
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZScheduleZEC12.td225
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp2
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZSubtarget.h8
-rw-r--r--contrib/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp4
-rw-r--r--contrib/llvm/lib/Target/X86/X86ISelLowering.cpp81
-rw-r--r--contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp55
-rw-r--r--contrib/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp21
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td2
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td9
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h5
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h6
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h10
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h3
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td8
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h13
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h10
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGCoroutine.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Frontend/SerializedDiagnosticPrinter.cpp2
-rw-r--r--contrib/llvm/tools/clang/lib/Headers/altivec.h106
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Lexer.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp41
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/PPLexerChange.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Pragma.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/Preprocessor.cpp9
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp43
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp15
-rw-r--r--contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp13
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp83
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp833
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IteratorPastEndChecker.cpp840
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp146
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ProgramState.cpp100
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/RegionStore.cpp5
-rw-r--r--contrib/llvm/tools/lld/ELF/LinkerScript.cpp13
-rw-r--r--contrib/llvm/tools/lld/ELF/LinkerScript.h5
-rw-r--r--contrib/llvm/tools/lld/ELF/MapFile.cpp15
-rw-r--r--contrib/llvm/tools/lld/ELF/MapFile.h5
-rw-r--r--contrib/llvm/tools/lld/ELF/OutputSections.cpp2
-rw-r--r--contrib/llvm/tools/lld/ELF/ScriptParser.cpp6
-rw-r--r--contrib/llvm/tools/lld/ELF/Writer.cpp53
-rw-r--r--contrib/llvm/tools/lldb/include/lldb/Utility/Log.h4
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp14
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/C13DebugFragmentVisitor.h22
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp14
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp16
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp13
-rw-r--r--contrib/llvm/tools/llvm-readobj/COFFDumper.cpp113
-rw-r--r--contrib/llvm/tools/llvm-readobj/CodeView.h54
-rw-r--r--contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/X86FoldTablesEmitter.cpp9
-rw-r--r--lib/clang/include/clang/Basic/Version.inc2
-rw-r--r--lib/clang/include/lld/Config/Version.inc2
-rw-r--r--lib/clang/include/llvm/Support/VCSRevision.h2
-rw-r--r--lib/clang/libclang/Makefile2
-rw-r--r--lib/clang/libllvm/Makefile16
133 files changed, 4227 insertions, 1963 deletions
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 <class _Tp, bool _CallIsValid = false>
+ static coroutine_handle from_address(_Tp*) {
+ static_assert(_CallIsValid,
+ "coroutine_handle<void>::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);
+ }
+
+ template <class _Tp, bool _CallIsValid = false>
+ static coroutine_handle from_address(_Tp*) {
+ static_assert(_CallIsValid,
+ "coroutine_handle<promise_type>::from_address cannot be called with "
+ "non-void pointers");
}
- // from_address cannot be used with the coroutines promise type.
- static coroutine_handle from_address(_Promise*) = delete;
+ template <bool _CallIsValid = false>
+ static coroutine_handle from_address(_Promise*) {
+ static_assert(_CallIsValid,
+ "coroutine_handle<promise_type>::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 @@ public:
/// 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 @@ private:
return;
#define HANDLE_DIEVALUE_SMALL(T) \
case is##T: \
- destruct<DIE##T>();
+ destruct<DIE##T>(); \
return;
#define HANDLE_DIEVALUE_LARGE(T) \
case is##T: \
- destruct<const DIE##T *>();
+ destruct<const DIE##T *>(); \
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 <cinttypes>
#include <type_traits>
+#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
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 @@ public:
namespace llvm {
namespace codeview {
-class ModuleDebugFileChecksumFragmentRef final : public ModuleDebugFragmentRef {
+class DebugChecksumsSubsectionRef final : public DebugSubsectionRef {
typedef VarStreamArray<codeview::FileChecksumEntry> 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 @@ private:
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<uint8_t> 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<uint32_t, uint32_t> 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<FrameData>::Iterator begin() const { return Frames.begin(); }
+ FixedStreamArray<FrameData>::Iterator end() const { return Frames.end(); }
+
+ const void *getRelocPtr() const { return RelocPtr; }
+
+private:
+ const uint32_t *RelocPtr = nullptr;
+ FixedStreamArray<FrameData> 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<FrameData> Frames;
+};
+}
+}
+
+#endif
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h b/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<codeview::InlineeSourceLine> {
};
namespace codeview {
-class ModuleDebugInlineeLineFragmentRef final : public ModuleDebugFragmentRef {
+class DebugInlineeLinesSubsectionRef final : public DebugSubsectionRef {
typedef VarStreamArray<InlineeSourceLine> 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 @@ private:
VarStreamArray<InlineeSourceLine> 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
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 @@ public:
LineColumnEntry &Item, const LineFragmentHeader *Ctx);
};
-class ModuleDebugLineFragmentRef final : public ModuleDebugFragmentRef {
+class DebugLinesSubsectionRef final : public DebugSubsectionRef {
friend class LineColumnExtractor;
typedef VarStreamArray<LineColumnEntry, LineColumnExtractor> 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 @@ private:
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 @@ public:
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 @@ public:
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
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 @@ private:
BinaryStreamRef Stream;
};
-/// Represents a read-write view of a CodeView string table. StringTable owns
-/// the underlying storage for the table, and is capable of serializing the
-/// string table into a format understood by StringTableRef.
-class StringTable {
+/// 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 @@ public:
// 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
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<codeview::ModuleDebugFragmentRecord> {
+template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> {
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<codeview::ModuleDebugFragmentRecord> {
};
namespace codeview {
-typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray;
+typedef VarStreamArray<DebugSubsectionRecord> DebugSubsectionArray;
}
} // namespace llvm
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h b/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 <typename T>
-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<CVSymbol> Records;
+};
+}
+}
+
+#endif
diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h b/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 @@ public:
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 @@ public:
void setObjFileName(StringRef Name);
void addSymbol(codeview::CVSymbol Symbol);
- void addC13Fragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
+ void addC13Fragment(std::unique_ptr<codeview::DebugLinesSubsection> Lines);
void addC13Fragment(
- std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees);
+ std::unique_ptr<codeview::DebugInlineeLinesSubsection> Inlinees);
void setC13FileChecksums(
- std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> Checksums);
+ std::unique_ptr<codeview::DebugChecksumsSubsection> Checksums);
uint16_t getStreamIndex() const;
StringRef getModuleName() const { return ModuleName; }
@@ -83,12 +83,11 @@ private:
std::vector<std::string> SourceFiles;
std::vector<codeview::CVSymbol> Symbols;
- std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> ChecksumInfo;
- std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
- std::vector<std::unique_ptr<codeview::ModuleDebugInlineeLineFragment>>
- Inlinees;
+ std::unique_ptr<codeview::DebugChecksumsSubsection> ChecksumInfo;
+ std::vector<std::unique_ptr<codeview::DebugLinesSubsection>> LineInfo;
+ std::vector<std::unique_ptr<codeview::DebugInlineeLinesSubsection>> Inlinees;
- std::vector<std::unique_ptr<codeview::ModuleDebugFragmentRecordBuilder>>
+ std::vector<std::unique_ptr<codeview::DebugSubsectionRecordBuilder>>
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 @@ private:
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 @@ private:
Error readEpilogue(BinaryStreamReader &Reader);
const PDBStringTableHeader *Header = nullptr;
- codeview::StringTableRef Strings;
+ codeview::DebugStringTableSubsectionRef Strings;
FixedStreamArray<support::ulittle32_t> 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 <vector>
@@ -41,8 +41,10 @@ public:
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 @@ private:
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 <cstdint>
+#include <map>
namespace llvm {
@@ -44,7 +45,7 @@ struct ConstantPoolEntry {
class ConstantPool {
using EntryVecTy = SmallVector<ConstantPoolEntry, 4>;
EntryVecTy Entries;
- DenseMap<int64_t, const MCSymbolRefExpr *> CachedEntries;
+ std::map<int64_t, const MCSymbolRefExpr *> 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 <atomic>
#include <cstddef>
namespace llvm {
/// object_creator - Helper method for ManagedStatic.
-template<class C>
-LLVM_LIBRARY_VISIBILITY void* object_creator() {
- return new C();
-}
+template <class C> struct object_creator {
+ static void *call() { return new C(); }
+};
/// object_deleter - Helper method for ManagedStatic.
///
-template <typename T> struct LLVM_LIBRARY_VISIBILITY object_deleter {
+template <typename T> struct object_deleter {
static void call(void *Ptr) { delete (T *)Ptr; }
};
-template <typename T, size_t N>
-struct LLVM_LIBRARY_VISIBILITY object_deleter<T[N]> {
+template <typename T, size_t N> struct object_deleter<T[N]> {
static void call(void *Ptr) { delete[](T *)Ptr; }
};
@@ -59,14 +56,15 @@ public:
/// libraries that link in LLVM components) and for making destruction be
/// explicit through the llvm_shutdown() function call.
///
-template<class C>
+template <class C, class Creator = object_creator<C>,
+ class Deleter = object_deleter<C>>
class ManagedStatic : public ManagedStaticBase {
public:
// Accessors.
C &operator*() {
void *Tmp = Ptr.load(std::memory_order_acquire);
if (!Tmp)
- RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
+ RegisterManagedStatic(Creator::call, Deleter::call);
return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
}
@@ -76,7 +74,7 @@ public:
const C &operator*() const {
void *Tmp = Ptr.load(std::memory_order_acquire);
if (!Tmp)
- RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
+ RegisterManagedStatic(Creator::call, Deleter::call);
return *static_cast<C *>(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 @@ public:
return Init ? Init->getValue() : StringRef();
}
+ ArrayRef<Init *> getArgs() const {
+ return makeArrayRef(getTrailingObjects<Init *>(), NumArgs);
+ }
ArrayRef<StringInit *> getArgNames() const {
return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
}
@@ -1200,19 +1203,16 @@ public:
typedef SmallVectorImpl<Init*>::const_iterator const_arg_iterator;
typedef SmallVectorImpl<StringInit*>::const_iterator const_name_iterator;
- inline const_arg_iterator arg_begin() const { return getTrailingObjects<Init *>(); }
- inline const_arg_iterator arg_end () const { return arg_begin() + NumArgs; }
- inline iterator_range<const_arg_iterator> 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<StringInit *>(); }
- 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 @@ public:
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<unsigned>(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<const SCEV *> &Ops,
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(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<const SCEV *> &Ops,
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(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<LoadSDNode>(Extract->getOperand(0));
auto *ExtIdx = dyn_cast<ConstantSDNode>(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
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<FileChecksumEntry>::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<uint8_t> Bytes) {
+void DebugChecksumsSubsection::addChecksum(StringRef FileName,
+ FileChecksumKind Kind,
+ ArrayRef<uint8_t> Bytes) {
FileChecksumEntry Entry;
if (!Bytes.empty()) {
uint8_t *Copy = Storage.Allocate<uint8_t>(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<CodeViewError>(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<uint32_t>(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
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<InlineeSourceLine>::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
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
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<StringRef> StringTableRef::getString(uint32_t Offset) const {
+Expected<StringRef>
+DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
BinaryStreamReader Reader(Stream);
Reader.setOffset(Offset);
StringRef Result;
@@ -32,7 +34,10 @@ Expected<StringRef> 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
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<DebugSubsectionKind>(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<uint32_t> FrameProcSymFlagNames[] = {
};
static const EnumEntry<uint32_t> 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<uint16_t> 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<ModuleDebugFragmentKind>(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<ModuleDebugLineFragment> Lines) {
- ModuleDebugLineFragment &Frag = *Lines;
+ std::unique_ptr<DebugLinesSubsection> 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<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+ llvm::make_unique<DebugSubsectionRecordBuilder>(Frag.kind(), Frag));
}
void DbiModuleDescriptorBuilder::addC13Fragment(
- std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees) {
- ModuleDebugInlineeLineFragment &Frag = *Inlinees;
+ std::unique_ptr<codeview::DebugInlineeLinesSubsection> 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<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+ llvm::make_unique<DebugSubsectionRecordBuilder>(Frag.kind(), Frag));
}
void DbiModuleDescriptorBuilder::setC13FileChecksums(
- std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) {
+ std::unique_ptr<DebugChecksumsSubsection> 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<ModuleDebugFragmentRecordBuilder>(
+ C13Builders[0] = llvm::make_unique<DebugSubsectionRecordBuilder>(
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<raw_fd_ostream> llvm::CreateInfoOutputFile() {
return llvm::make_unique<raw_fd_ostream>(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<TimerGroup, CreateDefaultTimerGroup> 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<unsigned> Bits) const {
}
CodeInit *CodeInit::get(StringRef V) {
- static DenseMap<StringRef, CodeInit*> ThePool;
+ static StringMap<CodeInit*, BumpPtrAllocator &> 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<StringRef, StringInit*> ThePool;
+ static StringMap<StringInit*, BumpPtrAllocator &> 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<Init*, 8> 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<bool> 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 @@ public:
/// \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<FoldCandidate> &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<MachineInstr *> &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 @@ private:
std::unordered_map<MachineInstr *, std::unique_ptr<SDWAOperand>> SDWAOperands;
std::unordered_map<MachineInstr *, SDWAOperandsVector> PotentialMatches;
+ SmallVector<MachineInstr *, 8> ConvertedInstructions;
Optional<int64_t> foldToImm(const MachineOperand &Op) const;
@@ -69,6 +70,7 @@ public:
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<SISubtarget>();
@@ -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 @@ public:
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 @@ public:
"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 @@ public:
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<float>(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 $<reg> offset($reg2)' to 'lw $<reg>, offset($reg2);
// lw $<reg+1>>, offset+4($reg2)'
// or expand 'sd $<reg> offset($reg2)' to 'sw $<reg>, 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<AFGR64> {
let ParserMatchClass = AFGR64AsmOperand;
}
+def StrictlyAFGR64Opnd : RegisterOperand<AFGR64> {
+ let ParserMatchClass = StrictlyAFGR64AsmOperand;
+}
+
def FGR64Opnd : RegisterOperand<FGR64> {
let ParserMatchClass = FGR64AsmOperand;
}
+def StrictlyFGR64Opnd : RegisterOperand<FGR64> {
+ let ParserMatchClass = StrictlyFGR64AsmOperand;
+}
+
def FGR32Opnd : RegisterOperand<FGR32> {
let ParserMatchClass = FGR32AsmOperand;
}
+def StrictlyFGR32Opnd : RegisterOperand<FGR32> {
+ let ParserMatchClass = StrictlyFGR32AsmOperand;
+}
+
def FGRCCOpnd : RegisterOperand<FGRCC> {
// 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<LoadSDNode>(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,
// <ABxx> <CDxx>
// V VMRHG
// <ABCD>
- 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<LoadSDNode>(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<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{3-0} = R2;
}
+class InstRRFd<bits<16> op, dag outs, dag ins, string asmstr, list<dag> 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<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<4, outs, ins, asmstr, pattern> {
field bits<32> Inst;
@@ -725,6 +741,22 @@ class InstRSLa<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{7-0} = op{7-0};
}
+class InstRSLb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> 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<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
@@ -2752,6 +2784,15 @@ class BinaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator,
let DisableEncoding = "$R1src";
}
+class BinaryRRD<string mnemonic, bits<16> opcode, SDPatternOperator operator,
+ RegisterOperand cls1, RegisterOperand cls2>
+ : InstRRD<opcode, (outs cls1:$R1), (ins cls2:$R3, cls2:$R2),
+ mnemonic#"\t$R1, $R3, $R2",
+ [(set cls1:$R1, (operator cls2:$R3, cls2:$R2))]> {
+ let OpKey = mnemonic#cls;
+ let OpType = "reg";
+}
+
class BinaryRRFa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
RegisterOperand cls1, RegisterOperand cls2,
RegisterOperand cls3>
@@ -2808,6 +2849,11 @@ multiclass BinaryMemRRFcOpt<string mnemonic, bits<16> opcode,
def Opt : UnaryMemRRFc<mnemonic, opcode, cls1, cls2>;
}
+class BinaryRRFd<string mnemonic, bits<16> opcode, RegisterOperand cls1,
+ RegisterOperand cls2>
+ : InstRRFd<opcode, (outs cls1:$R1), (ins cls2:$R2, imm32zx4:$M4),
+ mnemonic#"\t$R1, $R2, $M4", []>;
+
class BinaryRRFe<string mnemonic, bits<16> opcode, RegisterOperand cls1,
RegisterOperand cls2>
: InstRRFe<opcode, (outs cls1:$R1), (ins imm32zx4:$M3, cls2:$R2),
@@ -2958,6 +3004,13 @@ multiclass BinaryRSAndK<string mnemonic, bits<8> opcode1, bits<16> opcode2,
}
}
+class BinaryRSL<string mnemonic, bits<16> opcode, RegisterOperand cls>
+ : InstRSLb<opcode, (outs cls:$R1),
+ (ins bdladdr12onlylen8:$BDL2, imm32zx4:$M3),
+ mnemonic#"\t$R1, $BDL2, $M3", []> {
+ let mayLoad = 1;
+}
+
class BinaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator,
RegisterOperand cls, SDPatternOperator load, bits<5> bytes,
AddressingMode mode = bdxaddr12only>
@@ -2987,6 +3040,18 @@ class BinaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator,
let M3 = 0;
}
+class BinaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator,
+ RegisterOperand cls1, RegisterOperand cls2,
+ SDPatternOperator load, bits<5> bytes>
+ : InstRXF<opcode, (outs cls1:$R1), (ins cls2:$R3, bdxaddr12only:$XBD2),
+ mnemonic#"\t$R1, $R3, $XBD2",
+ [(set cls1:$R1, (operator cls2:$R3, (load bdxaddr12only:$XBD2)))]> {
+ let OpKey = mnemonic#"r"#cls;
+ let OpType = "mem";
+ let mayLoad = 1;
+ let AccessBytes = bytes;
+}
+
class BinaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator,
RegisterOperand cls, SDPatternOperator load, bits<5> bytes,
AddressingMode mode = bdxaddr20only>
@@ -3294,6 +3359,13 @@ multiclass StoreBinaryRSPair<string mnemonic, bits<8> rsOpcode,
}
}
+class StoreBinaryRSL<string mnemonic, bits<16> opcode, RegisterOperand cls>
+ : InstRSLb<opcode, (outs),
+ (ins cls:$R1, bdladdr12onlylen8:$BDL2, imm32zx4:$M3),
+ mnemonic#"\t$R1, $BDL2, $M3", []> {
+ let mayStore = 1;
+}
+
class StoreBinaryVRV<string mnemonic, bits<16> opcode, bits<5> bytes,
Immediate index>
: InstVRV<opcode, (outs), (ins VR128:$V1, bdvaddr12only:$VBD2, index:$M3),
@@ -3581,6 +3653,12 @@ class SideEffectTernarySSF<string mnemonic, bits<12> opcode,
(ins bdaddr12only:$BD1, bdaddr12only:$BD2, cls:$R3),
mnemonic#"\t$BD1, $BD2, $R3", []>;
+class TernaryRRFa<string mnemonic, bits<16> opcode,
+ RegisterOperand cls1, RegisterOperand cls2,
+ RegisterOperand cls3>
+ : InstRRFa<opcode, (outs cls1:$R1), (ins cls2:$R2, cls3:$R3, imm32zx4:$M4),
+ mnemonic#"\t$R1, $R2, $R3, $M4", []>;
+
class TernaryRRFb<string mnemonic, bits<16> opcode,
RegisterOperand cls1, RegisterOperand cls2,
RegisterOperand cls3>
@@ -3597,11 +3675,11 @@ class TernaryRRFe<string mnemonic, bits<16> opcode, RegisterOperand cls1,
(ins imm32zx4:$M3, cls2:$R2, imm32zx4:$M4),
mnemonic#"\t$R1, $M3, $R2, $M4", []>;
-class TernaryRRD<string mnemonic, bits<16> opcode,
- SDPatternOperator operator, RegisterOperand cls>
- : InstRRD<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, cls:$R2),
+class TernaryRRD<string mnemonic, bits<16> opcode, SDPatternOperator operator,
+ RegisterOperand cls1, RegisterOperand cls2>
+ : InstRRD<opcode, (outs cls1:$R1), (ins cls2:$R1src, cls2:$R3, cls2:$R2),
mnemonic#"\t$R1, $R3, $R2",
- [(set cls:$R1, (operator cls:$R1src, cls:$R3, cls:$R2))]> {
+ [(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<string mnemonic, bits<16> opcode,
}
class TernaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator,
- RegisterOperand cls, SDPatternOperator load, bits<5> bytes>
- : InstRXF<opcode, (outs cls:$R1),
- (ins cls:$R1src, cls:$R3, bdxaddr12only:$XBD2),
+ RegisterOperand cls1, RegisterOperand cls2,
+ SDPatternOperator load, bits<5> bytes>
+ : InstRXF<opcode, (outs cls1:$R1),
+ (ins cls2:$R1src, cls2:$R3, bdxaddr12only:$XBD2),
mnemonic#"\t$R1, $R3, $XBD2",
- [(set cls:$R1, (operator cls:$R1src, cls:$R3,
- (load bdxaddr12only:$XBD2)))]> {
+ [(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 @@ protected:
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 @@ public:
// 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 @@ public:
// 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<int> ExperimentalPrefLoopAlignment(
" of the loop header PC will be 0)."),
cl::Hidden);
+static cl::opt<bool> 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 @@ private:
int StoreCount = 0;
};
-struct HashedExpression;
namespace llvm {
template <> struct DenseMapInfo<const Expression *> {
static const Expression *getEmptyKey() {
@@ -391,41 +390,25 @@ template <> struct DenseMapInfo<const Expression *> {
return reinterpret_cast<const Expression *>(Val);
}
static unsigned getHashValue(const Expression *E) {
- return static_cast<unsigned>(E->getHashValue());
+ return static_cast<unsigned>(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<const Expression *>::getHashValue(E)) {}
-};
-
-unsigned
-DenseMapInfo<const Expression *>::getHashValue(const HashedExpression &HE) {
- return HE.HashVal;
-}
-bool DenseMapInfo<const Expression *>::isEqual(const HashedExpression &LHS,
- const Expression *RHS) {
- return isEqual(LHS.E, RHS);
-}
-
namespace {
class NewGVN {
Function &F;
@@ -707,7 +690,7 @@ private:
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<VariableExpression>(E)) {
EClass = ValueToClass.lookup(VE->getVariableValue());
} else if (isa<DeadExpression>(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<const Value *, 4> Operands(I->operand_values());
- unsigned N = isScalarAfterVectorization(I, VF) ? VF : 1;
- return N * TTI.getArithmeticInstrCost(I->getOpcode(), VectorTy, Op1VK,
- Op2VK, Op1VP, Op2VP, Operands);
+ SmallVector<const Value *, 4> Operands(I->operand_values());
+ return TTI.getArithmeticInstrCost(I->getOpcode(), VectorTy, Op1VK,
+ Op2VK, Op1VP, Op2VP, Operands);
}
case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(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) \
@@ -1419,6 +1419,15 @@ CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
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.
*/
CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
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 @@ public:
ArrayRef<RemappedFile> RemappedFiles = None,
IntrusiveRefCntPtr<vfs::FileSystem> 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<int, bool> 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<PPConditionalInfo> getStack() const {
+ return ConditionalStack;
+ }
+
+ void doneReplaying() {
+ ConditionalStack.clear();
+ ConditionalStackState = Off;
+ }
+
+ void setStack(ArrayRef<PPConditionalInfo> s) {
+ if (!isRecording() && !isReplaying())
+ return;
+ ConditionalStack.clear();
+ ConditionalStack.append(s.begin(), s.end());
+ }
+
+ bool hasRecordedPreamble() const { return !ConditionalStack.empty(); }
+
+ private:
+ SmallVector<PPConditionalInfo, 4> 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 @@ public:
/// \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 @@ public:
Module *M,
SourceLocation MLoc);
+ bool isRecordingPreamble() const {
+ return PreambleConditionalStack.isRecording();
+ }
+
+ bool hasRecordedPreamble() const {
+ return PreambleConditionalStack.hasRecordedPreamble();
+ }
+
+ ArrayRef<PPConditionalInfo> getPreambleConditionalStack() const {
+ return PreambleConditionalStack.getStack();
+ }
+
+ void setRecordedPreambleConditionalStack(ArrayRef<PPConditionalInfo> s) {
+ PreambleConditionalStack.setStack(s);
+ }
+
+ void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> 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 @@ public:
conditional_iterator conditional_end() const {
return ConditionalStack.end();
}
+
+ void setConditionalLevels(ArrayRef<PPConditionalInfo> 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 @@ public:
/// The boolean indicates whether the preamble ends at the start of a new
/// line.
std::pair<unsigned, bool> 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 @@ public:
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<ConstraintManager>(*ConstraintManagerCreator)(
ProgramStateManager &, SubEngine *);
typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)(
ProgramStateManager &);
+typedef llvm::ImmutableMap<const SubRegion*, TaintTagType> TaintedSubRegions;
//===----------------------------------------------------------------------===//
// ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState.
@@ -343,6 +344,9 @@ public:
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 @@ public:
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 @@ private:
std::unique_ptr<ConstraintManager> ConstraintMgr;
ProgramState::GenericDataMap::Factory GDMFactory;
+ TaintedSubRegions::Factory TSRFactory;
typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > 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<TaintMap>
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<SymbolRef, TaintedSubRegions> DerivedSymTaintImpl;
+template<> struct ProgramStateTrait<DerivedSymTaint>
+ : public ProgramStatePartialTrait<DerivedSymTaintImpl> {
+ 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<StoredDiagnostic> &
bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
- SavedMainFileBuffer.reset();
-
if (!Invocation)
return true;
@@ -1090,17 +1088,11 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
Clang->createFileManager();
FileMgr = &Clang->getFileManager();
}
- SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
- UserFilesAreVolatile);
- TheSema.reset();
- Ctx = nullptr;
- PP = nullptr;
- Reader = nullptr;
- // Clear out old caches and data.
- TopLevelDecls.clear();
- clearFileLevelDecls();
+ ResetForParse();
+ SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
+ UserFilesAreVolatile);
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<PCHContainerOperations> 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<unsigned, bool> 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<unsigned, bool> 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<unsigned, bool> 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<PreprocessorOptions> 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<ExtVectorType>(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<ExtVectorType>(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<OMPClause *> Clauses) {
- for (ArrayRef<OMPClause *>::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<OMPClause *> Clauses,
+ const OpenMPClauseKind K) {
+ return llvm::any_of(
+ Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
+}
- return false;
+template <typename... Params>
+static bool hasClauses(ArrayRef<OMPClause *> Clauses, const OpenMPClauseKind K,
+ const Params... ClauseTypes) {
+ return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
}
StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
@@ -5952,8 +5953,9 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> 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<PPConditionalInfo, 4> 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 @@ private:
/// 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<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
/// Functions defining the attack surface.
typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
@@ -186,9 +173,14 @@ private:
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<SVal> 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<SVal> 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<SVal> 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<SVal> 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<Loc> AddrLoc = AddrVal.getAs<Loc>();
if (!AddrLoc)
- return nullptr;
+ return None;
const PointerType *ArgTy =
dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
- SVal Val = State->getSVal(*AddrLoc,
- ArgTy ? ArgTy->getPointeeType(): QualType());
-
- if (auto LCV = Val.getAs<nonloc::LazyCompoundVal>())
- 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<SVal> 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<SVal> 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<const MemRegion *, SymbolRef> 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::PreCall, check::PostCall,
+ check::PostStmt<MaterializeTemporaryExpr>,
+ check::DeadSymbols,
+ eval::Assume> {
+
+ std::unique_ptr<BugType> 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<FunctionDecl>(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<CXXInstanceCall>(&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<FunctionDecl>(Call.getDecl());
+ if (!Func)
+ return;
+
+ if (Func->isOverloadedOperator()) {
+ const auto Op = Func->getOverloadedOperator();
+ if (isSimpleComparisonOperator(Op)) {
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&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<CXXInstanceCall>(&Call)) {
+ if (isEndCall(Func)) {
+ handleEnd(C, OrigExpr, Call.getReturnValue(),
+ InstCall->getCXXThisVal());
+ return;
+ }
+ }
+
+ // Copy-like and move constructors
+ if (isa<CXXConstructorCall>(&Call) && Call.getNumArgs() == 1) {
+ if (const auto *Pos = getIteratorPosition(State, Call.getArgSVal(0))) {
+ State = setIteratorPosition(State, Call.getReturnValue(), *Pos);
+ if (cast<CXXConstructorDecl>(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<IteratorRegionMap>();
+ for (const auto Reg : RegionMap) {
+ if (!SR.isLiveRegion(Reg.first)) {
+ State = State->remove<IteratorRegionMap>(Reg.first);
+ }
+ }
+
+ auto SymbolMap = State->get<IteratorSymbolMap>();
+ for (const auto Sym : SymbolMap) {
+ if (!SR.isLive(Sym.first)) {
+ State = State->remove<IteratorSymbolMap>(Sym.first);
+ }
+ }
+
+ auto ContMap = State->get<ContainerMap>();
+ for (const auto Cont : ContMap) {
+ if (!SR.isLiveRegion(Cont.first)) {
+ State = State->remove<ContainerMap>(Cont.first);
+ }
+ }
+
+ auto ComparisonMap = State->get<IteratorComparisonMap>();
+ for (const auto Comp : ComparisonMap) {
+ if (!SR.isLive(Comp.first)) {
+ State = State->remove<IteratorComparisonMap>(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<SymIntExpr>(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<nonloc::ConcreteInt>()) {
+ 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<CXXBaseObjectRegion>()) {
+ 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<CXXBaseObjectRegion>()) {
+ 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<BugReport>(*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<CXXConstructorDecl>(Method)) {
+ if (Ctor->isCopyConstructor()) {
+ HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() == AS_public;
+ }
+ continue;
+ }
+ if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(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<BinarySymExpr>(SE)) {
+ return BSE->getOpcode();
+ } else if (const auto *SC = dyn_cast<SymbolConjured>(SE)) {
+ const auto *COE = dyn_cast<CXXOperatorCallExpr>(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<nonloc::LazyCompoundVal>()) {
+ 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<IteratorComparisonMap>(Condition,
+ IteratorComparison(Left, Right, Eq));
+}
+
+const IteratorComparison *loadComparison(ProgramStateRef State,
+ const SymExpr *Condition) {
+ return State->get<IteratorComparisonMap>(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<ContainerMap>(Cont);
+}
+
+ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
+ const ContainerData &CData) {
+ return State->set<ContainerMap>(Cont, CData);
+}
+
+const IteratorPosition *getIteratorPosition(ProgramStateRef State,
+ const SVal &Val) {
+ if (const auto Reg = Val.getAsRegion()) {
+ return State->get<IteratorRegionMap>(Reg);
+ } else if (const auto Sym = Val.getAsSymbol()) {
+ return State->get<IteratorSymbolMap>(Sym);
+ } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
+ return State->get<IteratorRegionMap>(LCVal->getRegion());
+ }
+ return nullptr;
+}
+
+const IteratorPosition *getIteratorPosition(ProgramStateRef State,
+ RegionOrSymbol RegOrSym) {
+ if (RegOrSym.is<const MemRegion *>()) {
+ return State->get<IteratorRegionMap>(RegOrSym.get<const MemRegion *>());
+ } else if (RegOrSym.is<SymbolRef>()) {
+ return State->get<IteratorSymbolMap>(RegOrSym.get<SymbolRef>());
+ }
+ return nullptr;
+}
+
+ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
+ const IteratorPosition &Pos) {
+ if (const auto Reg = Val.getAsRegion()) {
+ return State->set<IteratorRegionMap>(Reg, Pos);
+ } else if (const auto Sym = Val.getAsSymbol()) {
+ return State->set<IteratorSymbolMap>(Sym, Pos);
+ } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
+ return State->set<IteratorRegionMap>(LCVal->getRegion(), Pos);
+ }
+ return nullptr;
+}
+
+ProgramStateRef setIteratorPosition(ProgramStateRef State,
+ RegionOrSymbol RegOrSym,
+ const IteratorPosition &Pos) {
+ if (RegOrSym.is<const MemRegion *>()) {
+ return State->set<IteratorRegionMap>(RegOrSym.get<const MemRegion *>(),
+ Pos);
+ } else if (RegOrSym.is<SymbolRef>()) {
+ return State->set<IteratorSymbolMap>(RegOrSym.get<SymbolRef>(), Pos);
+ }
+ return nullptr;
+}
+
+ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val) {
+ if (const auto Reg = Val.getAsRegion()) {
+ return State->remove<IteratorRegionMap>(Reg);
+ } else if (const auto Sym = Val.getAsSymbol()) {
+ return State->remove<IteratorSymbolMap>(Sym);
+ } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
+ return State->remove<IteratorRegionMap>(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<DefinedSVal>();
+ 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<DefinedSVal>();
+
+ if(comparison) {
+ return !!State->assume(*comparison, true);
+ }
+
+ return false;
+}
+
+} // namespace
+
+#define REGISTER_CHECKER(name) \
+ void ento::register##name(CheckerManager &Mgr) { \
+ auto *checker = Mgr.registerChecker<IteratorChecker>(); \
+ 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 <utility>
-
-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<const MemRegion *, SymbolRef> 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<CXXOperatorCallExpr>,
- check::PostStmt<CXXConstructExpr>, check::PostStmt<DeclStmt>,
- check::PostStmt<MaterializeTemporaryExpr>, 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<BugType> 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<CXXInstanceCall>(&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<const CXXInstanceCall &>(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<const CXXInstanceCall &>(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<CXXTempObjectRegion>())
- 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<StackFrameContext>(LCtx)->getCallSite();
- if (!Site)
- return;
-
- const auto *FD = dyn_cast<FunctionDecl>(LCtx->getDecl());
- if (!FD)
- return;
-
- const auto *CE = dyn_cast<CallExpr>(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<VarDecl>(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<IteratorRegionMap>();
- for (const auto Reg : RegionMap) {
- if (!SR.isLiveRegion(Reg.first)) {
- State = State->remove<IteratorRegionMap>(Reg.first);
- }
- }
-
- auto SymbolMap = State->get<IteratorSymbolMap>();
- for (const auto Sym : SymbolMap) {
- if (SR.isDead(Sym.first)) {
- State = State->remove<IteratorSymbolMap>(Sym.first);
- }
- }
-
- auto ComparisonMap = State->get<IteratorComparisonMap>();
- for (const auto Comp : ComparisonMap) {
- if (SR.isDead(Comp.first)) {
- State = State->remove<IteratorComparisonMap>(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<SymIntExpr>(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<nonloc::ConcreteInt>()) {
- 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<BugReport>(*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<CXXConstructorDecl>(Method)) {
- if (Ctor->isCopyConstructor()) {
- HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() == AS_public;
- }
- continue;
- }
- if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(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<BinarySymExpr>(SE)) {
- return BSE->getOpcode();
- } else if (const auto *SC = dyn_cast<SymbolConjured>(SE)) {
- const auto *COE = dyn_cast<CXXOperatorCallExpr>(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<nonloc::LazyCompoundVal>()) {
- 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<IteratorComparisonMap>(Condition,
- IteratorComparison(Left, Right, Eq));
-}
-
-const IteratorComparison *loadComparison(ProgramStateRef State,
- const SymExpr *Condition) {
- return State->get<IteratorComparisonMap>(Condition);
-}
-
-const IteratorPosition *getIteratorPosition(ProgramStateRef State,
- const SVal &Val) {
- if (const auto Reg = Val.getAsRegion()) {
- return State->get<IteratorRegionMap>(Reg);
- } else if (const auto Sym = Val.getAsSymbol()) {
- return State->get<IteratorSymbolMap>(Sym);
- } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
- return State->get<IteratorRegionMap>(LCVal->getRegion());
- }
- return nullptr;
-}
-
-const IteratorPosition *getIteratorPosition(ProgramStateRef State,
- RegionOrSymbol RegOrSym) {
- if (RegOrSym.is<const MemRegion *>()) {
- return State->get<IteratorRegionMap>(RegOrSym.get<const MemRegion *>());
- } else if (RegOrSym.is<SymbolRef>()) {
- return State->get<IteratorSymbolMap>(RegOrSym.get<SymbolRef>());
- }
- return nullptr;
-}
-
-ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
- IteratorPosition Pos) {
- if (const auto Reg = Val.getAsRegion()) {
- return State->set<IteratorRegionMap>(Reg, Pos);
- } else if (const auto Sym = Val.getAsSymbol()) {
- return State->set<IteratorSymbolMap>(Sym, Pos);
- } else if (const auto LCVal = Val.getAs<nonloc::LazyCompoundVal>()) {
- return State->set<IteratorRegionMap>(LCVal->getRegion(), Pos);
- }
- return nullptr;
-}
-
-ProgramStateRef setIteratorPosition(ProgramStateRef State,
- RegionOrSymbol RegOrSym,
- IteratorPosition Pos) {
- if (RegOrSym.is<const MemRegion *>()) {
- return State->set<IteratorRegionMap>(RegOrSym.get<const MemRegion *>(),
- Pos);
- } else if (RegOrSym.is<SymbolRef>()) {
- return State->set<IteratorSymbolMap>(RegOrSym.get<SymbolRef>(), 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<IteratorPastEndChecker>();
-}
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 @@ public:
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 @@ public:
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<CallExpr> > {
+class PthreadLockChecker
+ : public Checker<check::PostStmt<CallExpr>, check::DeadSymbols> {
mutable std::unique_ptr<BugType> BT_doublelock;
mutable std::unique_ptr<BugType> BT_doubleunlock;
mutable std::unique_ptr<BugType> BT_destroylock;
@@ -61,22 +80,31 @@ class PthreadLockChecker : public Checker< check::PostStmt<CallExpr> > {
};
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<LockMap>(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<LockMap>(lockR);
+ else if (lstate->isUnlockedAndPossiblyDestroyed())
+ state = state->set<LockMap>(lockR, LockState::getUnlocked());
+ } else
+ state = state->set<LockMap>(lockR, LockState::getDestroyed());
+
+ // Removing the map entry (lockR, sym) from DestroyRetVal as the lock state is
+ // now resolved.
+ state = state->remove<DestroyRetVal>(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<DestroyRetVal>(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<DestroyRetVal>(lockR);
+ if (sym)
+ state = resolvePossiblyDestroyedMutex(state, lockR, sym);
if (const LockState *LState = state->get<LockMap>(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 SymbolRef *sym = State->get<DestroyRetVal>(LockR);
+ if (sym)
+ State = resolvePossiblyDestroyedMutex(State, LockR, sym);
+
const LockState *LState = State->get<LockMap>(LockR);
- if (!LState || LState->isUnlocked()) {
- State = State->set<LockMap>(LockR, LockState::getDestroyed());
- C.addTransition(State);
- return;
+ // 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<LockMap>(LockR);
+ C.addTransition(State);
+ return;
+ }
+ State = State->set<DestroyRetVal>(LockR, sym);
+ if (LState && LState->isUnlocked())
+ State = State->set<LockMap>(
+ LockR, LockState::getUnlockedAndPossiblyDestroyed());
+ else
+ State = State->set<LockMap>(
+ LockR, LockState::getUntouchedAndPossiblyDestroyed());
+ C.addTransition(State);
+ return;
+ }
+ } else {
+ if (!LState || LState->isUnlocked()) {
+ State = State->set<LockMap>(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<DestroyRetVal>(LockR);
+ if (sym)
+ State = resolvePossiblyDestroyedMutex(State, LockR, sym);
+
const struct LockState *LState = State->get<LockMap>(LockR);
if (!LState || LState->isDestroyed()) {
State = State->set<LockMap>(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<DestroyRetVal>();
+ 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<PthreadLockChecker>();
}
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<Expr>(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<nonloc::LazyCompoundVal>()) {
+ if (Optional<SVal> 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<TaintMap>(ParentSym) && *get<TaintMap>(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<DerivedSymTaint>(ParentSym);
+ TaintedSubRegions Regs =
+ SavedRegs ? *SavedRegs : stateMgr->TSRFactory.getEmptyMap();
+
+ Regs = stateMgr->TSRFactory.add(Regs, SubRegion, Kind);
+ ProgramStateRef NewState = set<DerivedSymTaint>(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<Expr>(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<SymbolData>(*SI))
continue;
- const TaintTagType *Tag = get<TaintMap>(*SI);
- Tainted = (Tag && *Tag == Kind);
+ if (const TaintTagType *Tag = get<TaintMap>(*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<SymbolDerived>(*SI))
- Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind);
+ if (const SymbolDerived *SD = dyn_cast<SymbolDerived>(*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<DerivedSymTaint>(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<SymbolRegionValue>(*SI))
- Tainted = Tainted || isTainted(SRV->getRegion(), Kind);
-
- // If If this is a SymbolCast from a tainted value, it's also tainted.
- if (const SymbolCast *SC = dyn_cast<SymbolCast>(*SI))
- Tainted = Tainted || isTainted(SC->getOperand(), Kind);
+ if (const SymbolRegionValue *SRV = dyn_cast<SymbolRegionValue>(*SI)) {
+ if (isTainted(SRV->getRegion(), Kind))
+ return true;
+ }
- if (Tainted)
- return true;
+ // If this is a SymbolCast from a tainted value, it's also tainted.
+ if (const SymbolCast *SC = dyn_cast<SymbolCast>(*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 @@ public: // Part of public interface to class.
Optional<SVal> 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<InputSection>(Sec))
+ continue;
+
if (Sec->Assigned)
continue;
@@ -1076,6 +1080,9 @@ template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
return;
}
+ if (Sec->Type == SHT_NOBITS)
+ return;
+
// Write leading padding.
ArrayRef<InputSection *> 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<DefinedRegular *> Syms) {
}
template <class ELFT>
-void elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) {
+void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) {
if (Config->MapFile.empty())
return;
@@ -123,10 +123,7 @@ void elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) {
<< " Align Out In Symbol\n";
// Print out file contents.
- for (BaseCommand *Base : Script) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- if (!Cmd)
- continue;
+ for (OutputSectionCommand *Cmd : Script) {
OutputSection *OSec = Cmd->Sec;
writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment);
OS << OSec->Name << '\n';
@@ -147,7 +144,7 @@ void elf::writeMapFile(llvm::ArrayRef<BaseCommand *> Script) {
}
}
-template void elf::writeMapFile<ELF32LE>(ArrayRef<BaseCommand *>);
-template void elf::writeMapFile<ELF32BE>(ArrayRef<BaseCommand *>);
-template void elf::writeMapFile<ELF64LE>(ArrayRef<BaseCommand *>);
-template void elf::writeMapFile<ELF64BE>(ArrayRef<BaseCommand *>);
+template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionCommand *>);
+template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionCommand *>);
+template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionCommand *>);
+template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionCommand *>);
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 <class ELFT> void writeMapFile(llvm::ArrayRef<BaseCommand *> Script);
+struct OutputSectionCommand;
+template <class ELFT>
+void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> 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 <class ELFT> 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<ELFT> *Obj = Sec->Sections[0]->getFile<ELFT>();
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 @@ private:
std::unique_ptr<FileOutputBuffer> Buffer;
std::vector<OutputSection *> OutputSections;
+ std::vector<OutputSectionCommand *> OutputSectionCommands;
OutputSectionFactory Factory{OutputSections};
void addRelIpltSymbols();
@@ -262,6 +263,10 @@ template <class ELFT> void Writer<ELFT>::run() {
Script->fabricateDefaultCommands();
}
+ for (BaseCommand *Base : Script->Opt.Commands)
+ if (auto *Cmd = dyn_cast<OutputSectionCommand>(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 <class ELFT> void Writer<ELFT>::run() {
// Handle -Map option.
- writeMapFile<ELFT>(Script->Opt.Commands);
+ writeMapFile<ELFT>(OutputSectionCommands);
if (ErrorCount)
return;
@@ -1201,8 +1206,6 @@ template <class ELFT> void Writer<ELFT>::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 <class ELFT> void Writer<ELFT>::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<OutputSection>(findSection(".ARM.exidx"));
- if (OS && !OS->Sections.empty() && !Config->Relocatable)
- OS->addSection(make<ARMExidxSentinelSection>());
+ if (!OS || OS->Sections.empty() || Config->Relocatable)
+ return;
+
+ auto *Sentinel = make<ARMExidxSentinelSection>();
+ 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<InputSectionDescription>(Base);
+ });
+ cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel);
+ }
}
// The linker is expected to define SECNAME_start and SECNAME_end
@@ -1315,10 +1330,9 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
template <class ELFT>
OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) {
- for (BaseCommand *Base : Script->Opt.Commands)
- if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
- if (Cmd->Name == Name)
- return Cmd;
+ for (OutputSectionCommand *Cmd : OutputSectionCommands)
+ if (Cmd->Name == Name)
+ return Cmd;
return nullptr;
}
@@ -1708,7 +1722,7 @@ template <class ELFT> void Writer<ELFT>::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 <class ELFT> void Writer<ELFT>::writeHeader() {
// Write the section header table. Note that the first table entry is null.
auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
- for (OutputSection *Sec : OutputSections)
- Sec->writeHeaderTo<ELFT>(++SHdrs);
+ for (OutputSectionCommand *Cmd : OutputSectionCommands)
+ Cmd->Sec->writeHeaderTo<ELFT>(++SHdrs);
}
// Open a result file.
@@ -1764,10 +1778,7 @@ template <class ELFT> void Writer<ELFT>::openFile() {
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
uint8_t *Buf = Buffer->getBufferStart();
- for (BaseCommand *Base : Script->Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
- if (!Cmd)
- continue;
+ for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (Sec->Flags & SHF_ALLOC)
Cmd->writeTo<ELFT>(Buf + Sec->Offset);
@@ -1794,19 +1805,13 @@ template <class ELFT> void Writer<ELFT>::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<OutputSectionCommand>(Base);
- if (!Cmd)
- continue;
+ for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
Cmd->writeTo<ELFT>(Buf + Sec->Offset);
}
- for (BaseCommand *Base : Script->Opt.Commands) {
- auto *Cmd = dyn_cast<OutputSectionCommand>(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 <atomic>
@@ -30,9 +31,6 @@
namespace llvm {
class raw_ostream;
}
-namespace llvm {
-template <class C> 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 <vector>
@@ -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 visitUnknown(codeview::DebugUnknownSubsectionRef &Fragment) final;
- Error visitFileChecksums(
- codeview::ModuleDebugFileChecksumFragmentRef &Checksums) final;
+ Error
+ visitFileChecksums(codeview::DebugChecksumsSubsectionRef &Checksums) final;
- Error visitLines(codeview::ModuleDebugLineFragmentRef &Lines) final;
+ Error visitLines(codeview::DebugLinesSubsectionRef &Lines) final;
Error
- visitInlineeLines(codeview::ModuleDebugInlineeLineFragmentRef &Lines) final;
+ visitInlineeLines(codeview::DebugInlineeLinesSubsectionRef &Lines) final;
Error finished() final;
@@ -48,9 +48,9 @@ protected:
Expected<StringRef> getNameFromStringTable(uint32_t Offset);
Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
- Optional<codeview::ModuleDebugFileChecksumFragmentRef> Checksums;
- std::vector<codeview::ModuleDebugInlineeLineFragmentRef> InlineeLines;
- std::vector<codeview::ModuleDebugLineFragmentRef> Lines;
+ Optional<codeview::DebugChecksumsSubsectionRef> Checksums;
+ std::vector<codeview::DebugInlineeLinesSubsectionRef> InlineeLines;
+ std::vector<codeview::DebugLinesSubsectionRef> 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<ModuleDebugFileChecksumFragment>(Strings);
+ auto Checksums = llvm::make_unique<DebugChecksumsSubsection>(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<ModuleDebugLineFragment>(ChecksumRef, Strings);
+ llvm::make_unique<DebugLinesSubsection>(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<ModuleDebugInlineeLineFragment>(
+ auto Inlinees = llvm::make_unique<DebugInlineeLinesSubsection>(
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 @@ private:
bool RelocCached = false;
RelocMapTy RelocMap;
- VarStreamArray<FileChecksumEntry> CVFileChecksumTable;
+ DebugChecksumsSubsectionRef CVFileChecksumTable;
- StringTableRef CVStringTable;
+ DebugStringTableSubsectionRef CVStringTable;
ScopedPrinter &Writer;
BinaryByteStream TypeContents;
@@ -200,7 +200,9 @@ public:
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<uint32_t> 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<uint32_t> 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<BuildMIAction &> 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<DagInit>(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