From cd81d94322a39503e4a3e87b6ee03d4fcb3465fb Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 21 Jul 2014 00:45:20 -0700 Subject: Update LLVM for rebase to r212749. Includes a cherry-pick of: r212948 - fixes a small issue with atomic calls Change-Id: Ib97bd980b59f18142a69506400911a6009d9df18 --- include/llvm-c/Core.h | 16 +- include/llvm-c/module.modulemap | 1 - include/llvm/ADT/APSInt.h | 2 +- include/llvm/ADT/ArrayRef.h | 6 + include/llvm/ADT/BitVector.h | 5 +- include/llvm/ADT/DenseMap.h | 9 +- include/llvm/ADT/DenseSet.h | 6 +- include/llvm/ADT/FoldingSet.h | 8 + include/llvm/ADT/Hashing.h | 4 +- include/llvm/ADT/IntrusiveRefCntPtr.h | 47 +- include/llvm/ADT/MapVector.h | 15 +- include/llvm/ADT/OwningPtr.h | 165 ---- include/llvm/ADT/ScopedHashTable.h | 4 +- include/llvm/ADT/SmallBitVector.h | 3 +- include/llvm/ADT/SmallPtrSet.h | 5 +- include/llvm/ADT/SmallSet.h | 5 +- include/llvm/ADT/SmallVector.h | 15 +- include/llvm/ADT/SparseBitVector.h | 3 +- include/llvm/ADT/SparseMultiSet.h | 5 +- include/llvm/ADT/SparseSet.h | 5 +- include/llvm/ADT/StringMap.h | 64 +- include/llvm/ADT/Triple.h | 11 +- include/llvm/ADT/Twine.h | 4 + include/llvm/ADT/UniqueVector.h | 19 +- include/llvm/Analysis/AliasAnalysis.h | 8 + include/llvm/Analysis/BlockFrequencyInfoImpl.h | 691 +------------- include/llvm/Analysis/JumpInstrTableInfo.h | 60 ++ include/llvm/Analysis/Passes.h | 4 + include/llvm/Analysis/RegionInfo.h | 10 + include/llvm/Analysis/TargetTransformInfo.h | 1 + include/llvm/Analysis/ValueTracking.h | 5 +- include/llvm/Bitcode/LLVMBitCodes.h | 14 +- include/llvm/Bitcode/ReaderWriter.h | 11 +- include/llvm/CodeGen/Analysis.h | 4 +- include/llvm/CodeGen/AsmPrinter.h | 1 - include/llvm/CodeGen/CommandFlags.h | 16 + include/llvm/CodeGen/FastISel.h | 13 +- include/llvm/CodeGen/ISDOpcodes.h | 37 + include/llvm/CodeGen/JumpInstrTables.h | 104 ++ include/llvm/CodeGen/LexicalScopes.h | 6 +- include/llvm/CodeGen/LiveIntervalAnalysis.h | 11 + include/llvm/CodeGen/MachineBasicBlock.h | 4 +- include/llvm/CodeGen/MachineFrameInfo.h | 3 + include/llvm/CodeGen/MachineInstr.h | 5 +- include/llvm/CodeGen/MachineScheduler.h | 217 ++++- include/llvm/CodeGen/Passes.h | 19 + include/llvm/CodeGen/RegisterPressure.h | 2 - include/llvm/CodeGen/ScheduleDFS.h | 2 - include/llvm/CodeGen/SelectionDAG.h | 87 +- include/llvm/CodeGen/SelectionDAGNodes.h | 86 +- include/llvm/CodeGen/StackMapLivenessAnalysis.h | 15 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 12 +- include/llvm/Config/config.h.cmake | 155 +-- include/llvm/Config/config.h.in | 156 +-- include/llvm/Config/llvm-config.h.cmake | 41 +- include/llvm/Config/llvm-config.h.in | 41 +- include/llvm/ExecutionEngine/ExecutionEngine.h | 29 +- include/llvm/ExecutionEngine/ObjectBuffer.h | 3 +- include/llvm/ExecutionEngine/RuntimeDyld.h | 2 + include/llvm/ExecutionEngine/RuntimeDyldChecker.h | 98 ++ .../llvm/ExecutionEngine/SectionMemoryManager.h | 5 +- include/llvm/IR/Attributes.h | 1 + include/llvm/IR/AutoUpgrade.h | 5 + include/llvm/IR/Comdat.h | 66 ++ include/llvm/IR/Constant.h | 14 + include/llvm/IR/DIBuilder.h | 13 +- include/llvm/IR/DataLayout.h | 4 +- include/llvm/IR/DebugInfo.h | 16 +- include/llvm/IR/DebugLoc.h | 2 +- include/llvm/IR/DiagnosticInfo.h | 8 - include/llvm/IR/Dominators.h | 4 - include/llvm/IR/GVMaterializer.h | 9 +- include/llvm/IR/GlobalAlias.h | 34 +- include/llvm/IR/GlobalObject.h | 14 +- include/llvm/IR/GlobalValue.h | 53 +- include/llvm/IR/GlobalVariable.h | 21 - include/llvm/IR/IRBuilder.h | 29 + include/llvm/IR/Instructions.h | 36 +- include/llvm/IR/Intrinsics.h | 3 + include/llvm/IR/Intrinsics.td | 4 + include/llvm/IR/IntrinsicsAArch64.td | 7 + include/llvm/IR/IntrinsicsARM.td | 17 +- include/llvm/IR/IntrinsicsNVVM.td | 183 +++- include/llvm/IR/IntrinsicsR600.td | 36 + include/llvm/IR/IntrinsicsX86.td | 36 +- include/llvm/IR/LegacyPassNameParser.h | 2 +- include/llvm/IR/Module.h | 31 +- include/llvm/IR/User.h | 10 +- include/llvm/IR/Value.h | 26 +- include/llvm/IR/ValueMap.h | 19 +- include/llvm/IRReader/IRReader.h | 10 +- include/llvm/InitializePasses.h | 3 + include/llvm/LTO/LTOModule.h | 95 +- include/llvm/LinkAllPasses.h | 2 + include/llvm/Linker/Linker.h | 2 + include/llvm/MC/ConstantPools.h | 80 ++ include/llvm/MC/MCAnalysis/MCAtom.h | 199 ++++ include/llvm/MC/MCAnalysis/MCFunction.h | 142 +++ include/llvm/MC/MCAnalysis/MCModule.h | 134 +++ include/llvm/MC/MCAnalysis/MCModuleYAML.h | 40 + include/llvm/MC/MCAsmInfo.h | 1006 ++++++++++---------- include/llvm/MC/MCAssembler.h | 2 +- include/llvm/MC/MCAtom.h | 199 ---- include/llvm/MC/MCContext.h | 37 +- include/llvm/MC/MCDwarf.h | 7 +- include/llvm/MC/MCELFStreamer.h | 1 - include/llvm/MC/MCELFSymbolFlags.h | 1 + include/llvm/MC/MCExpr.h | 3 +- include/llvm/MC/MCFunction.h | 142 --- include/llvm/MC/MCLinkerOptimizationHint.h | 15 +- include/llvm/MC/MCMachObjectWriter.h | 2 + include/llvm/MC/MCModule.h | 134 --- include/llvm/MC/MCModuleYAML.h | 40 - include/llvm/MC/MCObjectFileInfo.h | 15 +- include/llvm/MC/MCObjectStreamer.h | 9 +- include/llvm/MC/MCParser/AsmLexer.h | 4 +- include/llvm/MC/MCParser/MCAsmParser.h | 32 +- include/llvm/MC/MCSectionCOFF.h | 18 +- include/llvm/MC/MCStreamer.h | 114 ++- include/llvm/MC/MCTargetAsmParser.h | 20 +- include/llvm/MC/MCTargetOptions.h | 4 +- include/llvm/MC/MCTargetOptionsCommandFlags.h | 9 + include/llvm/MC/MCWinCOFFStreamer.h | 3 +- include/llvm/MC/StringTableBuilder.h | 59 ++ include/llvm/MC/YAML.h | 94 ++ include/llvm/Object/Archive.h | 18 +- include/llvm/Object/Binary.h | 8 +- include/llvm/Object/COFF.h | 134 +-- include/llvm/Object/COFFYAML.h | 4 +- include/llvm/Object/ELF.h | 60 +- include/llvm/Object/ELFObjectFile.h | 240 ++--- include/llvm/Object/ELFYAML.h | 13 +- include/llvm/Object/Error.h | 34 +- include/llvm/Object/IRObjectFile.h | 21 +- include/llvm/Object/MachO.h | 123 ++- include/llvm/Object/MachOUniversal.h | 19 +- include/llvm/Object/ObjectFile.h | 231 +++-- include/llvm/Object/RelocVisitor.h | 6 +- include/llvm/Object/StringTableBuilder.h | 59 -- include/llvm/Object/SymbolicFile.h | 36 +- include/llvm/Object/YAML.h | 117 --- include/llvm/Option/ArgList.h | 8 + include/llvm/PassInfo.h | 147 +++ include/llvm/PassRegistry.h | 27 +- include/llvm/PassSupport.h | 128 +-- include/llvm/ProfileData/InstrProf.h | 26 +- include/llvm/ProfileData/InstrProfReader.h | 49 +- include/llvm/ProfileData/InstrProfWriter.h | 5 +- include/llvm/Support/ARMBuildAttributes.h | 15 + include/llvm/Support/ARMWinEH.h | 384 ++++++++ include/llvm/Support/COFF.h | 10 +- include/llvm/Support/Compiler.h | 6 + include/llvm/Support/ConvertUTF.h | 14 +- include/llvm/Support/CrashRecoveryContext.h | 3 + include/llvm/Support/DataTypes.h.cmake | 121 +-- include/llvm/Support/DataTypes.h.in | 119 +-- include/llvm/Support/Dwarf.h | 1 - include/llvm/Support/ELF.h | 27 +- include/llvm/Support/Endian.h | 2 +- include/llvm/Support/Errc.h | 86 ++ include/llvm/Support/ErrorHandling.h | 5 - include/llvm/Support/ErrorOr.h | 42 +- include/llvm/Support/FEnv.h | 56 -- include/llvm/Support/FileOutputBuffer.h | 10 +- include/llvm/Support/FileSystem.h | 237 ++--- include/llvm/Support/Format.h | 102 +- include/llvm/Support/GenericDomTree.h | 4 + include/llvm/Support/GraphWriter.h | 2 +- include/llvm/Support/LockFileManager.h | 5 +- include/llvm/Support/MachO.h | 23 +- include/llvm/Support/ManagedStatic.h | 3 - include/llvm/Support/MathExtras.h | 9 + include/llvm/Support/Memory.h | 10 +- include/llvm/Support/MemoryBuffer.h | 52 +- include/llvm/Support/Process.h | 11 +- include/llvm/Support/Program.h | 7 +- include/llvm/Support/RandomNumberGenerator.h | 57 ++ include/llvm/Support/ScaledNumber.h | 897 +++++++++++++++++ include/llvm/Support/SourceMgr.h | 122 +-- include/llvm/Support/SpecialCaseList.h | 96 ++ include/llvm/Support/StreamableMemoryObject.h | 7 +- include/llvm/Support/StringPool.h | 7 +- include/llvm/Support/SwapByteOrder.h | 31 +- include/llvm/Support/TargetRegistry.h | 27 +- include/llvm/Support/Threading.h | 29 +- include/llvm/Support/WindowsError.h | 19 + include/llvm/Support/YAMLTraits.h | 8 +- include/llvm/Support/system_error.h | 901 ------------------ include/llvm/TableGen/SetTheory.h | 142 +++ include/llvm/Target/Target.td | 5 + include/llvm/Target/TargetFrameLowering.h | 13 + include/llvm/Target/TargetInstrInfo.h | 18 +- include/llvm/Target/TargetLowering.h | 70 +- include/llvm/Target/TargetLoweringObjectFile.h | 6 +- include/llvm/Target/TargetOptions.h | 17 +- include/llvm/Target/TargetRegisterInfo.h | 6 - include/llvm/Target/TargetSelectionDAGInfo.h | 2 +- include/llvm/Target/TargetSubtargetInfo.h | 16 + include/llvm/Transforms/IPO/PassManagerBuilder.h | 1 + include/llvm/Transforms/Instrumentation.h | 12 +- include/llvm/Transforms/Scalar.h | 7 + include/llvm/Transforms/Utils/Local.h | 2 +- include/llvm/Transforms/Utils/LoopUtils.h | 4 +- include/llvm/Transforms/Utils/SpecialCaseList.h | 114 --- include/llvm/Transforms/Utils/VectorUtils.h | 15 + 205 files changed, 6086 insertions(+), 5229 deletions(-) delete mode 100644 include/llvm/ADT/OwningPtr.h create mode 100644 include/llvm/Analysis/JumpInstrTableInfo.h create mode 100644 include/llvm/CodeGen/JumpInstrTables.h create mode 100644 include/llvm/ExecutionEngine/RuntimeDyldChecker.h create mode 100644 include/llvm/IR/Comdat.h create mode 100644 include/llvm/MC/ConstantPools.h create mode 100644 include/llvm/MC/MCAnalysis/MCAtom.h create mode 100644 include/llvm/MC/MCAnalysis/MCFunction.h create mode 100644 include/llvm/MC/MCAnalysis/MCModule.h create mode 100644 include/llvm/MC/MCAnalysis/MCModuleYAML.h delete mode 100644 include/llvm/MC/MCAtom.h delete mode 100644 include/llvm/MC/MCFunction.h delete mode 100644 include/llvm/MC/MCModule.h delete mode 100644 include/llvm/MC/MCModuleYAML.h create mode 100644 include/llvm/MC/StringTableBuilder.h create mode 100644 include/llvm/MC/YAML.h delete mode 100644 include/llvm/Object/StringTableBuilder.h delete mode 100644 include/llvm/Object/YAML.h create mode 100644 include/llvm/PassInfo.h create mode 100644 include/llvm/Support/ARMWinEH.h create mode 100644 include/llvm/Support/Errc.h delete mode 100644 include/llvm/Support/FEnv.h create mode 100644 include/llvm/Support/RandomNumberGenerator.h create mode 100644 include/llvm/Support/ScaledNumber.h create mode 100644 include/llvm/Support/SpecialCaseList.h create mode 100644 include/llvm/Support/WindowsError.h delete mode 100644 include/llvm/Support/system_error.h create mode 100644 include/llvm/TableGen/SetTheory.h delete mode 100644 include/llvm/Transforms/Utils/SpecialCaseList.h (limited to 'include') diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index f37e3f8..8693a30 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -166,7 +166,8 @@ typedef enum { LLVMCold = 1ULL << 34, LLVMOptimizeNone = 1ULL << 35, LLVMInAllocaAttribute = 1ULL << 36, - LLVMNonNullAttribute = 1ULL << 37 + LLVMNonNullAttribute = 1ULL << 37, + LLVMJumpTableAttribute = 1ULL << 38, */ } LLVMAttribute; @@ -2847,16 +2848,13 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); * @{ */ -/** Allocate and initialize structures needed to make LLVM safe for - multithreading. The return value indicates whether multithreaded - initialization succeeded. Must be executed in isolation from all - other LLVM api calls. - @see llvm::llvm_start_multithreaded */ +/** Deprecated: Multi-threading can only be enabled/disabled with the compile + time define LLVM_ENABLE_THREADS. This function always returns + LLVMIsMultithreaded(). */ LLVMBool LLVMStartMultithreaded(void); -/** Deallocate structures necessary to make LLVM safe for multithreading. - Must be executed in isolation from all other LLVM api calls. - @see llvm::llvm_stop_multithreaded */ +/** Deprecated: Multi-threading can only be enabled/disabled with the compile + time define LLVM_ENABLE_THREADS. */ void LLVMStopMultithreaded(void); /** Check whether LLVM is executing in thread-safe mode or not. diff --git a/include/llvm-c/module.modulemap b/include/llvm-c/module.modulemap index 2bcdbc1..a456119 100644 --- a/include/llvm-c/module.modulemap +++ b/include/llvm-c/module.modulemap @@ -1,5 +1,4 @@ module LLVM_C { - requires cplusplus umbrella "." module * { export * } } diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 053deff..ee34e9b 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -56,7 +56,7 @@ public: APInt::toString(Str, Radix, isSigned()); } /// toString - Converts an APInt to a std::string. This is an inefficient - /// method, your should prefer passing in a SmallString instead. + /// method; you should prefer passing in a SmallString instead. std::string toString(unsigned Radix) const { return APInt::toString(Radix, isSigned()); } diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 1b64fee..0fff505 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -147,6 +147,12 @@ namespace llvm { return ArrayRef(data()+N, M); } + // \brief Drop the last \p N elements of the array. + ArrayRef drop_back(unsigned N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return slice(0, size() - N); + } + /// @} /// @name Operator Overloads /// @{ diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index da2b3ad..34e2284 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -34,6 +34,7 @@ class BitVector { unsigned Capacity; // Size of allocated memory in BitWord. public: + typedef unsigned size_type; // Encapsulation of a single bit. class reference { friend class BitVector; @@ -111,10 +112,10 @@ public: bool empty() const { return Size == 0; } /// size - Returns the number of bits in this bitvector. - unsigned size() const { return Size; } + size_type size() const { return Size; } /// count - Returns the number of bits which are set. - unsigned count() const { + size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < NumBitWords(size()); ++i) if (sizeof(BitWord) == 4) diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 8269132..85f37b9 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -43,6 +43,7 @@ protected: typedef std::pair BucketT; public: + typedef unsigned size_type; typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; @@ -70,7 +71,7 @@ public: unsigned size() const { return getNumEntries(); } /// Grow the densemap so that it has at least Size buckets. Does not shrink - void resize(size_t Size) { + void resize(size_type Size) { if (Size > getNumBuckets()) grow(Size); } @@ -99,10 +100,10 @@ public: setNumTombstones(0); } - /// count - Return true if the specified key is in the map. - bool count(const KeyT &Val) const { + /// Return 1 if the specified key is in the map, 0 otherwise. + size_type count(const KeyT &Val) const { const BucketT *TheBucket; - return LookupBucketFor(Val, TheBucket); + return LookupBucketFor(Val, TheBucket) ? 1 : 0; } iterator find(const KeyT &Val) { diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 1d8c39c..37a81b0 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -29,11 +29,12 @@ class DenseSet { public: typedef ValueT key_type; typedef ValueT value_type; + typedef unsigned size_type; explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} bool empty() const { return TheMap.empty(); } - unsigned size() const { return TheMap.size(); } + size_type size() const { return TheMap.size(); } size_t getMemorySize() const { return TheMap.getMemorySize(); } /// Grow the DenseSet so that it has at least Size buckets. Will not shrink @@ -44,7 +45,8 @@ public: TheMap.clear(); } - bool count(const ValueT &V) const { + /// Return 1 if the specified key is in the set, 0 otherwise. + size_type count(const ValueT &V) const { return TheMap.count(V); } diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 9b7ee85..14c5933 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -794,6 +794,14 @@ template struct FoldingSetTrait { ID.AddPointer(X); } }; +template +struct FoldingSetTrait> { + static inline void Profile(const std::pair &P, + llvm::FoldingSetNodeID &ID) { + ID.Add(P.first); + ID.Add(P.second); + } +}; } // End of namespace llvm. #endif diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index b11e3c1..abf02b8 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -152,7 +152,7 @@ inline uint64_t fetch64(const char *p) { uint64_t result; memcpy(&result, p, sizeof(result)); if (sys::IsBigEndianHost) - return sys::SwapByteOrder(result); + sys::swapByteOrder(result); return result; } @@ -160,7 +160,7 @@ inline uint32_t fetch32(const char *p) { uint32_t result; memcpy(&result, p, sizeof(result)); if (sys::IsBigEndianHost) - return sys::SwapByteOrder(result); + sys::swapByteOrder(result); return result; } diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index cd1946c..f9df378 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -154,13 +154,13 @@ public: } template - IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.getPtr()) { + IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.get()) { S.Obj = 0; } template IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) - : Obj(S.getPtr()) { + : Obj(S.get()) { retain(); } @@ -175,12 +175,9 @@ public: T* operator->() const { return Obj; } - T* getPtr() const { return Obj; } + T* get() const { return Obj; } - typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; - operator unspecified_bool_type() const { - return Obj ? &IntrusiveRefCntPtr::getPtr : nullptr; - } + LLVM_EXPLICIT operator bool() const { return Obj; } void swap(IntrusiveRefCntPtr& other) { T* tmp = other.Obj; @@ -206,42 +203,62 @@ public: inline bool operator==(const IntrusiveRefCntPtr& A, const IntrusiveRefCntPtr& B) { - return A.getPtr() == B.getPtr(); + return A.get() == B.get(); } template inline bool operator!=(const IntrusiveRefCntPtr& A, const IntrusiveRefCntPtr& B) { - return A.getPtr() != B.getPtr(); + return A.get() != B.get(); } template inline bool operator==(const IntrusiveRefCntPtr& A, U* B) { - return A.getPtr() == B; + return A.get() == B; } template inline bool operator!=(const IntrusiveRefCntPtr& A, U* B) { - return A.getPtr() != B; + return A.get() != B; } template inline bool operator==(T* A, const IntrusiveRefCntPtr& B) { - return A == B.getPtr(); + return A == B.get(); } template inline bool operator!=(T* A, const IntrusiveRefCntPtr& B) { - return A != B.getPtr(); + return A != B.get(); + } + + template + bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr &B) { + return !B; + } + + template + bool operator==(const IntrusiveRefCntPtr &A, std::nullptr_t B) { + return B == A; + } + + template + bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr &B) { + return !(A == B); + } + + template + bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { + return !(A == B); } //===----------------------------------------------------------------------===// @@ -251,14 +268,14 @@ public: template struct simplify_type > { typedef T* SimpleType; static SimpleType getSimplifiedValue(IntrusiveRefCntPtr& Val) { - return Val.getPtr(); + return Val.get(); } }; template struct simplify_type > { typedef /*const*/ T* SimpleType; static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { - return Val.getPtr(); + return Val.get(); } }; diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 7fd1570..2eae22c 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -29,7 +29,7 @@ template, typename VectorType = std::vector > > class MapVector { - typedef typename VectorType::size_type SizeType; + typedef typename VectorType::size_type size_type; MapType Map; VectorType Vector; @@ -38,7 +38,7 @@ public: typedef typename VectorType::iterator iterator; typedef typename VectorType::const_iterator const_iterator; - SizeType size() const { + size_type size() const { return Vector.size(); } @@ -100,7 +100,7 @@ public: return std::make_pair(begin() + I, false); } - unsigned count(const KeyT &Key) const { + size_type count(const KeyT &Key) const { typename MapType::const_iterator Pos = Map.find(Key); return Pos == Map.end()? 0 : 1; } @@ -123,6 +123,15 @@ public: Map.erase(Pos); Vector.pop_back(); } + + /// \brief Remove the element given by Iterator. + /// Returns an iterator to the element following the one which was removed, + /// which may be end(). + typename VectorType::iterator erase(typename VectorType::iterator Iterator) { + typename MapType::iterator MapIterator = Map.find(Iterator->first); + Map.erase(MapIterator); + return Vector.erase(Iterator); + } }; } diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h deleted file mode 100644 index 5e83358..0000000 --- a/include/llvm/ADT/OwningPtr.h +++ /dev/null @@ -1,165 +0,0 @@ -//===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines and implements the OwningPtr class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_OWNINGPTR_H -#define LLVM_ADT_OWNINGPTR_H - -#include "llvm/Support/Compiler.h" -#include -#include -#include - -namespace llvm { - -/// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it -/// guarantees deletion of the object pointed to, either on destruction of the -/// OwningPtr or via an explicit reset(). Once created, ownership of the -/// pointee object can be taken away from OwningPtr by using the take method. -template -class OwningPtr { - OwningPtr(OwningPtr const &) LLVM_DELETED_FUNCTION; - OwningPtr &operator=(OwningPtr const &) LLVM_DELETED_FUNCTION; - T *Ptr; -public: - explicit OwningPtr(T *P = 0) : Ptr(P) {} - - OwningPtr(OwningPtr &&Other) : Ptr(Other.take()) {} - - OwningPtr &operator=(OwningPtr &&Other) { - reset(Other.take()); - return *this; - } - - OwningPtr(std::unique_ptr Other) : Ptr(Other.release()) {} - - OwningPtr &operator=(std::unique_ptr Other) { - reset(Other.release()); - return *this; - } - -#if LLVM_HAS_RVALUE_REFERENCE_THIS - operator std::unique_ptr() && { return std::unique_ptr(take()); } -#endif - - ~OwningPtr() { - delete Ptr; - } - - /// reset - Change the current pointee to the specified pointer. Note that - /// calling this with any pointer (including a null pointer) deletes the - /// current pointer. - void reset(T *P = 0) { - if (P == Ptr) return; - T *Tmp = Ptr; - Ptr = P; - delete Tmp; - } - - /// take - Reset the owning pointer to null and return its pointer. This does - /// not delete the pointer before returning it. - T *take() { - T *Tmp = Ptr; - Ptr = nullptr; - return Tmp; - } - - T *release() { return take(); } - - std::unique_ptr take_unique() { return std::unique_ptr(take()); } - - T &operator*() const { - assert(Ptr && "Cannot dereference null pointer"); - return *Ptr; - } - - T *operator->() const { return Ptr; } - T *get() const { return Ptr; } - LLVM_EXPLICIT operator bool() const { return Ptr != nullptr; } - bool operator!() const { return Ptr == nullptr; } - bool isValid() const { return Ptr != nullptr; } - - void swap(OwningPtr &RHS) { - T *Tmp = RHS.Ptr; - RHS.Ptr = Ptr; - Ptr = Tmp; - } -}; - -template -inline void swap(OwningPtr &a, OwningPtr &b) { - a.swap(b); -} - -/// OwningArrayPtr smart pointer - OwningArrayPtr provides the same -/// functionality as OwningPtr, except that it works for array types. -template -class OwningArrayPtr { - OwningArrayPtr(OwningArrayPtr const &) LLVM_DELETED_FUNCTION; - OwningArrayPtr &operator=(OwningArrayPtr const &) LLVM_DELETED_FUNCTION; - T *Ptr; -public: - explicit OwningArrayPtr(T *P = 0) : Ptr(P) {} - - OwningArrayPtr(OwningArrayPtr &&Other) : Ptr(Other.take()) {} - - OwningArrayPtr &operator=(OwningArrayPtr &&Other) { - reset(Other.take()); - return *this; - } - - ~OwningArrayPtr() { - delete [] Ptr; - } - - /// reset - Change the current pointee to the specified pointer. Note that - /// calling this with any pointer (including a null pointer) deletes the - /// current pointer. - void reset(T *P = 0) { - if (P == Ptr) return; - T *Tmp = Ptr; - Ptr = P; - delete [] Tmp; - } - - /// take - Reset the owning pointer to null and return its pointer. This does - /// not delete the pointer before returning it. - T *take() { - T *Tmp = Ptr; - Ptr = 0; - return Tmp; - } - - T &operator[](std::ptrdiff_t i) const { - assert(Ptr && "Cannot dereference null pointer"); - return Ptr[i]; - } - - T *get() const { return Ptr; } - LLVM_EXPLICIT operator bool() const { return Ptr != 0; } - bool operator!() const { return Ptr == nullptr; } - - void swap(OwningArrayPtr &RHS) { - T *Tmp = RHS.Ptr; - RHS.Ptr = Ptr; - Ptr = Tmp; - } -}; - -template -inline void swap(OwningArrayPtr &a, OwningArrayPtr &b) { - a.swap(b); -} - -} // end namespace llvm - -#endif diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 3cc7738..02a6ea3 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -148,6 +148,7 @@ public: /// ScopeTy - This is a helpful typedef that allows clients to get easy access /// to the name of the scope for this hash table. typedef ScopedHashTableScope ScopeTy; + typedef unsigned size_type; private: typedef ScopedHashTableVal ValTy; DenseMap TopLevelMap; @@ -170,7 +171,8 @@ public: AllocatorTy &getAllocator() { return Allocator; } const AllocatorTy &getAllocator() const { return Allocator; } - bool count(const K &Key) const { + /// Return 1 if the specified key is in the table, 0 otherwise. + size_type count(const K &Key) const { return TopLevelMap.count(Key); } diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index e965bc4..0922017 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -54,6 +54,7 @@ class SmallBitVector { }; public: + typedef unsigned size_type; // Encapsulation of a single bit. class reference { SmallBitVector &TheVector; @@ -173,7 +174,7 @@ public: } /// count - Returns the number of bits which are set. - unsigned count() const { + size_type count() const { if (isSmall()) { uintptr_t Bits = getSmallBits(); if (NumBaseBits == 32) diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 67104f3..74f3fd4 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -73,8 +73,9 @@ protected: ~SmallPtrSetImplBase(); public: + typedef unsigned size_type; bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } - unsigned size() const { return NumElements; } + size_type size() const { return NumElements; } void clear() { // If the capacity of the array is huge, and the # elements used is small, @@ -263,7 +264,7 @@ public: } /// count - Return 1 if the specified pointer is in the set, 0 otherwise. - unsigned count(PtrType Ptr) const { + size_type count(PtrType Ptr) const { return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; } diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index 6f36234..bb1971e 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -37,18 +37,19 @@ class SmallSet { typedef typename SmallVector::const_iterator VIterator; typedef typename SmallVector::iterator mutable_iterator; public: + typedef size_t size_type; SmallSet() {} bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return Vector.empty() && Set.empty(); } - unsigned size() const { + size_type size() const { return isSmall() ? Vector.size() : Set.size(); } /// count - Return 1 if the element is in the set, 0 otherwise. - unsigned count(const T &V) const { + size_type count(const T &V) const { if (isSmall()) { // Since the collection is small, just do a linear search. return vfind(V) == Vector.end() ? 0 : 1; diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index dcf0354..82538e9 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -380,7 +380,8 @@ public: } else if (N > this->size()) { if (this->capacity() < N) this->grow(N); - std::uninitialized_fill(this->end(), this->begin()+N, T()); + for (auto I = this->end(), E = this->begin() + N; I != E; ++I) + new (&*I) T(); this->setEnd(this->begin()+N); } } @@ -488,9 +489,9 @@ public: } ::new ((void*) this->end()) T(::std::move(this->back())); - this->setEnd(this->end()+1); // Push everything else over. this->move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); // If we just moved the element we're inserting, be sure to update // the reference. @@ -516,10 +517,10 @@ public: this->grow(); I = this->begin()+EltNo; } - ::new ((void*) this->end()) T(this->back()); - this->setEnd(this->end()+1); + ::new ((void*) this->end()) T(std::move(this->back())); // Push everything else over. this->move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); // If we just moved the element we're inserting, be sure to update // the reference. @@ -555,7 +556,8 @@ public: // reallocate the vector. if (size_t(this->end()-I) >= NumToInsert) { T *OldEnd = this->end(); - append(this->end()-NumToInsert, this->end()); + append(std::move_iterator(this->end() - NumToInsert), + std::move_iterator(this->end())); // Copy the existing elements that get replaced. this->move_backward(I, OldEnd-NumToInsert, OldEnd); @@ -608,7 +610,8 @@ public: // reallocate the vector. if (size_t(this->end()-I) >= NumToInsert) { T *OldEnd = this->end(); - append(this->end()-NumToInsert, this->end()); + append(std::move_iterator(this->end() - NumToInsert), + std::move_iterator(this->end())); // Copy the existing elements that get replaced. this->move_backward(I, OldEnd-NumToInsert, OldEnd); diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 706f248..36754d6 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -45,6 +45,7 @@ struct SparseBitVectorElement : public ilist_node > { public: typedef unsigned long BitWord; + typedef unsigned size_type; enum { BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, @@ -120,7 +121,7 @@ public: return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); } - unsigned count() const { + size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) if (sizeof(BitWord) == 4) diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index d2b2f8d..dc1273e 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -185,6 +185,7 @@ public: typedef const ValueT &const_reference; typedef ValueT *pointer; typedef const ValueT *const_pointer; + typedef unsigned size_type; SparseMultiSet() : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {} @@ -327,7 +328,7 @@ public: /// This is not the same as BitVector::size() which returns the size of the /// universe. /// - unsigned size() const { + size_type size() const { assert(NumFree <= Dense.size() && "Out-of-bounds free entries"); return Dense.size() - NumFree; } @@ -378,7 +379,7 @@ public: /// Returns the number of elements identified by Key. This will be linear in /// the number of elements of that key. - unsigned count(const KeyT &Key) const { + size_type count(const KeyT &Key) const { unsigned Ret = 0; for (const_iterator It = find(Key); It != end(); ++It) ++Ret; diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 899f2e4..632d52a 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -124,6 +124,7 @@ class SparseSet { typedef typename KeyFunctorT::argument_type KeyT; typedef SmallVector DenseT; + typedef unsigned size_type; DenseT Dense; SparseT *Sparse; unsigned Universe; @@ -186,7 +187,7 @@ public: /// This is not the same as BitVector::size() which returns the size of the /// universe. /// - unsigned size() const { return Dense.size(); } + size_type size() const { return Dense.size(); } /// clear - Clears the set. This is a very fast constant time operation. /// @@ -231,7 +232,7 @@ public: /// count - Returns 1 if this set contains an element identified by Key, /// 0 otherwise. /// - unsigned count(const KeyT &Key) const { + size_type count(const KeyT &Key) const { return find(Key) == end() ? 0 : 1; } diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index ecac5dd..c40e5e2 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -64,7 +64,7 @@ protected: } StringMapImpl(unsigned InitSize, unsigned ItemSize); - void RehashTable(); + unsigned RehashTable(unsigned BucketNo = 0); /// LookupBucketFor - Look up the bucket that the specified string should end /// up in. If it already exists as a key in the map, the Item pointer for the @@ -139,10 +139,10 @@ public: /// Create - Create a StringMapEntry for the specified key and default /// construct the value. template - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, InitType InitVal) { - unsigned KeyLength = static_cast(KeyEnd-KeyStart); + unsigned KeyLength = Key.size(); // Allocate a new item with space for the string at the end and a null // terminator. @@ -158,27 +158,25 @@ public: // Copy the string information. char *StrBuffer = const_cast(NewItem->getKeyData()); - memcpy(StrBuffer, KeyStart, KeyLength); + memcpy(StrBuffer, Key.data(), KeyLength); StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. return NewItem; } template - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, - AllocatorTy &Allocator) { - return Create(KeyStart, KeyEnd, Allocator, 0); + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { + return Create(Key, Allocator, ValueTy()); } /// Create - Create a StringMapEntry with normal malloc/free. template - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, - InitType InitVal) { + static StringMapEntry *Create(StringRef Key, InitType InitVal) { MallocAllocator A; - return Create(KeyStart, KeyEnd, A, std::move(InitVal)); + return Create(Key, A, std::move(InitVal)); } - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) { - return Create(KeyStart, KeyEnd, ValueTy()); + static StringMapEntry *Create(StringRef Key) { + return Create(Key, ValueTy()); } /// GetStringMapEntryFromValue - Given a value that is known to be embedded @@ -325,6 +323,28 @@ public: return true; } + /// insert - Inserts the specified key/value pair into the map if the key + /// isn't already in the map. The bool component of the returned pair is true + /// if and only if the insertion takes place, and the iterator component of + /// the pair points to the element with key equivalent to the key of the pair. + std::pair insert(std::pair KV) { + unsigned BucketNo = LookupBucketFor(KV.first); + StringMapEntryBase *&Bucket = TheTable[BucketNo]; + if (Bucket && Bucket != getTombstoneVal()) + return std::make_pair(iterator(TheTable + BucketNo, false), + false); // Already exists in map. + + if (Bucket == getTombstoneVal()) + --NumTombstones; + Bucket = + MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); + ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); + + BucketNo = RehashTable(BucketNo); + return std::make_pair(iterator(TheTable + BucketNo, false), true); + } + // clear - Empties out the StringMap void clear() { if (empty()) return; @@ -348,25 +368,7 @@ public: /// return. template MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) { - unsigned BucketNo = LookupBucketFor(Key); - StringMapEntryBase *&Bucket = TheTable[BucketNo]; - if (Bucket && Bucket != getTombstoneVal()) - return *static_cast(Bucket); - - MapEntryTy *NewItem = - MapEntryTy::Create(Key.begin(), Key.end(), Allocator, std::move(Val)); - - if (Bucket == getTombstoneVal()) - --NumTombstones; - ++NumItems; - assert(NumItems + NumTombstones <= NumBuckets); - - // Fill in the bucket for the hash table. The FullHashValue was already - // filled in by LookupBucketFor. - Bucket = NewItem; - - RehashTable(); - return *NewItem; + return *insert(std::make_pair(Key, std::move(Val))).first; } MapEntryTy &GetOrCreateValue(StringRef Key) { diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 95f3380..2867a0e 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -76,7 +76,8 @@ public: le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) amdil, // amdil: amd IL spir, // SPIR: standard portable IR for OpenCL 32-bit version - spir64 // SPIR: standard portable IR for OpenCL 64-bit version + spir64, // SPIR: standard portable IR for OpenCL 64-bit version + kalimba // Kalimba: generic kalimba }; enum VendorType { UnknownVendor, @@ -88,7 +89,9 @@ public: BGQ, Freescale, IBM, - NVIDIA + ImaginationTechnologies, + NVIDIA, + CSR }; enum OSType { UnknownOS, @@ -350,6 +353,10 @@ public: return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC; } + bool isWindowsItaniumEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::Itanium; + } + bool isWindowsCygwinEnvironment() const { return getOS() == Triple::Cygwin || (getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus); diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index a54fd74..4be3ee6 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -182,6 +182,10 @@ namespace llvm { assert(isValid() && "Invalid twine!"); } + /// Since the intended use of twines is as temporary objects, assignments + /// when concatenating might cause undefined behavior or stack corruptions + Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION; + /// isNull - Check for the null twine. bool isNull() const { return getLHSKind() == NullKind; diff --git a/include/llvm/ADT/UniqueVector.h b/include/llvm/ADT/UniqueVector.h index 2d02d1c..a9cb2f5 100644 --- a/include/llvm/ADT/UniqueVector.h +++ b/include/llvm/ADT/UniqueVector.h @@ -22,13 +22,18 @@ namespace llvm { /// class should have an implementation of operator== and of operator<. /// Entries can be fetched using operator[] with the entry ID. template class UniqueVector { +public: + typedef typename std::vector VectorType; + typedef typename VectorType::iterator iterator; + typedef typename VectorType::const_iterator const_iterator; + private: // Map - Used to handle the correspondence of entry to ID. std::map Map; // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. // - std::vector Vector; + VectorType Vector; public: /// insert - Append entry to the vector if it doesn't already exist. Returns @@ -68,6 +73,18 @@ public: return Vector[ID - 1]; } + /// \brief Return an iterator to the start of the vector. + iterator begin() { return Vector.begin(); } + + /// \brief Return an iterator to the start of the vector. + const_iterator begin() const { return Vector.begin(); } + + /// \brief Return an iterator to the end of the vector. + iterator end() { return Vector.end(); } + + /// \brief Return an iterator to the end of the vector. + const_iterator end() const { return Vector.end(); } + /// size - Returns the number of entries in the vector. /// size_t size() const { return Vector.size(); } diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 8852866..79d52fc 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -274,6 +274,14 @@ public: UnknownModRefBehavior = Anywhere | ModRef }; + /// Get the location associated with a pointer argument of a callsite. + /// The mask bits are set to indicate the allowed aliasing ModRef kinds. + /// Note that these mask bits do not necessarily account for the overall + /// behavior of the function, but rather only provide additional + /// per-argument information. + virtual Location getArgLocation(ImmutableCallSite CS, unsigned ArgIdx, + ModRefResult &Mask); + /// getModRefBehavior - Return the behavior when calling the given call site. virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index bd72d3e..7340801 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -22,6 +22,7 @@ #include "llvm/Support/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ScaledNumber.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -32,676 +33,6 @@ //===----------------------------------------------------------------------===// // -// UnsignedFloat definition. -// -// TODO: Make this private to BlockFrequencyInfoImpl or delete. -// -//===----------------------------------------------------------------------===// -namespace llvm { - -class UnsignedFloatBase { -public: - static const int32_t MaxExponent = 16383; - static const int32_t MinExponent = -16382; - static const int DefaultPrecision = 10; - - static void dump(uint64_t D, int16_t E, int Width); - static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width, - unsigned Precision); - static std::string toString(uint64_t D, int16_t E, int Width, - unsigned Precision); - static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); } - static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); } - static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); } - - static std::pair splitSigned(int64_t N) { - if (N >= 0) - return std::make_pair(N, false); - uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N); - return std::make_pair(Unsigned, true); - } - static int64_t joinSigned(uint64_t U, bool IsNeg) { - if (U > uint64_t(INT64_MAX)) - return IsNeg ? INT64_MIN : INT64_MAX; - return IsNeg ? -int64_t(U) : int64_t(U); - } - - static int32_t extractLg(const std::pair &Lg) { - return Lg.first; - } - static int32_t extractLgFloor(const std::pair &Lg) { - return Lg.first - (Lg.second > 0); - } - static int32_t extractLgCeiling(const std::pair &Lg) { - return Lg.first + (Lg.second < 0); - } - - static std::pair divide64(uint64_t L, uint64_t R); - static std::pair multiply64(uint64_t L, uint64_t R); - - static int compare(uint64_t L, uint64_t R, int Shift) { - assert(Shift >= 0); - assert(Shift < 64); - - uint64_t L_adjusted = L >> Shift; - if (L_adjusted < R) - return -1; - if (L_adjusted > R) - return 1; - - return L > L_adjusted << Shift ? 1 : 0; - } -}; - -/// \brief Simple representation of an unsigned floating point. -/// -/// UnsignedFloat is a unsigned floating point number. It uses simple -/// saturation arithmetic, and every operation is well-defined for every value. -/// -/// The number is split into a signed exponent and unsigned digits. The number -/// represented is \c getDigits()*2^getExponent(). In this way, the digits are -/// much like the mantissa in the x87 long double, but there is no canonical -/// form, so the same number can be represented by many bit representations -/// (it's always in "denormal" mode). -/// -/// UnsignedFloat is templated on the underlying integer type for digits, which -/// is expected to be one of uint64_t, uint32_t, uint16_t or uint8_t. -/// -/// Unlike builtin floating point types, UnsignedFloat is portable. -/// -/// Unlike APFloat, UnsignedFloat does not model architecture floating point -/// behaviour (this should make it a little faster), and implements most -/// operators (this makes it usable). -/// -/// UnsignedFloat is totally ordered. However, there is no canonical form, so -/// there are multiple representations of most scalars. E.g.: -/// -/// UnsignedFloat(8u, 0) == UnsignedFloat(4u, 1) -/// UnsignedFloat(4u, 1) == UnsignedFloat(2u, 2) -/// UnsignedFloat(2u, 2) == UnsignedFloat(1u, 3) -/// -/// UnsignedFloat implements most arithmetic operations. Precision is kept -/// where possible. Uses simple saturation arithmetic, so that operations -/// saturate to 0.0 or getLargest() rather than under or overflowing. It has -/// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0. -/// Any other division by 0.0 is defined to be getLargest(). -/// -/// As a convenience for modifying the exponent, left and right shifting are -/// both implemented, and both interpret negative shifts as positive shifts in -/// the opposite direction. -/// -/// Exponents are limited to the range accepted by x87 long double. This makes -/// it trivial to add functionality to convert to APFloat (this is already -/// relied on for the implementation of printing). -/// -/// The current plan is to gut this and make the necessary parts of it (even -/// more) private to BlockFrequencyInfo. -template class UnsignedFloat : UnsignedFloatBase { -public: - static_assert(!std::numeric_limits::is_signed, - "only unsigned floats supported"); - - typedef DigitsT DigitsType; - -private: - typedef std::numeric_limits DigitsLimits; - - static const int Width = sizeof(DigitsType) * 8; - static_assert(Width <= 64, "invalid integer width for digits"); - -private: - DigitsType Digits; - int16_t Exponent; - -public: - UnsignedFloat() : Digits(0), Exponent(0) {} - - UnsignedFloat(DigitsType Digits, int16_t Exponent) - : Digits(Digits), Exponent(Exponent) {} - -private: - UnsignedFloat(const std::pair &X) - : Digits(X.first), Exponent(X.second) {} - -public: - static UnsignedFloat getZero() { return UnsignedFloat(0, 0); } - static UnsignedFloat getOne() { return UnsignedFloat(1, 0); } - static UnsignedFloat getLargest() { - return UnsignedFloat(DigitsLimits::max(), MaxExponent); - } - static UnsignedFloat getFloat(uint64_t N) { return adjustToWidth(N, 0); } - static UnsignedFloat getInverseFloat(uint64_t N) { - return getFloat(N).invert(); - } - static UnsignedFloat getFraction(DigitsType N, DigitsType D) { - return getQuotient(N, D); - } - - int16_t getExponent() const { return Exponent; } - DigitsType getDigits() const { return Digits; } - - /// \brief Convert to the given integer type. - /// - /// Convert to \c IntT using simple saturating arithmetic, truncating if - /// necessary. - template IntT toInt() const; - - bool isZero() const { return !Digits; } - bool isLargest() const { return *this == getLargest(); } - bool isOne() const { - if (Exponent > 0 || Exponent <= -Width) - return false; - return Digits == DigitsType(1) << -Exponent; - } - - /// \brief The log base 2, rounded. - /// - /// Get the lg of the scalar. lg 0 is defined to be INT32_MIN. - int32_t lg() const { return extractLg(lgImpl()); } - - /// \brief The log base 2, rounded towards INT32_MIN. - /// - /// Get the lg floor. lg 0 is defined to be INT32_MIN. - int32_t lgFloor() const { return extractLgFloor(lgImpl()); } - - /// \brief The log base 2, rounded towards INT32_MAX. - /// - /// Get the lg ceiling. lg 0 is defined to be INT32_MIN. - int32_t lgCeiling() const { return extractLgCeiling(lgImpl()); } - - bool operator==(const UnsignedFloat &X) const { return compare(X) == 0; } - bool operator<(const UnsignedFloat &X) const { return compare(X) < 0; } - bool operator!=(const UnsignedFloat &X) const { return compare(X) != 0; } - bool operator>(const UnsignedFloat &X) const { return compare(X) > 0; } - bool operator<=(const UnsignedFloat &X) const { return compare(X) <= 0; } - bool operator>=(const UnsignedFloat &X) const { return compare(X) >= 0; } - - bool operator!() const { return isZero(); } - - /// \brief Convert to a decimal representation in a string. - /// - /// Convert to a string. Uses scientific notation for very large/small - /// numbers. Scientific notation is used roughly for numbers outside of the - /// range 2^-64 through 2^64. - /// - /// \c Precision indicates the number of decimal digits of precision to use; - /// 0 requests the maximum available. - /// - /// As a special case to make debugging easier, if the number is small enough - /// to convert without scientific notation and has more than \c Precision - /// digits before the decimal place, it's printed accurately to the first - /// digit past zero. E.g., assuming 10 digits of precision: - /// - /// 98765432198.7654... => 98765432198.8 - /// 8765432198.7654... => 8765432198.8 - /// 765432198.7654... => 765432198.8 - /// 65432198.7654... => 65432198.77 - /// 5432198.7654... => 5432198.765 - std::string toString(unsigned Precision = DefaultPrecision) { - return UnsignedFloatBase::toString(Digits, Exponent, Width, Precision); - } - - /// \brief Print a decimal representation. - /// - /// Print a string. See toString for documentation. - raw_ostream &print(raw_ostream &OS, - unsigned Precision = DefaultPrecision) const { - return UnsignedFloatBase::print(OS, Digits, Exponent, Width, Precision); - } - void dump() const { return UnsignedFloatBase::dump(Digits, Exponent, Width); } - - UnsignedFloat &operator+=(const UnsignedFloat &X); - UnsignedFloat &operator-=(const UnsignedFloat &X); - UnsignedFloat &operator*=(const UnsignedFloat &X); - UnsignedFloat &operator/=(const UnsignedFloat &X); - UnsignedFloat &operator<<=(int16_t Shift) { shiftLeft(Shift); return *this; } - UnsignedFloat &operator>>=(int16_t Shift) { shiftRight(Shift); return *this; } - -private: - void shiftLeft(int32_t Shift); - void shiftRight(int32_t Shift); - - /// \brief Adjust two floats to have matching exponents. - /// - /// Adjust \c this and \c X to have matching exponents. Returns the new \c X - /// by value. Does nothing if \a isZero() for either. - /// - /// The value that compares smaller will lose precision, and possibly become - /// \a isZero(). - UnsignedFloat matchExponents(UnsignedFloat X); - - /// \brief Increase exponent to match another float. - /// - /// Increases \c this to have an exponent matching \c X. May decrease the - /// exponent of \c X in the process, and \c this may possibly become \a - /// isZero(). - void increaseExponentToMatch(UnsignedFloat &X, int32_t ExponentDiff); - -public: - /// \brief Scale a large number accurately. - /// - /// Scale N (multiply it by this). Uses full precision multiplication, even - /// if Width is smaller than 64, so information is not lost. - uint64_t scale(uint64_t N) const; - uint64_t scaleByInverse(uint64_t N) const { - // TODO: implement directly, rather than relying on inverse. Inverse is - // expensive. - return inverse().scale(N); - } - int64_t scale(int64_t N) const { - std::pair Unsigned = splitSigned(N); - return joinSigned(scale(Unsigned.first), Unsigned.second); - } - int64_t scaleByInverse(int64_t N) const { - std::pair Unsigned = splitSigned(N); - return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second); - } - - int compare(const UnsignedFloat &X) const; - int compareTo(uint64_t N) const { - UnsignedFloat Float = getFloat(N); - int Compare = compare(Float); - if (Width == 64 || Compare != 0) - return Compare; - - // Check for precision loss. We know *this == RoundTrip. - uint64_t RoundTrip = Float.template toInt(); - return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1; - } - int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } - - UnsignedFloat &invert() { return *this = UnsignedFloat::getFloat(1) / *this; } - UnsignedFloat inverse() const { return UnsignedFloat(*this).invert(); } - -private: - static UnsignedFloat getProduct(DigitsType L, DigitsType R); - static UnsignedFloat getQuotient(DigitsType Dividend, DigitsType Divisor); - - std::pair lgImpl() const; - static int countLeadingZerosWidth(DigitsType Digits) { - if (Width == 64) - return countLeadingZeros64(Digits); - if (Width == 32) - return countLeadingZeros32(Digits); - return countLeadingZeros32(Digits) + Width - 32; - } - - static UnsignedFloat adjustToWidth(uint64_t N, int32_t S) { - assert(S >= MinExponent); - assert(S <= MaxExponent); - if (Width == 64 || N <= DigitsLimits::max()) - return UnsignedFloat(N, S); - - // Shift right. - int Shift = 64 - Width - countLeadingZeros64(N); - DigitsType Shifted = N >> Shift; - - // Round. - assert(S + Shift <= MaxExponent); - return getRounded(UnsignedFloat(Shifted, S + Shift), - N & UINT64_C(1) << (Shift - 1)); - } - - static UnsignedFloat getRounded(UnsignedFloat P, bool Round) { - if (!Round) - return P; - if (P.Digits == DigitsLimits::max()) - // Careful of overflow in the exponent. - return UnsignedFloat(1, P.Exponent) <<= Width; - return UnsignedFloat(P.Digits + 1, P.Exponent); - } -}; - -#define UNSIGNED_FLOAT_BOP(op, base) \ - template \ - UnsignedFloat operator op(const UnsignedFloat &L, \ - const UnsignedFloat &R) { \ - return UnsignedFloat(L) base R; \ - } -UNSIGNED_FLOAT_BOP(+, += ) -UNSIGNED_FLOAT_BOP(-, -= ) -UNSIGNED_FLOAT_BOP(*, *= ) -UNSIGNED_FLOAT_BOP(/, /= ) -UNSIGNED_FLOAT_BOP(<<, <<= ) -UNSIGNED_FLOAT_BOP(>>, >>= ) -#undef UNSIGNED_FLOAT_BOP - -template -raw_ostream &operator<<(raw_ostream &OS, const UnsignedFloat &X) { - return X.print(OS, 10); -} - -#define UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, T1, T2) \ - template \ - bool operator op(const UnsignedFloat &L, T1 R) { \ - return L.compareTo(T2(R)) op 0; \ - } \ - template \ - bool operator op(T1 L, const UnsignedFloat &R) { \ - return 0 op R.compareTo(T2(L)); \ - } -#define UNSIGNED_FLOAT_COMPARE_TO(op) \ - UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \ - UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \ - UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, int64_t, int64_t) \ - UNSIGNED_FLOAT_COMPARE_TO_TYPE(op, int32_t, int64_t) -UNSIGNED_FLOAT_COMPARE_TO(< ) -UNSIGNED_FLOAT_COMPARE_TO(> ) -UNSIGNED_FLOAT_COMPARE_TO(== ) -UNSIGNED_FLOAT_COMPARE_TO(!= ) -UNSIGNED_FLOAT_COMPARE_TO(<= ) -UNSIGNED_FLOAT_COMPARE_TO(>= ) -#undef UNSIGNED_FLOAT_COMPARE_TO -#undef UNSIGNED_FLOAT_COMPARE_TO_TYPE - -template -uint64_t UnsignedFloat::scale(uint64_t N) const { - if (Width == 64 || N <= DigitsLimits::max()) - return (getFloat(N) * *this).template toInt(); - - // Defer to the 64-bit version. - return UnsignedFloat(Digits, Exponent).scale(N); -} - -template -UnsignedFloat UnsignedFloat::getProduct(DigitsType L, - DigitsType R) { - // Check for zero. - if (!L || !R) - return getZero(); - - // Check for numbers that we can compute with 64-bit math. - if (Width <= 32 || (L <= UINT32_MAX && R <= UINT32_MAX)) - return adjustToWidth(uint64_t(L) * uint64_t(R), 0); - - // Do the full thing. - return UnsignedFloat(multiply64(L, R)); -} -template -UnsignedFloat UnsignedFloat::getQuotient(DigitsType Dividend, - DigitsType Divisor) { - // Check for zero. - if (!Dividend) - return getZero(); - if (!Divisor) - return getLargest(); - - if (Width == 64) - return UnsignedFloat(divide64(Dividend, Divisor)); - - // We can compute this with 64-bit math. - int Shift = countLeadingZeros64(Dividend); - uint64_t Shifted = uint64_t(Dividend) << Shift; - uint64_t Quotient = Shifted / Divisor; - - // If Quotient needs to be shifted, then adjustToWidth will round. - if (Quotient > DigitsLimits::max()) - return adjustToWidth(Quotient, -Shift); - - // Round based on the value of the next bit. - return getRounded(UnsignedFloat(Quotient, -Shift), - Shifted % Divisor >= getHalf(Divisor)); -} - -template -template -IntT UnsignedFloat::toInt() const { - typedef std::numeric_limits Limits; - if (*this < 1) - return 0; - if (*this >= Limits::max()) - return Limits::max(); - - IntT N = Digits; - if (Exponent > 0) { - assert(size_t(Exponent) < sizeof(IntT) * 8); - return N << Exponent; - } - if (Exponent < 0) { - assert(size_t(-Exponent) < sizeof(IntT) * 8); - return N >> -Exponent; - } - return N; -} - -template -std::pair UnsignedFloat::lgImpl() const { - if (isZero()) - return std::make_pair(INT32_MIN, 0); - - // Get the floor of the lg of Digits. - int32_t LocalFloor = Width - countLeadingZerosWidth(Digits) - 1; - - // Get the floor of the lg of this. - int32_t Floor = Exponent + LocalFloor; - if (Digits == UINT64_C(1) << LocalFloor) - return std::make_pair(Floor, 0); - - // Round based on the next digit. - assert(LocalFloor >= 1); - bool Round = Digits & UINT64_C(1) << (LocalFloor - 1); - return std::make_pair(Floor + Round, Round ? 1 : -1); -} - -template -UnsignedFloat UnsignedFloat::matchExponents(UnsignedFloat X) { - if (isZero() || X.isZero() || Exponent == X.Exponent) - return X; - - int32_t Diff = int32_t(X.Exponent) - int32_t(Exponent); - if (Diff > 0) - increaseExponentToMatch(X, Diff); - else - X.increaseExponentToMatch(*this, -Diff); - return X; -} -template -void UnsignedFloat::increaseExponentToMatch(UnsignedFloat &X, - int32_t ExponentDiff) { - assert(ExponentDiff > 0); - if (ExponentDiff >= 2 * Width) { - *this = getZero(); - return; - } - - // Use up any leading zeros on X, and then shift this. - int32_t ShiftX = std::min(countLeadingZerosWidth(X.Digits), ExponentDiff); - assert(ShiftX < Width); - - int32_t ShiftThis = ExponentDiff - ShiftX; - if (ShiftThis >= Width) { - *this = getZero(); - return; - } - - X.Digits <<= ShiftX; - X.Exponent -= ShiftX; - Digits >>= ShiftThis; - Exponent += ShiftThis; - return; -} - -template -UnsignedFloat &UnsignedFloat:: -operator+=(const UnsignedFloat &X) { - if (isLargest() || X.isZero()) - return *this; - if (isZero() || X.isLargest()) - return *this = X; - - // Normalize exponents. - UnsignedFloat Scaled = matchExponents(X); - - // Check for zero again. - if (isZero()) - return *this = Scaled; - if (Scaled.isZero()) - return *this; - - // Compute sum. - DigitsType Sum = Digits + Scaled.Digits; - bool DidOverflow = Sum < Digits; - Digits = Sum; - if (!DidOverflow) - return *this; - - if (Exponent == MaxExponent) - return *this = getLargest(); - - ++Exponent; - Digits = UINT64_C(1) << (Width - 1) | Digits >> 1; - - return *this; -} -template -UnsignedFloat &UnsignedFloat:: -operator-=(const UnsignedFloat &X) { - if (X.isZero()) - return *this; - if (*this <= X) - return *this = getZero(); - - // Normalize exponents. - UnsignedFloat Scaled = matchExponents(X); - assert(Digits >= Scaled.Digits); - - // Compute difference. - if (!Scaled.isZero()) { - Digits -= Scaled.Digits; - return *this; - } - - // Check if X just barely lost its last bit. E.g., for 32-bit: - // - // 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32 - if (*this == UnsignedFloat(1, X.lgFloor() + Width)) { - Digits = DigitsType(0) - 1; - --Exponent; - } - return *this; -} -template -UnsignedFloat &UnsignedFloat:: -operator*=(const UnsignedFloat &X) { - if (isZero()) - return *this; - if (X.isZero()) - return *this = X; - - // Save the exponents. - int32_t Exponents = int32_t(Exponent) + int32_t(X.Exponent); - - // Get the raw product. - *this = getProduct(Digits, X.Digits); - - // Combine with exponents. - return *this <<= Exponents; -} -template -UnsignedFloat &UnsignedFloat:: -operator/=(const UnsignedFloat &X) { - if (isZero()) - return *this; - if (X.isZero()) - return *this = getLargest(); - - // Save the exponents. - int32_t Exponents = int32_t(Exponent) - int32_t(X.Exponent); - - // Get the raw quotient. - *this = getQuotient(Digits, X.Digits); - - // Combine with exponents. - return *this <<= Exponents; -} -template -void UnsignedFloat::shiftLeft(int32_t Shift) { - if (!Shift || isZero()) - return; - assert(Shift != INT32_MIN); - if (Shift < 0) { - shiftRight(-Shift); - return; - } - - // Shift as much as we can in the exponent. - int32_t ExponentShift = std::min(Shift, MaxExponent - Exponent); - Exponent += ExponentShift; - if (ExponentShift == Shift) - return; - - // Check this late, since it's rare. - if (isLargest()) - return; - - // Shift the digits themselves. - Shift -= ExponentShift; - if (Shift > countLeadingZerosWidth(Digits)) { - // Saturate. - *this = getLargest(); - return; - } - - Digits <<= Shift; - return; -} - -template -void UnsignedFloat::shiftRight(int32_t Shift) { - if (!Shift || isZero()) - return; - assert(Shift != INT32_MIN); - if (Shift < 0) { - shiftLeft(-Shift); - return; - } - - // Shift as much as we can in the exponent. - int32_t ExponentShift = std::min(Shift, Exponent - MinExponent); - Exponent -= ExponentShift; - if (ExponentShift == Shift) - return; - - // Shift the digits themselves. - Shift -= ExponentShift; - if (Shift >= Width) { - // Saturate. - *this = getZero(); - return; - } - - Digits >>= Shift; - return; -} - -template -int UnsignedFloat::compare(const UnsignedFloat &X) const { - // Check for zero. - if (isZero()) - return X.isZero() ? 0 : -1; - if (X.isZero()) - return 1; - - // Check for the scale. Use lgFloor to be sure that the exponent difference - // is always lower than 64. - int32_t lgL = lgFloor(), lgR = X.lgFloor(); - if (lgL != lgR) - return lgL < lgR ? -1 : 1; - - // Compare digits. - if (Exponent < X.Exponent) - return UnsignedFloatBase::compare(Digits, X.Digits, X.Exponent - Exponent); - - return -UnsignedFloatBase::compare(X.Digits, Digits, Exponent - X.Exponent); -} - -template struct isPodLike> { - static const bool value = true; -}; -} - -//===----------------------------------------------------------------------===// -// // BlockMass definition. // // TODO: Make this private to BlockFrequencyInfoImpl or delete. @@ -770,11 +101,11 @@ public: bool operator<(const BlockMass &X) const { return Mass < X.Mass; } bool operator>(const BlockMass &X) const { return Mass > X.Mass; } - /// \brief Convert to floating point. + /// \brief Convert to scaled number. /// - /// Convert to a float. \a isFull() gives 1.0, while \a isEmpty() gives - /// slightly above 0.0. - UnsignedFloat toFloat() const; + /// Convert to \a ScaledNumber. \a isFull() gives 1.0, while \a isEmpty() + /// gives slightly above 0.0. + ScaledNumber toScaled() const; void dump() const; raw_ostream &print(raw_ostream &OS) const; @@ -837,7 +168,7 @@ template struct BlockEdgesAdder; /// BlockFrequencyInfoImpl. See there for details. class BlockFrequencyInfoImplBase { public: - typedef UnsignedFloat Float; + typedef ScaledNumber Scaled64; /// \brief Representative of a block. /// @@ -866,7 +197,7 @@ public: /// \brief Stats about a block itself. struct FrequencyData { - Float Floating; + Scaled64 Scaled; uint64_t Integer; }; @@ -884,7 +215,7 @@ public: NodeList Nodes; ///< Header and the members of the loop. BlockMass BackedgeMass; ///< Mass returned to loop header. BlockMass Mass; - Float Scale; + Scaled64 Scale; LoopData(LoopData *Parent, const BlockNode &Header) : Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header) {} @@ -1131,7 +462,7 @@ public: virtual raw_ostream &print(raw_ostream &OS) const { return OS; } void dump() const { print(dbgs()); } - Float getFloatingBlockFreq(const BlockNode &Node) const; + Scaled64 getFloatingBlockFreq(const BlockNode &Node) const; BlockFrequency getBlockFreq(const BlockNode &Node) const; @@ -1310,7 +641,7 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// entries point to this block. Its successors are the headers, which split /// the frequency evenly. /// -/// This algorithm leverages BlockMass and UnsignedFloat to maintain precision, +/// This algorithm leverages BlockMass and ScaledNumber to maintain precision, /// separates mass distribution from loop scaling, and dithers to eliminate /// probability mass loss. /// @@ -1568,7 +899,7 @@ public: BlockFrequency getBlockFreq(const BlockT *BB) const { return BlockFrequencyInfoImplBase::getBlockFreq(getNode(BB)); } - Float getFloatingBlockFreq(const BlockT *BB) const { + Scaled64 getFloatingBlockFreq(const BlockT *BB) const { return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB)); } diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h new file mode 100644 index 0000000..54760aa --- /dev/null +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -0,0 +1,60 @@ +//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Information about jump-instruction tables that have been created by +/// JumpInstrTables pass. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H +#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Pass.h" + +#include + +namespace llvm { +class Function; +class FunctionType; + +/// This class stores information about jump-instruction tables created by the +/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a +/// map from a function type to a vector of pairs. The first element of each +/// pair is the function that has the jumptable annotation. The second element +/// is a function that was declared by JumpInstrTables and used to replace all +/// address-taking sites for the original function. +/// +/// The information in this pass is used in AsmPrinter +/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly +/// for the jump-instruction tables. +class JumpInstrTableInfo : public ImmutablePass { +public: + static char ID; + + JumpInstrTableInfo(); + virtual ~JumpInstrTableInfo(); + const char *getPassName() const override { + return "Jump-Instruction Table Info"; + } + + typedef std::pair JumpPair; + typedef DenseMap > JumpTables; + + /// Inserts an entry in a table, adding the table if it doesn't exist. + void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump); + + /// Gets the tables. + const JumpTables &getTables() const { return Tables; } + +private: + JumpTables Tables; +}; +} + +#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */ diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 9494b7d..fd65ae5 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -142,6 +142,10 @@ namespace llvm { // information and prints it with -analyze. // FunctionPass *createMemDepPrinter(); + + // createJumpInstrTableInfoPass - This creates a pass that stores information + // about the jump tables created by JumpInstrTables + ImmutablePass *createJumpInstrTableInfoPass(); } #endif diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 82a788d..93a1a48 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -22,6 +22,16 @@ // itself is not, but in practice runtime seems to be in the order of magnitude // of dominance tree calculation. // +// WARNING: LLVM is generally very concerned about compile time such that +// the use of additional analysis passes in the default +// optimization sequence is avoided as much as possible. +// Specifically, if you do not need the RegionInfo, but dominance +// information could be sufficient please base your work only on +// the dominator tree. Most passes maintain it, such that using +// it has often near zero cost. In contrast RegionInfo is by +// default not available, is not maintained by existing +// transformations and there is no intention to do so. +// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_REGIONINFO_H diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 79fe1dc..f57f3eb 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -322,6 +322,7 @@ public: enum ShuffleKind { SK_Broadcast, ///< Broadcast element 0 to all other elements. SK_Reverse, ///< Reverse the order of the vector. + SK_Alternate, ///< Choose alternate elements from vector. SK_InsertSubvector, ///< InsertSubvector. Index indicates start offset. SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. }; diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index ce78967..83b5408 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -37,7 +37,10 @@ namespace llvm { /// for all of the elements in the vector. void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout *TD = nullptr, unsigned Depth = 0); - void computeKnownBitsLoad(const MDNode &Ranges, APInt &KnownZero); + /// Compute known bits from the range metadata. + /// \p KnownZero the set of bits that are known to be zero + void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, + APInt &KnownZero); /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around computeKnownBits. diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 04c08ab..f7e30ef 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -71,7 +71,8 @@ namespace bitc { // MODULE_CODE_PURGEVALS: [numvals] MODULE_CODE_PURGEVALS = 10, - MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N] + MODULE_CODE_GCNAME = 11, // GCNAME: [strchr x N] + MODULE_CODE_COMDAT = 12, // COMDAT: [selection_kind, name] }; /// PARAMATTR blocks have code for defining a parameter attribute set. @@ -372,7 +373,16 @@ namespace bitc { ATTR_KIND_COLD = 36, ATTR_KIND_OPTIMIZE_NONE = 37, ATTR_KIND_IN_ALLOCA = 38, - ATTR_KIND_NON_NULL = 39 + ATTR_KIND_NON_NULL = 39, + ATTR_KIND_JUMP_TABLE = 40 + }; + + enum ComdatSelectionKindCodes { + COMDAT_SELECTION_KIND_ANY = 1, + COMDAT_SELECTION_KIND_EXACT_MATCH = 2, + COMDAT_SELECTION_KIND_LARGEST = 3, + COMDAT_SELECTION_KIND_NO_DUPLICATES = 4, + COMDAT_SELECTION_KIND_SAME_SIZE = 5, }; } // End bitc namespace diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 4c194a6..8cf5735 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -41,14 +41,11 @@ namespace llvm { LLVMContext &Context, std::string *ErrMsg = nullptr); - /// getBitcodeTargetTriple - Read the header of the specified bitcode - /// buffer and extract just the triple information. If successful, - /// this returns a string and *does not* take ownership - /// of 'buffer'. On error, this returns "", and fills in *ErrMsg - /// if ErrMsg is non-null. + /// Read the header of the specified bitcode buffer and extract just the + /// triple information. If successful, this returns a string and *does not* + /// take ownership of 'buffer'. On error, this returns "". std::string getBitcodeTargetTriple(MemoryBuffer *Buffer, - LLVMContext &Context, - std::string *ErrMsg = nullptr); + LLVMContext &Context); /// Read the specified bitcode file, returning the module. /// This method *never* takes ownership of Buffer. diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index c3aefd4..c5060fb 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file declares several CodeGen-specific LLVM IR analysis utilties. +// This file declares several CodeGen-specific LLVM IR analysis utilities. // //===----------------------------------------------------------------------===// @@ -86,7 +86,7 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// between it and the return. /// /// This function only tests target-independent requirements. -bool isInTailCallPosition(ImmutableCallSite CS, const TargetLowering &TLI); +bool isInTailCallPosition(ImmutableCallSite CS, const SelectionDAG &DAG); /// Test if given that the input instruction is in the tail call position if the /// return type or any attributes of the function will inhibit tail call diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index b53fb42..e1c9a14 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -52,7 +52,6 @@ class MCSubtargetInfo; class MCSymbol; class MDNode; class DwarfDebug; -class DwarfException; class Mangler; class TargetLoweringObjectFile; class DataLayout; diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 2956ad8..449d934 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -202,6 +202,21 @@ FunctionSections("function-sections", cl::desc("Emit functions into separate sections"), cl::init(false)); +cl::opt +JTableType("jump-table-type", + cl::desc("Choose the type of Jump-Instruction Table for jumptable."), + cl::init(JumpTable::Single), + cl::values( + clEnumValN(JumpTable::Single, "single", + "Create a single table for all jumptable functions"), + clEnumValN(JumpTable::Arity, "arity", + "Create one table per number of parameters."), + clEnumValN(JumpTable::Simplified, "simplified", + "Create one table per simplified function type."), + clEnumValN(JumpTable::Full, "full", + "Create one table per unique function type."), + clEnumValEnd)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -228,6 +243,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.FunctionSections = FunctionSections; Options.MCOptions = InitMCTargetOptionsFromFlags(); + Options.JTType = JTableType; return Options; } diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index bfeede2..2bebae6 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -23,6 +23,7 @@ namespace llvm { class AllocaInst; class Constant; class ConstantFP; +class CallInst; class DataLayout; class FunctionLoweringInfo; class Instruction; @@ -48,6 +49,7 @@ class FastISel { protected: DenseMap LocalValueMap; FunctionLoweringInfo &FuncInfo; + MachineFunction *MF; MachineRegisterInfo &MRI; MachineFrameInfo &MFI; MachineConstantPool &MCP; @@ -373,6 +375,12 @@ protected: /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); + /// Test whether the given value has exactly one use. + bool hasTrivialKill(const Value *V) const; + + /// \brief Create a machine mem operand from the given instruction. + MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); @@ -380,6 +388,7 @@ private: bool SelectGetElementPtr(const User *I); + bool SelectStackmap(const CallInst *I); bool SelectCall(const User *I); bool SelectBitCast(const User *I); @@ -409,8 +418,8 @@ private: /// heavy instructions like calls. void flushLocalValueMap(); - /// Test whether the given value has exactly one use. - bool hasTrivialKill(const Value *V) const; + bool addStackMapLiveVars(SmallVectorImpl &Ops, + const CallInst *CI, unsigned StartIdx); }; } diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 49891b2..a8f2368 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -379,6 +379,37 @@ namespace ISD { /// operand, a ValueType node. SIGN_EXTEND_INREG, + /// ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an + /// in-register any-extension of the low lanes of an integer vector. The + /// result type must have fewer elements than the operand type, and those + /// elements must be larger integer types such that the total size of the + /// operand type and the result type match. Each of the low operand + /// elements is any-extended into the corresponding, wider result + /// elements with the high bits becoming undef. + ANY_EXTEND_VECTOR_INREG, + + /// SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an + /// in-register sign-extension of the low lanes of an integer vector. The + /// result type must have fewer elements than the operand type, and those + /// elements must be larger integer types such that the total size of the + /// operand type and the result type match. Each of the low operand + /// elements is sign-extended into the corresponding, wider result + /// elements. + // FIXME: The SIGN_EXTEND_INREG node isn't specifically limited to + // scalars, but it also doesn't handle vectors well. Either it should be + // restricted to scalars or this node (and its handling) should be merged + // into it. + SIGN_EXTEND_VECTOR_INREG, + + /// ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an + /// in-register zero-extension of the low lanes of an integer vector. The + /// result type must have fewer elements than the operand type, and those + /// elements must be larger integer types such that the total size of the + /// operand type and the result type match. Each of the low operand + /// elements is zero-extended into the corresponding, wider result + /// elements. + ZERO_EXTEND_VECTOR_INREG, + /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned /// integer. FP_TO_SINT, @@ -619,6 +650,12 @@ namespace ISD { /// This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, + /// Val, Success, OUTCHAIN + /// = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) + /// N.b. this is still a strong cmpxchg operation, so + /// Success == "Val == cmp". + ATOMIC_CMP_SWAP_WITH_SUCCESS, + /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) /// For double-word atomic operations: diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h new file mode 100644 index 0000000..6ca3d7d --- /dev/null +++ b/include/llvm/CodeGen/JumpInstrTables.h @@ -0,0 +1,104 @@ +//===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief An implementation of tables consisting of jump instructions +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H +#define LLVM_CODEGEN_JUMPINSTRTABLES_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetOptions.h" + +namespace llvm { +class Constant; +class Function; +class FunctionType; +class JumpInstrTableInfo; +class Module; + +/// A class to manage a set of jump tables indexed on function type. It looks at +/// each function in the module to find all the functions that have the +/// jumptable attribute set. For each such function, it creates a new +/// jump-instruction-table function and stores the mapping in the ImmutablePass +/// JumpInstrTableInfo. +/// +/// These special functions get lowered in AsmPrinter to assembly of the form: +/// \verbatim +/// .globl f +/// .type f,@function +/// .align 8,0x90 +/// f: +/// jmp f_orig@PLT +/// \endverbatim +/// +/// Support for an architecture depends on two functions in TargetInstrInfo: +/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the +/// appropriate instructions for the jump statement (an unconditional branch) +/// and for padding to make the table have a size that is a power of two. This +/// padding uses a trap instruction to ensure that calls to this area halt the +/// program. The default implementations of these functions call +/// llvm_unreachable. +class JumpInstrTables : public ModulePass { +public: + static char ID; + + JumpInstrTables(); + JumpInstrTables(JumpTable::JumpTableType JTT); + virtual ~JumpInstrTables(); + bool runOnModule(Module &M) override; + const char *getPassName() const override { return "Jump-Instruction Tables"; } + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Creates a jump-instruction table function for the Target and adds it to + /// the tables. + Function *insertEntry(Module &M, Function *Target); + + /// Checks to see if there is already a table for the given FunctionType. + bool hasTable(FunctionType *FunTy); + +private: + /// The metadata used while a jump table is being built + struct TableMeta { + /// The number of this table + unsigned TableNum; + + /// The current number of jump entries in the table. + unsigned Count; + }; + + typedef DenseMap JumpMap; + + /// Maps the function into a subset of function types, depending on the + /// jump-instruction table style selected from JumpTableTypes in + /// JumpInstrTables.cpp. The choice of mapping determines the number of + /// jump-instruction tables generated by this pass. E.g., the simplest mapping + /// converts every function type into void f(); so, all functions end up in a + /// single table. + FunctionType *transformType(FunctionType *FunTy); + + /// The current state of functions and jump entries in the table(s). + JumpMap Metadata; + + /// The ImmutablePass that stores information about the generated tables. + JumpInstrTableInfo *JITI; + + /// The total number of tables. + unsigned TableCount; + + /// The type of tables to build. + JumpTable::JumpTableType JTType; +}; + +/// Creates a JumpInstrTables pass for the given type of jump table. +ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT); +} + +#endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */ diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 31d6872..036aea3 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -197,6 +197,9 @@ public: /// dump - Print data structures to dbgs(). void dump(); + /// getOrCreateAbstractScope - Find or create an abstract lexical scope. + LexicalScope *getOrCreateAbstractScope(const MDNode *N); + private: /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If /// not available then create new lexical scope. @@ -208,9 +211,6 @@ private: /// getOrCreateInlinedScope - Find or create an inlined lexical scope. LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt); - /// getOrCreateAbstractScope - Find or create an abstract lexical scope. - LexicalScope *getOrCreateAbstractScope(const MDNode *N); - /// extractLexicalScopes - Extract instruction ranges for each lexical scopes /// for the given machine function. void extractLexicalScopes(SmallVectorImpl &MIRanges, diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index ddd623c..176665b 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -155,6 +155,17 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); + /// \brief Walk the values in the given interval and compute which ones + /// are dead. Dead values are not deleted, however: + /// - Dead PHIDef values are marked as unused. + /// - New dead machine instructions are added to the dead vector. + /// - CanSeparate is set to true if the interval may have been separated + /// into multiple connected components. + void computeDeadValues(LiveInterval *li, + LiveRange &LR, + bool *CanSeparate, + SmallVectorImpl *dead); + /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by /// existing defs in LI. PHI-defs are added as needed to maintain SSA form. diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 90bdeee4..a08cc2e 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -620,7 +620,7 @@ public: /// computeRegisterLiveness - Return whether (physical) register \c Reg /// has been ined and not ed as of just before \c MI. - /// + /// /// Search is localised to a neighborhood of /// \c Neighborhood instructions before (searching for defs or kills) and /// Neighborhood instructions after (searching just for defs) MI. @@ -635,7 +635,7 @@ public: void print(raw_ostream &OS, SlotIndexes* = nullptr) const; // Printing method used by LoopInfo. - void printAsOperand(raw_ostream &OS, bool PrintType = true); + void printAsOperand(raw_ostream &OS, bool PrintType = true) const; /// getNumber - MachineBasicBlocks are uniquely numbered at the function /// level, unless they're not in a MachineFunction yet, in which case this diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index bd0ea11..c51f8fe 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -484,6 +484,9 @@ public: /// int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable); + /// CreateFixedSpillStackObject - Create a spill slot at a fixed location + /// on the stack. Returns an index with a negative value. + int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index b0d3e02..3c82811 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -727,6 +727,9 @@ public: bool isFullCopy() const { return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg(); } + bool isExtractSubreg() const { + return getOpcode() == TargetOpcode::EXTRACT_SUBREG; + } /// isCopyLike - Return true if the instruction behaves like a copy. /// This does not include native copy instructions. @@ -947,7 +950,7 @@ public: } /// isRegTiedToDefOperand - Return true if the use operand of the specified - /// index is tied to an def operand. It also returns the def operand index by + /// index is tied to a def operand. It also returns the def operand index by /// reference if DefOpIdx is not null. bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = nullptr) const { diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index acd37e1..7d85432 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -518,9 +518,7 @@ public: return Queue.begin() + idx; } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump(); -#endif }; /// Summarize the unscheduled region. @@ -624,9 +622,9 @@ private: SmallVector ReservedCycles; #ifndef NDEBUG - // Remember the greatest operand latency as an upper bound on the number of + // Remember the greatest possible stall as an upper bound on the number of // times we should retry the pending queue because of a hazard. - unsigned MaxObservedLatency; + unsigned MaxObservedStall; #endif public: @@ -739,6 +737,217 @@ public: #endif }; +/// Base class for GenericScheduler. This class maintains information about +/// scheduling candidates based on TargetSchedModel making it easy to implement +/// heuristics for either preRA or postRA scheduling. +class GenericSchedulerBase : public MachineSchedStrategy { +public: + /// Represent the type of SchedCandidate found within a single queue. + /// pickNodeBidirectional depends on these listed by decreasing priority. + enum CandReason { + NoCand, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax, + ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce, + TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder}; + +#ifndef NDEBUG + static const char *getReasonStr(GenericSchedulerBase::CandReason Reason); +#endif + + /// Policy for scheduling the next instruction in the candidate's zone. + struct CandPolicy { + bool ReduceLatency; + unsigned ReduceResIdx; + unsigned DemandResIdx; + + CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {} + }; + + /// Status of an instruction's critical resource consumption. + struct SchedResourceDelta { + // Count critical resources in the scheduled region required by SU. + unsigned CritResources; + + // Count critical resources from another region consumed by SU. + unsigned DemandedResources; + + SchedResourceDelta(): CritResources(0), DemandedResources(0) {} + + bool operator==(const SchedResourceDelta &RHS) const { + return CritResources == RHS.CritResources + && DemandedResources == RHS.DemandedResources; + } + bool operator!=(const SchedResourceDelta &RHS) const { + return !operator==(RHS); + } + }; + + /// Store the state used by GenericScheduler heuristics, required for the + /// lifetime of one invocation of pickNode(). + struct SchedCandidate { + CandPolicy Policy; + + // The best SUnit candidate. + SUnit *SU; + + // The reason for this candidate. + CandReason Reason; + + // Set of reasons that apply to multiple candidates. + uint32_t RepeatReasonSet; + + // Register pressure values for the best candidate. + RegPressureDelta RPDelta; + + // Critical resource consumption of the best candidate. + SchedResourceDelta ResDelta; + + SchedCandidate(const CandPolicy &policy) + : Policy(policy), SU(nullptr), Reason(NoCand), RepeatReasonSet(0) {} + + bool isValid() const { return SU; } + + // Copy the status of another candidate without changing policy. + void setBest(SchedCandidate &Best) { + assert(Best.Reason != NoCand && "uninitialized Sched candidate"); + SU = Best.SU; + Reason = Best.Reason; + RPDelta = Best.RPDelta; + ResDelta = Best.ResDelta; + } + + bool isRepeat(CandReason R) { return RepeatReasonSet & (1 << R); } + void setRepeat(CandReason R) { RepeatReasonSet |= (1 << R); } + + void initResourceDelta(const ScheduleDAGMI *DAG, + const TargetSchedModel *SchedModel); + }; + +protected: + const MachineSchedContext *Context; + const TargetSchedModel *SchedModel; + const TargetRegisterInfo *TRI; + + SchedRemainder Rem; +protected: + GenericSchedulerBase(const MachineSchedContext *C): + Context(C), SchedModel(nullptr), TRI(nullptr) {} + + void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, + SchedBoundary *OtherZone); + +#ifndef NDEBUG + void traceCandidate(const SchedCandidate &Cand); +#endif +}; + +/// GenericScheduler shrinks the unscheduled zone using heuristics to balance +/// the schedule. +class GenericScheduler : public GenericSchedulerBase { + ScheduleDAGMILive *DAG; + + // State of the top and bottom scheduled instruction boundaries. + SchedBoundary Top; + SchedBoundary Bot; + + MachineSchedPolicy RegionPolicy; +public: + GenericScheduler(const MachineSchedContext *C): + GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"), + Bot(SchedBoundary::BotQID, "BotQ") {} + + void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) override; + + bool shouldTrackPressure() const override { + return RegionPolicy.ShouldTrackPressure; + } + + void initialize(ScheduleDAGMI *dag) override; + + SUnit *pickNode(bool &IsTopNode) override; + + void schedNode(SUnit *SU, bool IsTopNode) override; + + void releaseTopNode(SUnit *SU) override { + Top.releaseTopNode(SU); + } + + void releaseBottomNode(SUnit *SU) override { + Bot.releaseBottomNode(SU); + } + + void registerRoots() override; + +protected: + void checkAcyclicLatency(); + + void tryCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary &Zone, + const RegPressureTracker &RPTracker, + RegPressureTracker &TempTracker); + + SUnit *pickNodeBidirectional(bool &IsTopNode); + + void pickNodeFromQueue(SchedBoundary &Zone, + const RegPressureTracker &RPTracker, + SchedCandidate &Candidate); + + void reschedulePhysRegCopies(SUnit *SU, bool isTop); +}; + +/// PostGenericScheduler - Interface to the scheduling algorithm used by +/// ScheduleDAGMI. +/// +/// Callbacks from ScheduleDAGMI: +/// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ... +class PostGenericScheduler : public GenericSchedulerBase { + ScheduleDAGMI *DAG; + SchedBoundary Top; + SmallVector BotRoots; +public: + PostGenericScheduler(const MachineSchedContext *C): + GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {} + + virtual ~PostGenericScheduler() {} + + void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) override { + /* no configurable policy */ + }; + + /// PostRA scheduling does not track pressure. + bool shouldTrackPressure() const override { return false; } + + void initialize(ScheduleDAGMI *Dag) override; + + void registerRoots() override; + + SUnit *pickNode(bool &IsTopNode) override; + + void scheduleTree(unsigned SubtreeID) override { + llvm_unreachable("PostRA scheduler does not support subtree analysis."); + } + + void schedNode(SUnit *SU, bool IsTopNode) override; + + void releaseTopNode(SUnit *SU) override { + Top.releaseTopNode(SU); + } + + // Only called for roots. + void releaseBottomNode(SUnit *SU) override { + BotRoots.push_back(SU); + } + +protected: + void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand); + + void pickNodeFromQueue(SchedCandidate &Cand); +}; + } // namespace llvm #endif diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 35210f1..17477fe 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -588,6 +588,25 @@ namespace llvm { /// the intrinsic for later emission to the StackMap. extern char &StackMapLivenessID; + /// createJumpInstrTables - This pass creates jump-instruction tables. + ModulePass *createJumpInstrTablesPass(); } // End llvm namespace +/// This initializer registers TargetMachine constructor, so the pass being +/// initialized can use target dependent interfaces. Please do not move this +/// macro to be together with INITIALIZE_PASS, which is a complete target +/// independent initializer, and we don't want to make libScalarOpts depend +/// on libCodeGen. +#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \ + PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + #endif diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index c11a6ac..cc9e000 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -434,10 +434,8 @@ protected: void bumpDownwardPressure(const MachineInstr *MI); }; -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dumpRegSetPressure(ArrayRef SetPressure, const TargetRegisterInfo *TRI); -#endif } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h index 73ce99f..b2108ad 100644 --- a/include/llvm/CodeGen/ScheduleDFS.h +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -57,11 +57,9 @@ struct ILPValue { return RHS <= *this; } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void print(raw_ostream &OS) const; void dump() const; -#endif }; /// \brief Compute the values of each DAG node for various metrics during DFS. diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index d9c38c0..5effb82 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -151,8 +151,7 @@ public: }; class SelectionDAG; -void checkForCycles(const SDNode *N); -void checkForCycles(const SelectionDAG *DAG); +void checkForCycles(const SelectionDAG *DAG, bool force = false); /// SelectionDAG class - This is used to represent a portion of an LLVM function /// in a low-level Data Dependence DAG representation suitable for instruction @@ -335,7 +334,7 @@ public: assert((!N.getNode() || N.getValueType() == MVT::Other) && "DAG root value is not a chain!"); if (N.getNode()) - checkForCycles(N.getNode()); + checkForCycles(N.getNode(), this); Root = N; if (N.getNode()) checkForCycles(this); @@ -540,6 +539,12 @@ public: /// undefined. SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, const int *MaskElts); + SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, + ArrayRef MaskElts) { + assert(VT.getVectorNumElements() == MaskElts.size() && + "Must have the same number of vector elements as mask elements!"); + return getVectorShuffle(VT, dl, N1, N2, MaskElts.data()); + } /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by either any-extending or truncating it. @@ -557,10 +562,28 @@ public: /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy); + /// getAnyExtendVectorInReg - Return an operation which will any-extend the + /// low lanes of the operand into the specified vector type. For example, + /// this can convert a v16i8 into a v4i32 by any-extending the low four + /// lanes of the operand from i8 to i32. + SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); + + /// getSignExtendVectorInReg - Return an operation which will sign extend the + /// low lanes of the operand into the specified vector type. For example, + /// this can convert a v16i8 into a v4i32 by sign extending the low four + /// lanes of the operand from i8 to i32. + SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); + + /// getZeroExtendVectorInReg - Return an operation which will zero extend the + /// low lanes of the operand into the specified vector type. For example, + /// this can convert a v16i8 into a v4i32 by zero extending the low four + /// lanes of the operand from i8 to i32. + SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); + /// getBoolExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by using an extension appropriate for the target's - /// BooleanContent or truncating it. - SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT); + /// BooleanContent for type OpVT or truncating it. + SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT); /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). SDValue getNOT(SDLoc DL, SDValue Val, EVT VT); @@ -607,14 +630,14 @@ public: /// SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - SDValue N1, SDValue N2, SDValue N3, SDValue N4, - SDValue N5); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + bool nuw = false, bool nsw = false, bool exact = false); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + SDValue N3); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + SDValue N3, SDValue N4, SDValue N5); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef Ops); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef Ops); @@ -695,20 +718,22 @@ public: SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue SV, unsigned Align); - /// getAtomic - Gets a node for an atomic op, produces result and chain and - /// takes 3 operands - SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Cmp, SDValue Swp, - MachinePointerInfo PtrInfo, unsigned Alignment, - AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, - SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Cmp, SDValue Swp, - MachineMemOperand *MMO, - AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, - SynchronizationScope SynchScope); + /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two + /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces a the value loaded and a + /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, + /// a success flag (initially i1), and a chain. + SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, + SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, + MachinePointerInfo PtrInfo, unsigned Alignment, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope); + SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, + SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope); /// getAtomic - Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. @@ -922,7 +947,9 @@ public: /// getNodeIfExists - Get the specified node if it's already available, or /// else return NULL. - SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef Ops); + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef Ops, + bool nuw = false, bool nsw = false, + bool exact = false); /// getDbgValue - Creates a SDDbgValue node. /// @@ -1179,6 +1206,10 @@ private: void allnodes_clear(); + BinarySDNode *GetBinarySDNode(unsigned Opcode, SDLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, bool nuw, bool nsw, + bool exact); + /// VTList - List of non-single value types. FoldingSet VTListMap; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 4f0ddb7..2231511 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -20,6 +20,7 @@ #define LLVM_CODEGEN_SELECTIONDAGNODES_H #include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" @@ -49,7 +50,26 @@ template struct DenseMapInfo; template struct simplify_type; template struct ilist_traits; -void checkForCycles(const SDNode *N); +/// isBinOpWithFlags - Returns true if the opcode is a binary operation +/// with flags. +static bool isBinOpWithFlags(unsigned Opcode) { + switch (Opcode) { + case ISD::SDIV: + case ISD::UDIV: + case ISD::SRA: + case ISD::SRL: + case ISD::MUL: + case ISD::ADD: + case ISD::SUB: + case ISD::SHL: + return true; + default: + return false; + } +} + +void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, + bool force = false); /// SDVTList - This represents a list of ValueType's that has been intern'd by /// a SelectionDAG. Instances of this simple value class are returned by @@ -123,6 +143,9 @@ public: bool operator<(const SDValue &O) const { return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); } + LLVM_EXPLICIT operator bool() const { + return Node != nullptr; + } SDValue getValue(unsigned R) const { return SDValue(Node, R); @@ -574,6 +597,7 @@ public: typedef SDUse* op_iterator; op_iterator op_begin() const { return OperandList; } op_iterator op_end() const { return OperandList+NumOperands; } + ArrayRef ops() const { return makeArrayRef(op_begin(), op_end()); } SDVTList getVTList() const { SDVTList X = { ValueList, NumValues }; @@ -938,6 +962,36 @@ public: } }; +/// BinaryWithFlagsSDNode - This class is an extension of BinarySDNode +/// used from those opcodes that have associated extra flags. +class BinaryWithFlagsSDNode : public BinarySDNode { + enum { NUW = (1 << 0), NSW = (1 << 1), EXACT = (1 << 2) }; + +public: + BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y) + : BinarySDNode(Opc, Order, dl, VTs, X, Y) {} + /// getRawSubclassData - Return the SubclassData value, which contains an + /// encoding of the flags. + /// This function should be used to add subclass data to the NodeID value. + unsigned getRawSubclassData() const { return SubclassData; } + void setHasNoUnsignedWrap(bool b) { + SubclassData = (SubclassData & ~NUW) | (b ? NUW : 0); + } + void setHasNoSignedWrap(bool b) { + SubclassData = (SubclassData & ~NSW) | (b ? NSW : 0); + } + void setIsExact(bool b) { + SubclassData = (SubclassData & ~EXACT) | (b ? EXACT : 0); + } + bool hasNoUnsignedWrap() const { return SubclassData & NUW; } + bool hasNoSignedWrap() const { return SubclassData & NSW; } + bool isExact() const { return SubclassData & EXACT; } + static bool classof(const SDNode *N) { + return isBinOpWithFlags(N->getOpcode()); + } +}; + /// TernarySDNode - This class is used for three-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class TernarySDNode : public SDNode { @@ -1077,6 +1131,7 @@ public: N->getOpcode() == ISD::STORE || N->getOpcode() == ISD::PREFETCH || N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || N->getOpcode() == ISD::ATOMIC_SWAP || N->getOpcode() == ISD::ATOMIC_LOAD_ADD || N->getOpcode() == ISD::ATOMIC_LOAD_SUB || @@ -1185,12 +1240,13 @@ public: bool isCompareAndSwap() const { unsigned Op = getOpcode(); - return Op == ISD::ATOMIC_CMP_SWAP; + return Op == ISD::ATOMIC_CMP_SWAP || Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS; } // Methods to support isa and dyn_cast static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || N->getOpcode() == ISD::ATOMIC_SWAP || N->getOpcode() == ISD::ATOMIC_LOAD_ADD || N->getOpcode() == ISD::ATOMIC_LOAD_SUB || @@ -1528,11 +1584,27 @@ public: unsigned MinSplatBits = 0, bool isBigEndian = false) const; - /// getConstantSplatValue - Check if this is a constant splat, and if so, - /// return the splat value only if it is a ConstantSDNode. Otherwise - /// return nullptr. This is a simpler form of isConstantSplat. - /// Get the constant splat only if you care about the splat value. - ConstantSDNode *getConstantSplatValue() const; + /// \brief Returns the splatted value or a null value if this is not a splat. + /// + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + SDValue getSplatValue(BitVector *UndefElements = nullptr) const; + + /// \brief Returns the splatted constant or null if this is not a constant + /// splat. + /// + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantSDNode * + getConstantSplatNode(BitVector *UndefElements = nullptr) const; + + /// \brief Returns the splatted constant FP or null if this is not a constant + /// FP splat. + /// + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantFPSDNode * + getConstantFPSplatNode(BitVector *UndefElements = nullptr) const; bool isConstant() const; diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h index 6ba7256..6f07546 100644 --- a/include/llvm/CodeGen/StackMapLivenessAnalysis.h +++ b/include/llvm/CodeGen/StackMapLivenessAnalysis.h @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// // // This pass calculates the liveness for each basic block in a function and -// attaches the register live-out information to a stackmap or patchpoint -// intrinsic if present. +// attaches the register live-out information to a patchpoint intrinsic (if +// present). // //===----------------------------------------------------------------------===// @@ -23,14 +23,13 @@ namespace llvm { /// \brief This pass calculates the liveness information for each basic block in -/// a function and attaches the register live-out information to a stackmap or -/// patchpoint intrinsic if present. +/// a function and attaches the register live-out information to a patchpoint +/// intrinsic if present. /// -/// This is an optional pass that has to be explicitly enabled via the -/// -enable-stackmap-liveness and/or -enable-patchpoint-liveness flag. The pass -/// skips functions that don't have any stackmap or patchpoint intrinsics. The +/// This pass can be disabled via the -enable-patchpoint-liveness=false flag. +/// The pass skips functions that don't have any patchpoint intrinsics. The /// information provided by this pass is optional and not required by the -/// aformentioned intrinsics to function. +/// aformentioned intrinsic to function. class StackMapLiveness : public MachineFunctionPass { MachineFunction *MF; const TargetRegisterInfo *TRI; diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 9f1cbaa..230d1ed 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -68,11 +68,9 @@ public: void InitializeELF(bool UseInitArray_); const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym, - const MCSection *KeySec) const override; + const MCSymbol *KeySym) const override; const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym, - const MCSection *KeySec) const override; + const MCSymbol *KeySym) const override; }; @@ -144,11 +142,9 @@ public: Mangler &Mang, const TargetMachine &TM) const override; const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym, - const MCSection *KeySec) const override; + const MCSymbol *KeySym) const override; const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym, - const MCSection *KeySec) const override; + const MCSymbol *KeySym) const override; }; } // end namespace llvm diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index ea1e75a..e9f6702 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -3,20 +3,14 @@ #ifndef CONFIG_H #define CONFIG_H -/* Bug report URL. */ -#define BUG_REPORT_URL "${BUG_REPORT_URL}" - -/* Define if we have libxml2 */ -#cmakedefine CLANG_HAVE_LIBXML ${CLANG_HAVE_LIBXML} - -/* Relative directory for resource files */ -#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" +/* Exported configuration */ +#include "llvm/Config/llvm-config.h" -/* Directories clang will search for headers */ -#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}" +/* Patch version of the LLVM API */ +#cmakedefine LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} -/* Default to all compiler invocations for --sysroot=. */ -#undef DEFAULT_SYSROOT +/* Bug report URL. */ +#define BUG_REPORT_URL "${BUG_REPORT_URL}" /* Define if you want backtraces on crash */ #cmakedefine ENABLE_BACKTRACES @@ -30,9 +24,6 @@ /* Define if timestamp information (e.g., __DATE__) is allowed */ #cmakedefine ENABLE_TIMESTAMPS ${ENABLE_TIMESTAMPS} -/* Directory where gcc is installed. */ -#undef GCC_INSTALL_PREFIX - /* Define to 1 if you have the `arc4random' function. */ #cmakedefine HAVE_ARC4RANDOM @@ -45,9 +36,6 @@ /* Define to 1 if you have the `ceilf' function. */ #cmakedefine HAVE_CEILF ${HAVE_CEILF} -/* Define if the neat program is available */ -#cmakedefine HAVE_CIRCO ${HAVE_CIRCO} - /* Define to 1 if you have the `closedir' function. */ #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} @@ -80,12 +68,6 @@ /* Define if dlopen() is available on this platform. */ #cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} -/* Define if the dot program is available */ -#cmakedefine HAVE_DOT ${HAVE_DOT} - -/* Define if the dotty program is available */ -#cmakedefine HAVE_DOTTY ${HAVE_DOTTY} - /* Define if you have the _dyld_func_lookup function. */ #undef HAVE_DYLD @@ -98,9 +80,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} -/* Define if the neat program is available */ -#cmakedefine HAVE_FDP ${HAVE_FDP} - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FENV_H ${HAVE_FENV_H} @@ -161,12 +140,6 @@ /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} -/* Define if the Graphviz program is available */ -#cmakedefine HAVE_GRAPHVIZ ${HAVE_GRAPHVIZ} - -/* Define if the gv program is available */ -#cmakedefine HAVE_GV ${HAVE_GV} - /* Define to 1 if the system has the type `int64_t'. */ #cmakedefine HAVE_INT64_T ${HAVE_INT64_T} @@ -271,9 +244,6 @@ /* Define to 1 if you have the `nearbyintf' function. */ #cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF} -/* Define if the neat program is available */ -#cmakedefine HAVE_NEATO ${HAVE_NEATO} - /* Define to 1 if you have the `opendir' function. */ #cmakedefine HAVE_OPENDIR ${HAVE_OPENDIR} @@ -417,9 +387,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} -/* Define if the neat program is available */ -#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} - /* Define to 1 if the system has the type `uint64_t'. */ #cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} @@ -438,9 +405,6 @@ /* Define to 1 if you have the `writev' function. */ #cmakedefine HAVE_WRITEV ${HAVE_WRITEV} -/* Define if the xdot.py program is available */ -#cmakedefine HAVE_XDOT ${HAVE_XDOT} - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} @@ -501,114 +465,9 @@ /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS -/* Installation directory for binary executables */ -#cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" - -/* Time at which LLVM was configured */ -#cmakedefine LLVM_CONFIGTIME "${LLVM_CONFIGTIME}" - -/* Installation directory for data files */ -#cmakedefine LLVM_DATADIR "${LLVM_DATADIR}" - -/* Target triple LLVM will generate code for by default */ -#cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" - -/* Installation directory for documentation */ -#cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" - -/* Define if threads enabled */ -#cmakedefine01 LLVM_ENABLE_THREADS - /* Define if zlib compression is available */ #cmakedefine01 LLVM_ENABLE_ZLIB -/* Installation directory for config files */ -#cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}" - -/* Has gcc/MSVC atomic intrinsics */ -#cmakedefine01 LLVM_HAS_ATOMICS - -/* Host triple LLVM will be executed on */ -#cmakedefine LLVM_HOST_TRIPLE "${LLVM_HOST_TRIPLE}" - -/* Installation directory for include files */ -#cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}" - -/* Installation directory for .info files */ -#cmakedefine LLVM_INFODIR "${LLVM_INFODIR}" - -/* Installation directory for man pages */ -#cmakedefine LLVM_MANDIR "${LLVM_MANDIR}" - -/* LLVM architecture name for the native architecture, if available */ -#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} - -/* LLVM name for the native AsmParser init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser - -/* LLVM name for the native AsmPrinter init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter - -/* LLVM name for the native Disassembler init function, if available */ -#cmakedefine LLVM_NATIVE_DISASSEMBLER LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler - -/* LLVM name for the native Target init function, if available */ -#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target - -/* LLVM name for the native TargetInfo init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo - -/* LLVM name for the native target MC init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC - -/* Define if this is Unixish platform */ -#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} - -/* Define if this is Win32ish platform */ -#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} - -/* Define to path to circo program if found or 'echo circo' otherwise */ -#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}" - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" - -/* Define to path to xdot.py program if found or 'echo xdot' otherwise */ -#cmakedefine LLVM_PATH_XDOT "${LLVM_PATH_XDOT}" - -/* Installation prefix directory */ -#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" - -/* Define if we have the Intel JIT API runtime support library */ -#cmakedefine LLVM_USE_INTEL_JITEVENTS 1 - -/* Define if we have the oprofile JIT-support library */ -#cmakedefine LLVM_USE_OPROFILE 1 - -/* Major version of the LLVM API */ -#cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} - -/* Minor version of the LLVM API */ -#cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} - /* Define if the OS needs help to load dependent libraries for dlopen(). */ #cmakedefine LTDL_DLOPEN_DEPLIBS ${LTDL_DLOPEN_DEPLIBS} @@ -689,7 +548,7 @@ /* Define to 1 if you have the `_chsize_s' function. */ #cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} -/* Added by Kevin -- Maximum path length */ +/* Maximum path length */ #cmakedefine MAXPATHLEN ${MAXPATHLEN} #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 6b8dbb7..b5f7297 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -3,20 +3,14 @@ #ifndef CONFIG_H #define CONFIG_H -/* Bug report URL. */ -#undef BUG_REPORT_URL - -/* Define if we have libxml2 */ -#undef CLANG_HAVE_LIBXML - -/* Relative directory for resource files */ -#undef CLANG_RESOURCE_DIR +/* Exported configuration */ +#include "llvm/Config/llvm-config.h" -/* Directories clang will search for headers */ -#undef C_INCLUDE_DIRS +/* Patch version of the LLVM API */ +#undef LLVM_VERSION_PATCH -/* Default to all compiler invocations for --sysroot=. */ -#undef DEFAULT_SYSROOT +/* Bug report URL. */ +#undef BUG_REPORT_URL /* Define if you want backtraces on crash */ #undef ENABLE_BACKTRACES @@ -30,18 +24,12 @@ /* Define if timestamp information (e.g., __DATE__) is allowed */ #undef ENABLE_TIMESTAMPS -/* Directory where gcc is installed. */ -#undef GCC_INSTALL_PREFIX - /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE /* Define to 1 if you have the `ceilf' function. */ #undef HAVE_CEILF -/* Define if the neat program is available */ -#undef HAVE_CIRCO - /* Define to 1 if you have the header file. */ #undef HAVE_CRASHREPORTERCLIENT_H @@ -77,12 +65,6 @@ /* Define if dlopen() is available on this platform. */ #undef HAVE_DLOPEN -/* Define if the dot program is available */ -#undef HAVE_DOT - -/* Define if the dotty program is available */ -#undef HAVE_DOTTY - /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H @@ -98,9 +80,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H -/* Define if the neat program is available */ -#undef HAVE_FDP - /* Define to 1 if you have the header file. */ #undef HAVE_FENV_H @@ -143,12 +122,6 @@ /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY -/* Define if the Graphviz program is available */ -#undef HAVE_GRAPHVIZ - -/* Define if the gv program is available */ -#undef HAVE_GV - /* Define to 1 if the system has the type `int64_t'. */ #undef HAVE_INT64_T @@ -259,9 +232,6 @@ /* Define to 1 if you have the `nearbyintf' function. */ #undef HAVE_NEARBYINTF -/* Define if the neat program is available */ -#undef HAVE_NEATO - /* Define to 1 if you have the `posix_spawn' function. */ #undef HAVE_POSIX_SPAWN @@ -402,9 +372,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H -/* Define if the neat program is available */ -#undef HAVE_TWOPI - /* Define to 1 if the system has the type `uint64_t'. */ #undef HAVE_UINT64_T @@ -423,9 +390,6 @@ /* Define to 1 if you have the `writev' function. */ #undef HAVE_WRITEV -/* Define if the xdot program is available */ -#undef HAVE_XDOT - /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H @@ -483,117 +447,9 @@ /* Linker version detected at compile time. */ #undef HOST_LINK_VERSION -/* Installation directory for binary executables */ -#undef LLVM_BINDIR - -/* Time at which LLVM was configured */ -#undef LLVM_CONFIGTIME - -/* Installation directory for data files */ -#undef LLVM_DATADIR - -/* Target triple LLVM will generate code for by default */ -#undef LLVM_DEFAULT_TARGET_TRIPLE - -/* Installation directory for documentation */ -#undef LLVM_DOCSDIR - -/* Define if threads enabled */ -#undef LLVM_ENABLE_THREADS - /* Define if zlib is enabled */ #undef LLVM_ENABLE_ZLIB -/* Installation directory for config files */ -#undef LLVM_ETCDIR - -/* Has gcc/MSVC atomic intrinsics */ -#undef LLVM_HAS_ATOMICS - -/* Host triple LLVM will be executed on */ -#undef LLVM_HOST_TRIPLE - -/* Installation directory for include files */ -#undef LLVM_INCLUDEDIR - -/* Installation directory for .info files */ -#undef LLVM_INFODIR - -/* Installation directory for man pages */ -#undef LLVM_MANDIR - -/* LLVM architecture name for the native architecture, if available */ -#undef LLVM_NATIVE_ARCH - -/* LLVM name for the native AsmParser init function, if available */ -#undef LLVM_NATIVE_ASMPARSER - -/* LLVM name for the native AsmPrinter init function, if available */ -#undef LLVM_NATIVE_ASMPRINTER - -/* LLVM name for the native Disassembler init function, if available */ -#undef LLVM_NATIVE_DISASSEMBLER - -/* LLVM name for the native Target init function, if available */ -#undef LLVM_NATIVE_TARGET - -/* LLVM name for the native TargetInfo init function, if available */ -#undef LLVM_NATIVE_TARGETINFO - -/* LLVM name for the native target MC init function, if available */ -#undef LLVM_NATIVE_TARGETMC - -/* Define if this is Unixish platform */ -#undef LLVM_ON_UNIX - -/* Define if this is Win32ish platform */ -#undef LLVM_ON_WIN32 - -/* Define to path to circo program if found or 'echo circo' otherwise */ -#undef LLVM_PATH_CIRCO - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#undef LLVM_PATH_DOT - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#undef LLVM_PATH_DOTTY - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#undef LLVM_PATH_FDP - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#undef LLVM_PATH_GRAPHVIZ - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#undef LLVM_PATH_GV - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#undef LLVM_PATH_NEATO - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#undef LLVM_PATH_TWOPI - -/* Define to path to xdot program if found or 'echo xdot' otherwise */ -#undef LLVM_PATH_XDOT - -/* Installation prefix directory */ -#undef LLVM_PREFIX - -/* Define if we have the Intel JIT API runtime support library */ -#undef LLVM_USE_INTEL_JITEVENTS - -/* Define if we have the oprofile JIT-support library */ -#undef LLVM_USE_OPROFILE - -/* Major version of the LLVM API */ -#undef LLVM_VERSION_MAJOR - -/* Minor version of the LLVM API */ -#undef LLVM_VERSION_MINOR - -/* Patch version of the LLVM API */ -#undef LLVM_VERSION_PATCH - /* The shared library extension */ #undef LTDL_SHLIB_EXT diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 65116cb..5811164 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -1,4 +1,4 @@ -/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/ /* */ /* The LLVM Compiler Infrastructure */ /* */ @@ -7,14 +7,12 @@ /* */ /*===----------------------------------------------------------------------===*/ -/* This file enumerates all of the llvm variables from configure so that - they can be in exported headers and won't override package specific - directives. This is a C file so we can include it in the llvm-c headers. */ +/* This file enumerates variables from the LLVM configuration so that they + can be in exported headers and won't override package specific directives. + This is a C header that can be included in the llvm-c headers. */ -/* To avoid multiple inclusions of these variables when we include the exported - headers and config.h, conditionally include these. */ -/* TODO: This is a bit of a hack. */ -#ifndef CONFIG_H +#ifndef LLVM_CONFIG_H +#define LLVM_CONFIG_H /* Installation directory for binary executables */ #cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" @@ -79,33 +77,6 @@ /* Define if this is Win32ish platform */ #cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} -/* Define to path to circo program if found or 'echo circo' otherwise */ -#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}" - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" - -/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ -#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT_PY}" - /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index a4fae55..5656240 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -1,4 +1,4 @@ -/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/ /* */ /* The LLVM Compiler Infrastructure */ /* */ @@ -7,14 +7,12 @@ /* */ /*===----------------------------------------------------------------------===*/ -/* This file enumerates all of the llvm variables from configure so that - they can be in exported headers and won't override package specific - directives. This is a C file so we can include it in the llvm-c headers. */ +/* This file enumerates variables from the LLVM configuration so that they + can be in exported headers and won't override package specific directives. + This is a C header that can be included in the llvm-c headers. */ -/* To avoid multiple inclusions of these variables when we include the exported - headers and config.h, conditionally include these. */ -/* TODO: This is a bit of a hack. */ -#ifndef CONFIG_H +#ifndef LLVM_CONFIG_H +#define LLVM_CONFIG_H /* Installation directory for binary executables */ #undef LLVM_BINDIR @@ -79,33 +77,6 @@ /* Define if this is Win32ish platform */ #undef LLVM_ON_WIN32 -/* Define to path to circo program if found or 'echo circo' otherwise */ -#undef LLVM_PATH_CIRCO - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#undef LLVM_PATH_DOT - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#undef LLVM_PATH_DOTTY - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#undef LLVM_PATH_FDP - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#undef LLVM_PATH_GRAPHVIZ - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#undef LLVM_PATH_GV - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#undef LLVM_PATH_NEATO - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#undef LLVM_PATH_TWOPI - -/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ -#undef LLVM_PATH_XDOT_PY - /* Installation prefix directory */ #undef LLVM_PREFIX diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 7518c1e..e5dab61 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -54,7 +54,7 @@ namespace object { } /// \brief Helper class for helping synchronize access to the global address map -/// table. +/// table. Access to this class should be serialized under a mutex. class ExecutionEngineState { public: struct AddressMapConfig : public ValueMapConfig { @@ -84,19 +84,19 @@ private: public: ExecutionEngineState(ExecutionEngine &EE); - GlobalAddressMapTy &getGlobalAddressMap(const MutexGuard &) { + GlobalAddressMapTy &getGlobalAddressMap() { return GlobalAddressMap; } std::map > & - getGlobalAddressReverseMap(const MutexGuard &) { + getGlobalAddressReverseMap() { return GlobalAddressReverseMap; } /// \brief Erase an entry from the mapping table. /// /// \returns The address that \p ToUnmap was happed to. - void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); + void *RemoveMapping(const GlobalValue *ToUnmap); }; /// \brief Abstract interface for implementation execution of LLVM modules, @@ -586,26 +586,7 @@ private: bool VerifyModules; /// InitEngine - Does the common initialization of default options. - void InitEngine() { - WhichEngine = EngineKind::Either; - ErrorStr = nullptr; - OptLevel = CodeGenOpt::Default; - MCJMM = nullptr; - JMM = nullptr; - Options = TargetOptions(); - AllocateGVsWithCode = false; - RelocModel = Reloc::Default; - CMModel = CodeModel::JITDefault; - UseMCJIT = false; - - // IR module verification is enabled by default in debug builds, and disabled - // by default in release builds. -#ifndef NDEBUG - VerifyModules = true; -#else - VerifyModules = false; -#endif - } + void InitEngine(); public: /// EngineBuilder - Constructor for EngineBuilder. If create() is called and diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h index 071a42b..6221d3b 100644 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ b/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -39,7 +39,8 @@ public: /// returns a pointer to an object that is owned by the caller. However, /// the caller does not take ownership of the underlying memory. MemoryBuffer *getMemBuffer() const { - return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), "", false); + return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), + Buffer->getBufferIdentifier(), false); } const char *getBufferStart() const { return Buffer->getBufferStart(); } diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 30c0d49..f123ffb 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -29,6 +29,8 @@ class RuntimeDyldImpl; class ObjectImage; class RuntimeDyld { + friend class RuntimeDyldChecker; + RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h new file mode 100644 index 0000000..38a4ea1 --- /dev/null +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -0,0 +1,98 @@ +//===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_RUNTIMEDYLDCHECKER_H +#define LLVM_RUNTIMEDYLDCHECKER_H + +#include "RuntimeDyld.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +class MCDisassembler; +class MCInstPrinter; + +/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has +/// correctly applied relocations. +/// +/// The RuntimeDyldChecker class evaluates expressions against an attached +/// RuntimeDyld instance to verify that relocations have been applied +/// correctly. +/// +/// The expression language supports basic pointer arithmetic and bit-masking, +/// and has limited disassembler integration for accessing instruction +/// operands and the next PC (program counter) address for each instruction. +/// +/// The language syntax is: +/// +/// check = expr '=' expr +/// +/// expr = binary_expr +/// | sliceable_expr +/// +/// sliceable_expr = '*{' number '}' load_addr_expr [slice] +/// | '(' expr ')' [slice] +/// | ident_expr [slice] +/// | number [slice] +/// +/// slice = '[' high-bit-index ':' low-bit-index ']' +/// +/// load_addr_expr = symbol +/// | '(' symbol '+' number ')' +/// | '(' symbol '-' number ')' +/// +/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' +/// | 'next_pc' '(' symbol ')' +/// | symbol +/// +/// binary_expr = expr '+' expr +/// | expr '-' expr +/// | expr '&' expr +/// | expr '|' expr +/// | expr '<<' expr +/// | expr '>>' expr +/// +class RuntimeDyldChecker { + friend class RuntimeDyldCheckerExprEval; +public: + RuntimeDyldChecker(RuntimeDyld &RTDyld, + MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, + llvm::raw_ostream &ErrStream) + : RTDyld(*RTDyld.Dyld), Disassembler(Disassembler), + InstPrinter(InstPrinter), ErrStream(ErrStream) {} + + /// \brief Check a single expression against the attached RuntimeDyld + /// instance. + bool check(StringRef CheckExpr) const; + + /// \brief Scan the given memory buffer for lines beginning with the string + /// in RulePrefix. The remainder of the line is passed to the check + /// method to be evaluated as an expression. + bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; + +private: + + bool checkSymbolIsValidForLoad(StringRef Symbol) const; + uint64_t getSymbolAddress(StringRef Symbol) const; + uint64_t readMemoryAtSymbol(StringRef Symbol, int64_t Offset, + unsigned Size) const; + StringRef getSubsectionStartingAt(StringRef Name) const; + + RuntimeDyldImpl &RTDyld; + MCDisassembler *Disassembler; + MCInstPrinter *InstPrinter; + llvm::raw_ostream &ErrStream; +}; + +} // end namespace llvm + +#endif // LLVM_RUNTIMEDYLDCHECKER_H diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index f24bb4d..1368563 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -21,7 +21,6 @@ #include "llvm/Support/Memory.h" namespace llvm { - /// This is a simple memory manager which implements the methods called by /// the RuntimeDyld class to allocate memory for section-based loading of /// objects, usually those generated by the MCJIT execution engine. @@ -93,8 +92,8 @@ private: uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size, unsigned Alignment); - error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, - unsigned Permissions); + std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, + unsigned Permissions); MemoryGroup CodeMem; MemoryGroup RWDataMem; diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 86f9cc8..e34dc83 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -75,6 +75,7 @@ public: Cold, ///< Marks function as being in a cold path. InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register + JumpTable, ///< Build jump-instruction tables and replace refs. MinSize, ///< Function must be optimized for size first Naked, ///< Naked function Nest, ///< Nested function static chain diff --git a/include/llvm/IR/AutoUpgrade.h b/include/llvm/IR/AutoUpgrade.h index 076ed4a..a4b3c41 100644 --- a/include/llvm/IR/AutoUpgrade.h +++ b/include/llvm/IR/AutoUpgrade.h @@ -14,6 +14,8 @@ #ifndef LLVM_IR_AUTOUPGRADE_H #define LLVM_IR_AUTOUPGRADE_H +#include + namespace llvm { class CallInst; class Constant; @@ -61,6 +63,9 @@ namespace llvm { /// Check the debug info version number, if it is out-dated, drop the debug /// info. Return true if module is modified. bool UpgradeDebugInfo(Module &M); + + /// Upgrade a metadata string constant in place. + void UpgradeMDStringConstant(std::string &String); } // End llvm namespace #endif diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h new file mode 100644 index 0000000..3e77a77 --- /dev/null +++ b/include/llvm/IR/Comdat.h @@ -0,0 +1,66 @@ +//===-- llvm/IR/Comdat.h - Comdat definitions -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declaration of the Comdat class, which represents a +/// single COMDAT in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_COMDAT_H +#define LLVM_IR_COMDAT_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class raw_ostream; +template class StringMapEntry; + +// This is a Name X SelectionKind pair. The reason for having this be an +// independent object instead of just adding the name and the SelectionKind +// to a GlobalObject is that it is invalid to have two Comdats with the same +// name but different SelectionKind. This structure makes that unrepresentable. +class Comdat { +public: + enum SelectionKind { + Any, ///< The linker may choose any COMDAT. + ExactMatch, ///< The data referenced by the COMDAT must be the same. + Largest, ///< The linker will choose the largest COMDAT. + NoDuplicates, ///< No other Module may specify this COMDAT. + SameSize, ///< The data referenced by the COMDAT must be the same size. + }; + + Comdat(Comdat &&C); + SelectionKind getSelectionKind() const { return SK; } + void setSelectionKind(SelectionKind Val) { SK = Val; } + StringRef getName() const; + void print(raw_ostream &OS) const; + void dump() const; + +private: + friend class Module; + Comdat(); + Comdat(SelectionKind SK, StringMapEntry *Name); + Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + + // Points to the map in Module. + StringMapEntry *Name; + SelectionKind SK; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) { + C.print(OS); + return OS; +} + +} // end llvm namespace + +#endif diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index f03e3dd..82ad9fc 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -64,6 +64,9 @@ public: /// Return true if the value is negative zero or null value. bool isZeroValue() const; + /// \brief Return true if the value is the smallest signed value. + bool isMinSignedValue() const; + /// canTrap - Return true if evaluation of this constant could trap. This is /// true for things like constant expressions that could divide by zero. bool canTrap() const; @@ -71,6 +74,9 @@ public: /// isThreadDependent - Return true if the value can vary between threads. bool isThreadDependent() const; + /// Return true if the value is dependent on a dllimport variable. + bool isDLLImportDependent() const; + /// isConstantUsed - Return true if the constant has users other than constant /// exprs and other dangling things. bool isConstantUsed() const; @@ -163,6 +169,14 @@ public: /// that want to check to see if a global is unused, but don't want to deal /// with potentially dead constants hanging off of the globals. void removeDeadConstantUsers() const; + + Constant *stripPointerCasts() { + return cast(Value::stripPointerCasts()); + } + + const Constant *stripPointerCasts() const { + return const_cast(this)->stripPointerCasts(); + } }; } // End llvm namespace diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 8b05bbb..2673504 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -108,12 +108,23 @@ namespace llvm { /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. + /// @param Kind The kind of debug information to generate. + /// @param EmitDebugInfo A boolean flag which indicates whether debug + /// information should be written to the final + /// output or not. When this is false, debug + /// information annotations will be present in + /// the IL but they are not written to the final + /// assembly or object file. This supports tracking + /// source location information in the back end + /// without actually changing the output (e.g., + /// when using optimization remarks). DICompileUnit createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName = StringRef(), - DebugEmissionKind Kind = FullDebug); + DebugEmissionKind Kind = FullDebug, + bool EmitDebugInfo = true); /// createFile - Create a file descriptor to hold debugging information /// for a file. diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 3079dec..877029f 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -414,8 +414,8 @@ public: return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize); } - /// getLargestLegalIntType - Return the size of largest legal integer type - /// size, or 0 if none are set. + /// getLargestLegalIntTypeSize - Return the size of largest legal integer + /// type size, or 0 if none are set. unsigned getLargestLegalIntTypeSize() const; /// getIndexedOffset - return the offset from the beginning of the type for diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 65e0a06..088eb9f 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -690,12 +690,17 @@ public: /// HasComplexAddr - Return true if the variable has a complex address. bool hasComplexAddress() const { return getNumAddrElements() > 0; } - unsigned getNumAddrElements() const; - - uint64_t getAddrElement(unsigned Idx) const { - return getUInt64Field(Idx + 8); + /// \brief Return the size of this variable's complex address or + /// zero if there is none. + unsigned getNumAddrElements() const { + if (DbgNode->getNumOperands() < 9) + return 0; + return getDescriptorField(8)->getNumOperands(); } + /// \brief return the Idx'th complex address element. + uint64_t getAddrElement(unsigned Idx) const; + /// isBlockByrefVariable - Return true if the variable was declared as /// a "__block" variable (Apple Blocks). bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { @@ -929,6 +934,9 @@ private: /// Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; + +DenseMap makeSubprogramMap(const Module &M); + } // end namespace llvm #endif diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 6d769d4..3d969a8 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -95,7 +95,7 @@ namespace llvm { // getFnDebugLoc - Walk up the scope chain of given debug loc and find line // number info for the function. - DebugLoc getFnDebugLoc(const LLVMContext &Ctx); + DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index e78a42b..de38d07 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -138,7 +138,6 @@ public: /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; - /// Hand rolled RTTI. static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_InlineAsm; } @@ -166,7 +165,6 @@ public: /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; - /// Hand rolled RTTI. static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_StackSize; } @@ -195,7 +193,6 @@ public: /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; - /// Hand rolled RTTI. static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_DebugMetadataVersion; } @@ -221,7 +218,6 @@ public: /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; - /// Hand rolled RTTI. static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_SampleProfile; } @@ -261,7 +257,6 @@ public: /// \see DiagnosticInfo::print. void print(DiagnosticPrinter &DP) const override; - /// Hand rolled RTTI. static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_OptimizationRemark; } @@ -323,7 +318,6 @@ public: : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemark, PassName, Fn, DLoc, Msg) {} - /// Hand rolled RTTI static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_OptimizationRemark; } @@ -350,7 +344,6 @@ public: : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkMissed, PassName, Fn, DLoc, Msg) {} - /// Hand rolled RTTI static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_OptimizationRemarkMissed; } @@ -378,7 +371,6 @@ public: : DiagnosticInfoOptimizationRemarkBase(DK_OptimizationRemarkAnalysis, PassName, Fn, DLoc, Msg) {} - /// Hand rolled RTTI static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_OptimizationRemarkAnalysis; } diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index 3648202..e2d1ccc 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -97,10 +97,6 @@ public: bool dominates(const BasicBlockEdge &BBE, const Use &U) const; bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const; - inline DomTreeNode *operator[](BasicBlock *BB) const { - return getNode(BB); - } - // Ensure base class overloads are visible. using Base::isReachableFromEntry; diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index dbe52bc..a1216a1 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -18,10 +18,9 @@ #ifndef LLVM_IR_GVMATERIALIZER_H #define LLVM_IR_GVMATERIALIZER_H -#include "llvm/Support/system_error.h" +#include namespace llvm { - class Function; class GlobalValue; class Module; @@ -43,7 +42,7 @@ public: /// Make sure the given GlobalValue is fully read. /// - virtual error_code Materialize(GlobalValue *GV) = 0; + virtual std::error_code Materialize(GlobalValue *GV) = 0; /// If the given GlobalValue is read in, and if the GVMaterializer supports /// it, release the memory for the GV, and set it up to be materialized @@ -54,7 +53,9 @@ public: /// Make sure the entire Module has been completely read. /// - virtual error_code MaterializeModule(Module *M) = 0; + virtual std::error_code MaterializeModule(Module *M) = 0; + + virtual void releaseBuffer() = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index d9f0b4a..075b570 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -34,7 +34,7 @@ class GlobalAlias : public GlobalValue, public ilist_node { void setParent(Module *parent); GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, GlobalObject *Aliasee, Module *Parent); + const Twine &Name, Constant *Aliasee, Module *Parent); public: // allocate space for exactly one operand @@ -46,7 +46,7 @@ public: /// the end of the specified module's alias list. static GlobalAlias *create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee, Module *Parent); + Constant *Aliasee, Module *Parent); // Without the Aliasee. static GlobalAlias *create(Type *Ty, unsigned AddressSpace, @@ -56,14 +56,14 @@ public: // The module is taken from the Aliasee. static GlobalAlias *create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee); + GlobalValue *Aliasee); // Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee); + GlobalValue *Aliasee); // Linkage, Type, Parent and AddressSpace taken from the Aliasee. - static GlobalAlias *create(const Twine &Name, GlobalObject *Aliasee); + static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -78,14 +78,28 @@ public: /// void eraseFromParent() override; - /// set/getAliasee - These methods retrive and set alias target. - void setAliasee(GlobalObject *GO); - const GlobalObject *getAliasee() const { + /// These methods retrive and set alias target. + void setAliasee(Constant *Aliasee); + const Constant *getAliasee() const { return const_cast(this)->getAliasee(); } + Constant *getAliasee() { + return getOperand(0); + } - GlobalObject *getAliasee() { - return cast_or_null(getOperand(0)); + const GlobalObject *getBaseObject() const { + return const_cast(this)->getBaseObject(); + } + GlobalObject *getBaseObject() { + return dyn_cast(getAliasee()->stripInBoundsOffsets()); + } + + const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const { + return const_cast(this)->getBaseObject(DL, Offset); + } + GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) { + return dyn_cast( + getAliasee()->stripAndAccumulateInBoundsConstantOffsets(DL, Offset)); } static bool isValidLinkage(LinkageTypes L) { diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 3bc8b85..2e042f4 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -20,7 +20,7 @@ #include "llvm/IR/GlobalValue.h" namespace llvm { - +class Comdat; class Module; class GlobalObject : public GlobalValue { @@ -29,21 +29,27 @@ class GlobalObject : public GlobalValue { protected: GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) - : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name) { + : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) { setGlobalValueSubClassData(0); } std::string Section; // Section to emit this into, empty means default + Comdat *ObjComdat; public: unsigned getAlignment() const { return (1u << getGlobalValueSubClassData()) >> 1; } void setAlignment(unsigned Align); - bool hasSection() const { return !getSection().empty(); } - const std::string &getSection() const { return Section; } + bool hasSection() const { return !StringRef(getSection()).empty(); } + const char *getSection() const { return Section.c_str(); } void setSection(StringRef S); + bool hasComdat() const { return getComdat() != nullptr; } + const Comdat *getComdat() const { return ObjComdat; } + Comdat *getComdat() { return ObjComdat; } + void setComdat(Comdat *C) { ObjComdat = C; } + void copyAttributesFrom(const GlobalValue *Src) override; // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 10df372..68e410b 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -23,6 +23,7 @@ namespace llvm { +class Comdat; class PointerType; class Module; @@ -63,7 +64,8 @@ protected: LinkageTypes Linkage, const Twine &Name) : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), - DllStorageClass(DefaultStorageClass), Parent(nullptr) { + DllStorageClass(DefaultStorageClass), + ThreadLocal(NotThreadLocal), Parent(nullptr) { setName(Name); } @@ -74,21 +76,32 @@ protected: unsigned UnnamedAddr : 1; // This value's address is not significant unsigned DllStorageClass : 2; // DLL storage class + unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is + // the desired model? + private: // Give subclasses access to what otherwise would be wasted padding. - // (22 + 2 + 1 + 2 + 5) == 32. - unsigned SubClassData : 22; + // (19 + 3 + 2 + 1 + 2 + 5) == 32. + unsigned SubClassData : 19; protected: unsigned getGlobalValueSubClassData() const { return SubClassData; } void setGlobalValueSubClassData(unsigned V) { - assert(V < (1 << 22) && "It will not fit"); + assert(V < (1 << 19) && "It will not fit"); SubClassData = V; } Module *Parent; // The containing module. public: + enum ThreadLocalMode { + NotThreadLocal = 0, + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + ~GlobalValue() { removeDeadConstantUsers(); // remove any dead constants using this. } @@ -98,6 +111,12 @@ public: bool hasUnnamedAddr() const { return UnnamedAddr; } void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + bool hasComdat() const { return getComdat() != nullptr; } + Comdat *getComdat(); + const Comdat *getComdat() const { + return const_cast(this)->getComdat(); + } + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } @@ -110,6 +129,19 @@ public: Visibility = V; } + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } + void setThreadLocal(bool Val) { + setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); + } + void setThreadLocalMode(ThreadLocalMode Val) { + assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); + ThreadLocal = Val; + } + ThreadLocalMode getThreadLocalMode() const { + return static_cast(ThreadLocal); + } + DLLStorageClassTypes getDLLStorageClass() const { return DLLStorageClassTypes(DllStorageClass); } @@ -121,8 +153,14 @@ public: } void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } - bool hasSection() const { return !getSection().empty(); } - const std::string &getSection() const; + bool hasSection() const { return !StringRef(getSection()).empty(); } + // It is unfortunate that we have to use "char *" in here since this is + // always non NULL, but: + // * The C API expects a null terminated string, so we cannot use StringRef. + // * The C API expects us to own it, so we cannot use a std:string. + // * For GlobalAliases we can fail to find the section and we have to + // return "", so we cannot use a "const std::string &". + const char *getSection() const; /// Global values are always pointers. inline PointerType *getType() const { @@ -142,6 +180,9 @@ public: static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { return Linkage == AvailableExternallyLinkage; } + static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceODRLinkage; + } static bool isLinkOnceLinkage(LinkageTypes Linkage) { return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; } diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 8cd4332..4189ccb 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -41,9 +41,6 @@ class GlobalVariable : public GlobalObject, public ilist_node { void setParent(Module *parent); bool isConstantGlobal : 1; // Is this a global constant? - unsigned threadLocalMode : 3; // Is this symbol "Thread Local", - // if so, what is the desired - // model? bool isExternallyInitializedConstant : 1; // Is this a global whose value // can change from its initial // value before global @@ -55,14 +52,6 @@ public: return User::operator new(s, 1); } - enum ThreadLocalMode { - NotThreadLocal = 0, - GeneralDynamicTLSModel, - LocalDynamicTLSModel, - InitialExecTLSModel, - LocalExecTLSModel - }; - /// GlobalVariable ctor - If a parent module is specified, the global is /// automatically inserted into the end of the specified modules global list. GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, @@ -155,16 +144,6 @@ public: bool isConstant() const { return isConstantGlobal; } void setConstant(bool Val) { isConstantGlobal = Val; } - /// If the value is "Thread Local", its value isn't shared by the threads. - bool isThreadLocal() const { return threadLocalMode != NotThreadLocal; } - void setThreadLocal(bool Val) { - threadLocalMode = Val ? GeneralDynamicTLSModel : NotThreadLocal; - } - void setThreadLocalMode(ThreadLocalMode Val) { threadLocalMode = Val; } - ThreadLocalMode getThreadLocalMode() const { - return static_cast(threadLocalMode); - } - bool isExternallyInitialized() const { return isExternallyInitializedConstant; } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 580d333..00d3684 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -327,6 +327,11 @@ public: return Type::getIntNTy(Context, N); } + /// \brief Fetch the type representing a 16-bit floating point value. + Type *getHalfTy() { + return Type::getHalfTy(Context); + } + /// \brief Fetch the type representing a 32-bit floating point value. Type *getFloatTy() { return Type::getFloatTy(Context); @@ -1464,6 +1469,30 @@ public: Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); } + + /// \brief Return a value that has been extracted from a larger integer type. + Value *CreateExtractInteger(const DataLayout &DL, Value *From, + IntegerType *ExtractedTy, uint64_t Offset, + const Twine &Name) { + IntegerType *IntTy = cast(From->getType()); + assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= + DL.getTypeStoreSize(IntTy) && + "Element extends past full value"); + uint64_t ShAmt = 8 * Offset; + Value *V = From; + if (DL.isBigEndian()) + ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - + DL.getTypeStoreSize(ExtractedTy) - Offset); + if (ShAmt) { + V = CreateLShr(V, ShAmt, Name + ".shift"); + } + assert(ExtractedTy->getBitWidth() <= IntTy->getBitWidth() && + "Cannot extract to a larger integer!"); + if (ExtractedTy != IntTy) { + V = CreateTrunc(V, ExtractedTy, Name + ".trunc"); + } + return V; + } }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 7d338a6..a590f5a 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -500,6 +500,16 @@ public: (unsigned)V); } + /// Return true if this cmpxchg may spuriously fail. + bool isWeak() const { + return getSubclassDataFromInstruction() & 0x100; + } + + void setWeak(bool IsWeak) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~0x100) | + (IsWeak << 8)); + } + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2311,12 +2321,14 @@ public: (V ? 1 : 0)); } - /// addClause - Add a catch or filter clause to the landing pad. - void addClause(Value *ClauseVal); + /// Add a catch or filter clause to the landing pad. + void addClause(Constant *ClauseVal); - /// getClause - Get the value of the clause at index Idx. Use isCatch/isFilter - /// to determine what type of clause this is. - Value *getClause(unsigned Idx) const { return OperandList[Idx + 1]; } + /// Get the value of the clause at index Idx. Use isCatch/isFilter to + /// determine what type of clause this is. + Constant *getClause(unsigned Idx) const { + return cast(OperandList[Idx + 1]); + } /// isCatch - Return 'true' if the clause and index Idx is a catch clause. bool isCatch(unsigned Idx) const { @@ -2649,6 +2661,9 @@ public: assert(RHS.SI == SI && "Incompatible operators."); return RHS.Index != Index; } + Self &operator*() { + return *this; + } }; typedef CaseIteratorT @@ -2729,6 +2744,17 @@ public: ConstCaseIt case_end() const { return ConstCaseIt(this, getNumCases()); } + + /// cases - iteration adapter for range-for loops. + iterator_range cases() { + return iterator_range(case_begin(), case_end()); + } + + /// cases - iteration adapter for range-for loops. + iterator_range cases() const { + return iterator_range(case_begin(), case_end()); + } + /// Returns an iterator that points to the default case. /// Note: this iterator allows to resolve successor only. Attempt /// to resolve case value causes an assertion. diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 839bbbd..b0d746b 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -71,6 +71,9 @@ namespace Intrinsic { /// Map a GCC builtin name to an intrinsic ID. ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + + /// Map a MS builtin name to an intrinsic ID. + ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); /// IITDescriptor - This is a type descriptor which explains the type /// requirements of an intrinsic. This is returned by diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index edd1621..ae2a90c 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -226,6 +226,10 @@ class GCCBuiltin { string GCCBuiltinName = name; } +class MSBuiltin { + string MSBuiltinName = name; +} + //===--------------- Variable Argument Handling Intrinsics ----------------===// // diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index 23757aa..e3c0fb3 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -31,6 +31,13 @@ def int_aarch64_sdiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_aarch64_udiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// RBIT + +def int_aarch64_rbit : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], + [IntrNoMem]>; + } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index d19d7b8..a02d707 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -54,8 +54,12 @@ def int_arm_ldaexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; //===----------------------------------------------------------------------===// // Data barrier instructions -def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; -def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, MSBuiltin<"__dmb">, + Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, MSBuiltin<"__dsb">, + Intrinsic<[], [llvm_i32_ty]>; +def int_arm_isb : GCCBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">, + Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // VFP @@ -74,17 +78,21 @@ def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], // Move to coprocessor def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, + MSBuiltin<"_MoveToCoprocessor">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, + MSBuiltin<"_MoveToCoprocessor2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; // Move from coprocessor def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, + MSBuiltin<"_MoveFromCoprocessor">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, + MSBuiltin<"_MoveFromCoprocessor2">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; @@ -126,6 +134,11 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// +// RBIT + +def int_arm_rbit : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// // UND (reserved undefined sequence) def int_arm_undefined : Intrinsic<[], [llvm_i32_ty]>; diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index 26dc70a..6baf018 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -796,26 +796,25 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType; // (space)i64* // Generated within nvvm. Use for ldu on sm_20 or later -// @TODO: Revisit this, Changed LLVMAnyPointerType to LLVMPointerType def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.i">; def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.f">; def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.p">; // Generated within nvvm. Use for ldg on sm_35 or later def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.i">; def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.f">; def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.p">; // Use for generic pointers @@ -889,6 +888,157 @@ def int_nvvm_compiler_error : def int_nvvm_compiler_warn : Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.warn">; +def int_nvvm_reflect : + Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.reflect">; + +// isspacep.{const, global, local, shared} +def int_nvvm_isspacep_const + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.const">, + GCCBuiltin<"__nvvm_isspacep_const">; +def int_nvvm_isspacep_global + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.global">, + GCCBuiltin<"__nvvm_isspacep_global">; +def int_nvvm_isspacep_local + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.local">, + GCCBuiltin<"__nvvm_isspacep_local">; +def int_nvvm_isspacep_shared + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.shared">, + GCCBuiltin<"__nvvm_isspacep_shared">; + +// Environment register read +def int_nvvm_read_ptx_sreg_envreg0 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg0">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg0">; +def int_nvvm_read_ptx_sreg_envreg1 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg1">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg1">; +def int_nvvm_read_ptx_sreg_envreg2 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg2">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg2">; +def int_nvvm_read_ptx_sreg_envreg3 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg3">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg3">; +def int_nvvm_read_ptx_sreg_envreg4 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg4">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg4">; +def int_nvvm_read_ptx_sreg_envreg5 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg5">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg5">; +def int_nvvm_read_ptx_sreg_envreg6 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg6">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg6">; +def int_nvvm_read_ptx_sreg_envreg7 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg7">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg7">; +def int_nvvm_read_ptx_sreg_envreg8 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg8">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg8">; +def int_nvvm_read_ptx_sreg_envreg9 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg9">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg9">; +def int_nvvm_read_ptx_sreg_envreg10 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg10">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg10">; +def int_nvvm_read_ptx_sreg_envreg11 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg11">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg11">; +def int_nvvm_read_ptx_sreg_envreg12 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg12">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg12">; +def int_nvvm_read_ptx_sreg_envreg13 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg13">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg13">; +def int_nvvm_read_ptx_sreg_envreg14 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg14">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg14">; +def int_nvvm_read_ptx_sreg_envreg15 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg15">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg15">; +def int_nvvm_read_ptx_sreg_envreg16 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg16">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg16">; +def int_nvvm_read_ptx_sreg_envreg17 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg17">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg17">; +def int_nvvm_read_ptx_sreg_envreg18 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg18">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg18">; +def int_nvvm_read_ptx_sreg_envreg19 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg19">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg19">; +def int_nvvm_read_ptx_sreg_envreg20 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg20">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg20">; +def int_nvvm_read_ptx_sreg_envreg21 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg21">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg21">; +def int_nvvm_read_ptx_sreg_envreg22 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg22">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg22">; +def int_nvvm_read_ptx_sreg_envreg23 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg23">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg23">; +def int_nvvm_read_ptx_sreg_envreg24 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg24">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg24">; +def int_nvvm_read_ptx_sreg_envreg25 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg25">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg25">; +def int_nvvm_read_ptx_sreg_envreg26 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg26">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg26">; +def int_nvvm_read_ptx_sreg_envreg27 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg27">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg27">; +def int_nvvm_read_ptx_sreg_envreg28 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg28">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg28">; +def int_nvvm_read_ptx_sreg_envreg29 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg29">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg29">; +def int_nvvm_read_ptx_sreg_envreg30 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg30">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg30">; +def int_nvvm_read_ptx_sreg_envreg31 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg31">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg31">; + // Texture Fetch def int_nvvm_tex_1d_v4f32_i32 @@ -1800,6 +1950,25 @@ def int_nvvm_sust_p_3d_v4i32_trap "llvm.nvvm.sust.p.3d.v4i32.trap">, GCCBuiltin<"__nvvm_sust_p_3d_v4i32_trap">; +def int_nvvm_rotate_b32 + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem], "llvm.nvvm.rotate.b32">, + GCCBuiltin<"__nvvm_rotate_b32">; + +def int_nvvm_rotate_b64 + :Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem], "llvm.nvvm.rotate.b64">, + GCCBuiltin<"__nvvm_rotate_b64">; + +def int_nvvm_rotate_right_b64 + : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem], "llvm.nvvm.rotate.right.b64">, + GCCBuiltin<"__nvvm_rotate_right_b64">; + +def int_nvvm_swap_lo_hi_b64 + : Intrinsic<[llvm_i64_ty], [llvm_i64_ty], + [IntrNoMem], "llvm.nvvm.swap.lo.hi.b64">, + GCCBuiltin<"__nvvm_swap_lo_hi_b64">; // Old PTX back-end intrinsics retained here for backwards-compatibility diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index ecb5668..ba69eaa 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -33,4 +33,40 @@ defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tgid">; defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tidig">; + } // End TargetPrefix = "r600" + +let TargetPrefix = "AMDGPU" in { +def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, + // 1st parameter: Numerator + // 2nd parameter: Denominator + // 3rd parameter: Constant to select select between first and + // second. (0 = first, 1 = second). + Intrinsic<[llvm_anyfloat_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], + [IntrNoMem]>; + +def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">, + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">, + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_AMDGPU_trig_preop : GCCBuiltin<"__builtin_amdgpu_trig_preop">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; + +def int_AMDGPU_rcp : GCCBuiltin<"__builtin_amdgpu_rcp">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +} // End TargetPrefix = "AMDGPU" diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 36d93fe..5de9508 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -26,6 +26,12 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrReadWriteArgMem]>; } +// Read Performance-Monitoring Counter. +let TargetPrefix = "x86" in { + def int_x86_rdpmc : GCCBuiltin<"__builtin_ia32_rdpmc">, + Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; +} + //===----------------------------------------------------------------------===// // 3DNow! @@ -667,6 +673,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pshuf_d : GCCBuiltin<"__builtin_ia32_pshufd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse2_pshufl_w : GCCBuiltin<"__builtin_ia32_pshuflw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse2_pshufh_w : GCCBuiltin<"__builtin_ia32_pshufhw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; @@ -1304,15 +1319,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector load with broadcast let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vbroadcast_ss : - GCCBuiltin<"__builtin_ia32_vbroadcastss">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; - def int_x86_avx_vbroadcast_sd_256 : - GCCBuiltin<"__builtin_ia32_vbroadcastsd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; - def int_x86_avx_vbroadcast_ss_256 : - GCCBuiltin<"__builtin_ia32_vbroadcastss256">, - Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx_vbroadcastf128_pd_256 : GCCBuiltin<"__builtin_ia32_vbroadcastf128_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; @@ -1948,6 +1954,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i32_ty], [IntrNoMem, Commutative]>; def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } //===----------------------------------------------------------------------===// @@ -3141,6 +3149,16 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], []>; + def int_x86_avx512_mask_lzcnt_d_512 : + GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], + []>; + def int_x86_avx512_mask_lzcnt_q_512 : + GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], + []>; } // Vector blend diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index b72fc4c..e2e4912 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -43,7 +43,7 @@ class PassNameParser : public PassRegistrationListener, public cl::parser { cl::Option *Opt; public: - PassNameParser() : Opt(nullptr) {} + PassNameParser(); virtual ~PassNameParser(); void initialize(cl::Option &O) { diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 0c309e8..26f62db 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -16,6 +16,7 @@ #define LLVM_IR_MODULE_H #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Comdat.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" @@ -23,13 +24,13 @@ #include "llvm/IR/Metadata.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/system_error.h" +#include namespace llvm { - class FunctionType; class GVMaterializer; class LLVMContext; +class RandomNumberGenerator; class StructType; template struct DenseMapInfo; template class DenseMap; @@ -123,6 +124,8 @@ public: typedef iplist AliasListType; /// The type for the list of named metadata. typedef ilist NamedMDListType; + /// The type of the comdat "symbol" table. + typedef StringMap ComdatSymTabType; /// The Global Variable iterator. typedef GlobalListType::iterator global_iterator; @@ -197,11 +200,14 @@ private: NamedMDListType NamedMDList; ///< The named metadata in the module std::string GlobalScopeAsm; ///< Inline Asm at global scope. ValueSymbolTable *ValSymTab; ///< Symbol table for values + ComdatSymTabType ComdatSymTab; ///< Symbol table for COMDATs std::unique_ptr Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on void *NamedMDSymTab; ///< NamedMDNode names. + // Allow lazy initialization in const method. + mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. // We need to keep the string because the C API expects us to own the string // representation. @@ -250,6 +256,11 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } + /// Get the RandomNumberGenerator for this module. The RNG can be + /// seeded via -rng-seed= and is salted with the ModuleID. + /// The returned RNG should not be shared across threads. + RandomNumberGenerator &getRNG() const; + /// @} /// @name Module Level Mutators /// @{ @@ -397,6 +408,14 @@ public: void eraseNamedMetadata(NamedMDNode *NMD); /// @} +/// @name Comdat Accessors +/// @{ + + /// Return the Comdat in the module with the specified name. It is created + /// if it didn't already exist. + Comdat *getOrInsertComdat(StringRef Name); + +/// @} /// @name Module Flags Accessors /// @{ @@ -454,12 +473,12 @@ public: void Dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. - error_code materializeAll(); + std::error_code materializeAll(); /// Make sure all GlobalValues in this Module are fully read and clear the /// Materializer. If the module is corrupt, this DOES NOT clear the old /// Materializer. - error_code materializeAllPermanently(); + std::error_code materializeAllPermanently(bool ReleaseBuffer = false); /// @} /// @name Direct access to the globals list, functions list, and symbol table @@ -497,6 +516,10 @@ public: const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } /// Get the Module's symbol table of global variable and function identifiers. ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + /// Get the Module's symbol table for COMDATs (constant). + const ComdatSymTabType &getComdatSymbolTable() const { return ComdatSymTab; } + /// Get the Module's symbol table for COMDATs. + ComdatSymTabType &getComdatSymbolTable() { return ComdatSymTab; } /// @} /// @name Global Variable Iteration diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index bc7696b..848adae 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -39,6 +39,10 @@ class User : public Value { friend struct HungoffOperandTraits; virtual void anchor(); protected: + /// NumOperands - The number of values used by this User. + /// + unsigned NumOperands; + /// OperandList - This is a pointer to the array of Uses for this User. /// For nodes of fixed arity (e.g. a binary operator) this array will live /// prefixed to some derived class instance. For nodes of resizable variable @@ -46,13 +50,9 @@ protected: /// allocated and should be destroyed by the classes' virtual dtor. Use *OperandList; - /// NumOperands - The number of values used by this User. - /// - unsigned NumOperands; - void *operator new(size_t s, unsigned Us); User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) - : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} + : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {} Use *allocHungoffUses(unsigned) const; void dropHungoffUses() { Use::zap(OperandList, OperandList + NumOperands, true); diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 0158683..b5bbc96 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -67,6 +67,13 @@ typedef StringMapEntry ValueName; /// /// @brief LLVM Value Representation class Value { + Type *VTy; + Use *UseList; + + friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueHandleBase; + ValueName *Name; + const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? protected: @@ -77,6 +84,11 @@ protected: unsigned char SubclassOptionalData : 7; private: + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + unsigned short SubclassData; + template // UseT == 'Use' or 'const Use' class use_iterator_impl : public std::iterator { @@ -167,18 +179,6 @@ private: unsigned getOperandNo() const { return UI->getOperandNo(); } }; - /// SubclassData - This member is defined by this class, but is not used for - /// anything. Subclasses can use it to hold whatever state they find useful. - /// This field is initialized to zero by the ctor. - unsigned short SubclassData; - - Type *VTy; - Use *UseList; - - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. - friend class ValueHandleBase; - ValueName *Name; - void operator=(const Value &) LLVM_DELETED_FUNCTION; Value(const Value &) LLVM_DELETED_FUNCTION; @@ -430,7 +430,7 @@ public: /// isDereferenceablePointer - Test if this value is always a pointer to /// allocated and suitably aligned memory for a simple load or store. - bool isDereferenceablePointer() const; + bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, /// return the value in the PHI node corresponding to PredBB. If not, return diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index 1503aed..43a79c7 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -45,8 +45,10 @@ class ValueMapConstIterator; /// This class defines the default behavior for configurable aspects of /// ValueMap<>. User Configs should inherit from this class to be as compatible /// as possible with future versions of ValueMap. -template +template struct ValueMapConfig { + typedef MutexT mutex_type; + /// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's /// false, the ValueMap will leave the original mapping in place. enum { FollowRAUW = true }; @@ -67,7 +69,7 @@ struct ValueMapConfig { /// and onDelete) and not inside other ValueMap methods. NULL means that no /// mutex is necessary. template - static sys::Mutex *getMutex(const ExtraDataT &/*Data*/) { return nullptr; } + static mutex_type *getMutex(const ExtraDataT &/*Data*/) { return nullptr; } }; /// See the file comment. @@ -85,6 +87,7 @@ public: typedef KeyT key_type; typedef ValueT mapped_type; typedef std::pair value_type; + typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data() {} @@ -101,16 +104,16 @@ public: inline const_iterator end() const { return const_iterator(Map.end()); } bool empty() const { return Map.empty(); } - unsigned size() const { return Map.size(); } + size_type size() const { return Map.size(); } /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } void clear() { Map.clear(); } - /// count - Return true if the specified key is in the map. - bool count(const KeyT &Val) const { - return Map.find_as(Val) != Map.end(); + /// Return 1 if the specified key is in the map, 0 otherwise. + size_type count(const KeyT &Val) const { + return Map.find_as(Val) == Map.end() ? 0 : 1; } iterator find(const KeyT &Val) { @@ -212,7 +215,7 @@ public: void deleted() override { // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); - sys::Mutex *M = Config::getMutex(Copy.Map->Data); + typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); if (M) M->acquire(); Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. @@ -225,7 +228,7 @@ public: "Invalid RAUW on key of ValueMap<>"); // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); - sys::Mutex *M = Config::getMutex(Copy.Map->Data); + typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); if (M) M->acquire(); diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h index e2ae5f7..59ffc09 100644 --- a/include/llvm/IRReader/IRReader.h +++ b/include/llvm/IRReader/IRReader.h @@ -24,13 +24,6 @@ class MemoryBuffer; class SMDiagnostic; class LLVMContext; -/// If the given MemoryBuffer holds a bitcode image, return a Module for it -/// which does lazy deserialization of function bodies. Otherwise, attempt to -/// parse it as LLVM Assembly and return a fully populated Module. This -/// function *always* takes ownership of the given MemoryBuffer. -Module *getLazyIRModule(MemoryBuffer *Buffer, SMDiagnostic &Err, - LLVMContext &Context); - /// If the given file holds a bitcode image, return a Module /// for it which does lazy deserialization of function bodies. Otherwise, /// attempt to parse it as LLVM Assembly and return a fully populated @@ -40,8 +33,7 @@ Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, /// If the given MemoryBuffer holds a bitcode image, return a Module /// for it. Otherwise, attempt to parse it as LLVM Assembly and return -/// a Module for it. This function *always* takes ownership of the given -/// MemoryBuffer. +/// a Module for it. This function *never* takes ownership of Buffer. Module *ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, LLVMContext &Context); /// If the given file holds a bitcode image, return a Module for it. diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 8e53615..0c840f3 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -146,6 +146,8 @@ void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInternalizePassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); +void initializeJumpInstrTableInfoPass(PassRegistry&); +void initializeJumpInstrTablesPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAPass(PassRegistry&); void initializeLICMPass(PassRegistry&); @@ -272,6 +274,7 @@ void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&); +void initializeLoadCombinePass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h index f1b1480..c43846a 100644 --- a/include/llvm/LTO/LTOModule.h +++ b/include/llvm/LTO/LTOModule.h @@ -16,10 +16,10 @@ #include "llvm-c/lto.h" #include "llvm/ADT/StringMap.h" -#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Target/TargetMachine.h" #include #include @@ -46,9 +46,8 @@ private: const GlobalValue *symbol; }; - std::unique_ptr _module; + std::unique_ptr IRFile; std::unique_ptr _target; - MCObjectFileInfo ObjFileInfo; StringSet _linkeropt_strings; std::vector _deplibs; std::vector _linkeropts; @@ -58,25 +57,22 @@ private: StringSet _defines; StringMap _undefines; std::vector _asm_undefines; - MCContext _context; - // Use mangler to add GlobalPrefix to names to match linker names. - Mangler _mangler; - - LTOModule(Module *m, TargetMachine *t); + LTOModule(std::unique_ptr Obj, TargetMachine *TM); public: /// Returns 'true' if the file or memory contents is LLVM bitcode. static bool isBitcodeFile(const void *mem, size_t length); static bool isBitcodeFile(const char *path); - /// Returns 'true' if the file or memory contents is LLVM bitcode for the - /// specified triple. - static bool isBitcodeFileForTarget(const void *mem, - size_t length, - const char *triplePrefix); - static bool isBitcodeFileForTarget(const char *path, - const char *triplePrefix); + /// Returns 'true' if the memory buffer is LLVM bitcode for the specified + /// triple. + static bool isBitcodeForTarget(MemoryBuffer *memBuffer, + StringRef triplePrefix); + + /// Create a MemoryBuffer from a memory range with an optional name. + static MemoryBuffer *makeBuffer(const void *mem, size_t length, + StringRef name = ""); /// Create an LTOModule. N.B. These methods take ownership of the buffer. The /// caller must have initialized the Targets, the TargetMCs, the AsmPrinters, @@ -86,25 +82,34 @@ public: /// InitializeAllTargetMCs(); /// InitializeAllAsmPrinters(); /// InitializeAllAsmParsers(); - static LTOModule *makeLTOModule(const char *path, TargetOptions options, - std::string &errMsg); - static LTOModule *makeLTOModule(int fd, const char *path, size_t size, - TargetOptions options, std::string &errMsg); - static LTOModule *makeLTOModule(int fd, const char *path, size_t map_size, - off_t offset, TargetOptions options, - std::string &errMsg); - static LTOModule *makeLTOModule(const void *mem, size_t length, - TargetOptions options, std::string &errMsg, - StringRef path = ""); + static LTOModule *createFromFile(const char *path, TargetOptions options, + std::string &errMsg); + static LTOModule *createFromOpenFile(int fd, const char *path, size_t size, + TargetOptions options, + std::string &errMsg); + static LTOModule *createFromOpenFileSlice(int fd, const char *path, + size_t map_size, off_t offset, + TargetOptions options, + std::string &errMsg); + static LTOModule *createFromBuffer(const void *mem, size_t length, + TargetOptions options, std::string &errMsg, + StringRef path = ""); + + const Module &getModule() const { + return const_cast(this)->getModule(); + } + Module &getModule() { + return IRFile->getModule(); + } /// Return the Module's target triple. - const char *getTargetTriple() { - return _module->getTargetTriple().c_str(); + const std::string &getTargetTriple() { + return getModule().getTargetTriple(); } /// Set the Module's target triple. - void setTargetTriple(const char *triple) { - _module->setTargetTriple(triple); + void setTargetTriple(StringRef Triple) { + getModule().setTargetTriple(Triple); } /// Get the number of symbols @@ -150,9 +155,6 @@ public: return nullptr; } - /// Return the Module. - Module *getLLVVMModule() { return _module.get(); } - const std::vector &getAsmUndefinedRefs() { return _asm_undefines; } @@ -167,20 +169,20 @@ private: bool parseSymbols(std::string &errMsg); /// Add a symbol which isn't defined just yet to a list to be resolved later. - void addPotentialUndefinedSymbol(const GlobalValue *dcl, bool isFunc); + void addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym, + bool isFunc); /// Add a defined symbol to the list. - void addDefinedSymbol(const GlobalValue *def, bool isFunction); - - /// Add a function symbol as defined to the list. - void addDefinedFunctionSymbol(const Function *f); + void addDefinedSymbol(const char *Name, const GlobalValue *def, + bool isFunction); /// Add a data symbol as defined to the list. - void addDefinedDataSymbol(const GlobalValue *v); + void addDefinedDataSymbol(const object::BasicSymbolRef &Sym); + void addDefinedDataSymbol(const char*Name, const GlobalValue *v); - /// Add global symbols from module-level ASM to the defined or undefined - /// lists. - bool addAsmGlobalSymbols(std::string &errMsg); + /// Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(const object::BasicSymbolRef &Sym); + void addDefinedFunctionSymbol(const char *Name, const Function *F); /// Add a global symbol from module-level ASM to the defined list. void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); @@ -200,17 +202,10 @@ private: /// Get string that the data pointer points to. bool objcClassNameFromExpression(const Constant *c, std::string &name); - /// Returns 'true' if the memory buffer is for the specified target triple. - static bool isTargetMatch(MemoryBuffer *memBuffer, const char *triplePrefix); - /// Create an LTOModule (private version). N.B. This method takes ownership of /// the buffer. - static LTOModule *makeLTOModule(MemoryBuffer *buffer, TargetOptions options, - std::string &errMsg); - - /// Create a MemoryBuffer from a memory range with an optional name. - static MemoryBuffer *makeBuffer(const void *mem, size_t length, - StringRef name = ""); + static LTOModule *makeLTOModule(std::unique_ptr Buffer, + TargetOptions options, std::string &errMsg); }; } #endif // LTO_MODULE_H diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 2616ebd..b2309ff 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -85,6 +85,8 @@ namespace { (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); + (void) llvm::createJumpInstrTableInfoPass(); + (void) llvm::createJumpInstrTablesPass(); (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 42b2cb3..6254bbb 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -15,6 +15,8 @@ namespace llvm { +class Comdat; +class GlobalValue; class Module; class StringRef; class StructType; diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h new file mode 100644 index 0000000..2819b75 --- /dev/null +++ b/include/llvm/MC/ConstantPools.h @@ -0,0 +1,80 @@ +//===- ConstantPool.h - Keep track of assembler-generated ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ConstantPool and AssemblerConstantPools classes. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_MC_CONSTANTPOOL_H +#define LLVM_MC_CONSTANTPOOL_H + +#include "llvm/ADT/SmallVector.h" +namespace llvm { +class MCContext; +class MCExpr; +class MCSection; +class MCStreamer; +class MCSymbol; +// A class to keep track of assembler-generated constant pools that are use to +// implement the ldr-pseudo. +class ConstantPool { + typedef SmallVector, 4> EntryVecTy; + EntryVecTy Entries; + +public: + // Initialize a new empty constant pool + ConstantPool() {} + + // Add a new entry to the constant pool in the next slot. + // \param Value is the new entry to put in the constant pool. + // + // \returns a MCExpr that references the newly inserted value + const MCExpr *addEntry(const MCExpr *Value, MCContext &Context); + + // Emit the contents of the constant pool using the provided streamer. + void emitEntries(MCStreamer &Streamer); + + // Return true if the constant pool is empty + bool empty(); +}; + +class AssemblerConstantPools { + // Map type used to keep track of per-Section constant pools used by the + // ldr-pseudo opcode. The map associates a section to its constant pool. The + // constant pool is a vector of (label, value) pairs. When the ldr + // pseudo is parsed we insert a new (label, value) pair into the constant pool + // for the current section and add MCSymbolRefExpr to the new label as + // an opcode to the ldr. After we have parsed all the user input we + // output the (label, value) pairs in each constant pool at the end of the + // section. + // + // We use the MapVector for the map type to ensure stable iteration of + // the sections at the end of the parse. We need to iterate over the + // sections in a stable order to ensure that we have print the + // constant pools in a deterministic order when printing an assembly + // file. + typedef MapVector ConstantPoolMapTy; + ConstantPoolMapTy ConstantPools; + +public: + AssemblerConstantPools() {} + ~AssemblerConstantPools() {} + + void emitAll(MCStreamer &Streamer); + void emitForCurrentSection(MCStreamer &Streamer); + const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr); + +private: + ConstantPool *getConstantPool(const MCSection *Section); + ConstantPool &getOrCreateConstantPool(const MCSection *Section); +}; +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCAnalysis/MCAtom.h b/include/llvm/MC/MCAnalysis/MCAtom.h new file mode 100644 index 0000000..33f3431 --- /dev/null +++ b/include/llvm/MC/MCAnalysis/MCAtom.h @@ -0,0 +1,199 @@ +//===-- MCAtom.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCAtom class, which is used to +// represent a contiguous region in a decoded object that is uniformly data or +// instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCANALYSIS_MCATOM_H +#define LLVM_MC_MCANALYSIS_MCATOM_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class MCModule; + +class MCAtom; +class MCTextAtom; +class MCDataAtom; + +/// \brief Represents a contiguous range of either instructions (a TextAtom) +/// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. +class MCAtom { + virtual void anchor(); +public: + virtual ~MCAtom() {} + + enum AtomKind { TextAtom, DataAtom }; + AtomKind getKind() const { return Kind; } + + /// \brief Get the start address of the atom. + uint64_t getBeginAddr() const { return Begin; } + /// \brief Get the end address, i.e. the last one inside the atom. + uint64_t getEndAddr() const { return End; } + + /// \name Atom modification methods: + /// When modifying a TextAtom, keep instruction boundaries in mind. + /// For instance, split must me given the start address of an instruction. + /// @{ + + /// \brief Splits the atom in two at a given address. + /// \param SplitPt Address at which to start a new atom, splitting this one. + /// \returns The newly created atom starting at \p SplitPt. + virtual MCAtom *split(uint64_t SplitPt) = 0; + + /// \brief Truncates an atom, discarding everything after \p TruncPt. + /// \param TruncPt Last byte address to be contained in this atom. + virtual void truncate(uint64_t TruncPt) = 0; + /// @} + + /// \name Naming: + /// + /// This is mostly for display purposes, and may contain anything that hints + /// at what the atom contains: section or symbol name, BB start address, .. + /// @{ + StringRef getName() const { return Name; } + void setName(StringRef NewName) { Name = NewName.str(); } + /// @} + +protected: + const AtomKind Kind; + std::string Name; + MCModule *Parent; + uint64_t Begin, End; + + friend class MCModule; + MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) + : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } + + /// \name Atom remapping helpers + /// @{ + + /// \brief Remap the atom, using the given range, updating Begin/End. + /// One or both of the bounds can remain the same, but overlapping with other + /// atoms in the module is still forbidden. + void remap(uint64_t NewBegin, uint64_t NewEnd); + + /// \brief Remap the atom to prepare for a truncation at TruncPt. + /// Equivalent to: + /// \code + /// // Bound checks + /// remap(Begin, TruncPt); + /// \endcode + void remapForTruncate(uint64_t TruncPt); + + /// \brief Remap the atom to prepare for a split at SplitPt. + /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. + /// The current atom is truncated to \p LEnd. + void remapForSplit(uint64_t SplitPt, + uint64_t &LBegin, uint64_t &LEnd, + uint64_t &RBegin, uint64_t &REnd); + /// @} +}; + +/// \name Text atom +/// @{ + +/// \brief An entry in an MCTextAtom: a disassembled instruction. +/// NOTE: Both the Address and Size field are actually redundant when taken in +/// the context of the text atom, and may better be exposed in an iterator +/// instead of stored in the atom, which would replace this class. +class MCDecodedInst { +public: + MCInst Inst; + uint64_t Address; + uint64_t Size; + MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) + : Inst(Inst), Address(Address), Size(Size) {} +}; + +/// \brief An atom consisting of disassembled instructions. +class MCTextAtom : public MCAtom { +private: + typedef std::vector InstListTy; + InstListTy Insts; + + /// \brief The address of the next appended instruction, i.e., the + /// address immediately after the last instruction in the atom. + uint64_t NextInstAddress; +public: + /// Append an instruction, expanding the atom if necessary. + void addInst(const MCInst &Inst, uint64_t Size); + + /// \name Instruction list access + /// @{ + typedef InstListTy::const_iterator const_iterator; + const_iterator begin() const { return Insts.begin(); } + const_iterator end() const { return Insts.end(); } + + const MCDecodedInst &back() const { return Insts.back(); } + const MCDecodedInst &at(size_t n) const { return Insts.at(n); } + size_t size() const { return Insts.size(); } + /// @} + + /// \name Atom type specific split/truncate logic. + /// @{ + MCTextAtom *split(uint64_t SplitPt) override; + void truncate(uint64_t TruncPt) override; + /// @} + + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} +}; +/// @} + +/// \name Data atom +/// @{ + +/// \brief An entry in an MCDataAtom. +// NOTE: This may change to a more complex type in the future. +typedef uint8_t MCData; + +/// \brief An atom consising of a sequence of bytes. +class MCDataAtom : public MCAtom { + std::vector Data; + +public: + /// Append a data entry, expanding the atom if necessary. + void addData(const MCData &D); + + /// Get a reference to the data in this atom. + ArrayRef getData() const { return Data; } + + /// \name Atom type specific split/truncate logic. + /// @{ + MCDataAtom *split(uint64_t SplitPt) override; + void truncate(uint64_t TruncPt) override; + /// @} + + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(DataAtom, P, Begin, End) { + Data.reserve(End + 1 - Begin); + } +}; + +} + +#endif diff --git a/include/llvm/MC/MCAnalysis/MCFunction.h b/include/llvm/MC/MCAnalysis/MCFunction.h new file mode 100644 index 0000000..44fa450 --- /dev/null +++ b/include/llvm/MC/MCAnalysis/MCFunction.h @@ -0,0 +1,142 @@ +//===-- MCFunction.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the data structures to hold a CFG reconstructed from +// machine code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCANALYSIS_MCFUNCTION_H +#define LLVM_MC_MCANALYSIS_MCFUNCTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCInst.h" +#include +#include +#include + +namespace llvm { + +class MCFunction; +class MCModule; +class MCTextAtom; + +/// \brief Basic block containing a sequence of disassembled instructions. +/// The basic block is backed by an MCTextAtom, which holds the instructions, +/// and the address range it covers. +/// Create a basic block using MCFunction::createBlock. +class MCBasicBlock { + const MCTextAtom *Insts; + + // MCFunction owns the basic block. + MCFunction *Parent; + friend class MCFunction; + MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); + + /// \name Predecessors/Successors, to represent the CFG. + /// @{ + typedef std::vector BasicBlockListTy; + BasicBlockListTy Successors; + BasicBlockListTy Predecessors; + /// @} +public: + + /// \brief Get the backing MCTextAtom, containing the instruction sequence. + const MCTextAtom *getInsts() const { return Insts; } + + /// \name Get the owning MCFunction. + /// @{ + const MCFunction *getParent() const { return Parent; } + MCFunction *getParent() { return Parent; } + /// @} + + /// MC CFG access: Predecessors/Successors. + /// @{ + typedef BasicBlockListTy::const_iterator succ_const_iterator; + succ_const_iterator succ_begin() const { return Successors.begin(); } + succ_const_iterator succ_end() const { return Successors.end(); } + + typedef BasicBlockListTy::const_iterator pred_const_iterator; + pred_const_iterator pred_begin() const { return Predecessors.begin(); } + pred_const_iterator pred_end() const { return Predecessors.end(); } + + void addSuccessor(const MCBasicBlock *MCBB); + bool isSuccessor(const MCBasicBlock *MCBB) const; + + void addPredecessor(const MCBasicBlock *MCBB); + bool isPredecessor(const MCBasicBlock *MCBB) const; + + /// \brief Split block, mirrorring NewAtom = Insts->split(..). + /// This moves all successors to \p SplitBB, and + /// adds a fallthrough to it. + /// \p SplitBB The result of splitting Insts, a basic block directly following + /// this basic block. + void splitBasicBlock(MCBasicBlock *SplitBB); + /// @} +}; + +/// \brief Represents a function in machine code, containing MCBasicBlocks. +/// MCFunctions are created by MCModule. +class MCFunction { + MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; + MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; + + std::string Name; + MCModule *ParentModule; + typedef std::vector> BasicBlockListTy; + BasicBlockListTy Blocks; + + // MCModule owns the function. + friend class MCModule; + MCFunction(StringRef Name, MCModule *Parent); + +public: + /// \brief Create an MCBasicBlock backed by Insts and add it to this function. + /// \param Insts Sequence of straight-line code backing the basic block. + /// \returns The newly created basic block. + MCBasicBlock &createBlock(const MCTextAtom &Insts); + + StringRef getName() const { return Name; } + + /// \name Get the owning MC Module. + /// @{ + const MCModule *getParent() const { return ParentModule; } + MCModule *getParent() { return ParentModule; } + /// @} + + /// \name Access to the function's basic blocks. No ordering is enforced, + /// except that the first block is the entry block. + /// @{ + /// \brief Get the entry point basic block. + const MCBasicBlock *getEntryBlock() const { return front(); } + MCBasicBlock *getEntryBlock() { return front(); } + + bool empty() const { return Blocks.empty(); } + + typedef BasicBlockListTy::const_iterator const_iterator; + typedef BasicBlockListTy:: iterator iterator; + const_iterator begin() const { return Blocks.begin(); } + iterator begin() { return Blocks.begin(); } + const_iterator end() const { return Blocks.end(); } + iterator end() { return Blocks.end(); } + + const MCBasicBlock* front() const { return Blocks.front().get(); } + MCBasicBlock* front() { return Blocks.front().get(); } + const MCBasicBlock* back() const { return Blocks.back().get(); } + MCBasicBlock* back() { return Blocks.back().get(); } + + /// \brief Find the basic block, if any, that starts at \p StartAddr. + const MCBasicBlock *find(uint64_t StartAddr) const; + MCBasicBlock *find(uint64_t StartAddr); + /// @} +}; + +} + +#endif diff --git a/include/llvm/MC/MCAnalysis/MCModule.h b/include/llvm/MC/MCAnalysis/MCModule.h new file mode 100644 index 0000000..cf7e2c0 --- /dev/null +++ b/include/llvm/MC/MCAnalysis/MCModule.h @@ -0,0 +1,134 @@ +//===-- MCModule.h - MCModule class -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCModule class, which is used to +// represent a complete, disassembled object file or executable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCANALYSIS_MCMODULE_H +#define LLVM_MC_MCANALYSIS_MCMODULE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { + +class MCAtom; +class MCBasicBlock; +class MCDataAtom; +class MCFunction; +class MCObjectDisassembler; +class MCTextAtom; + +/// \brief A completely disassembled object file or executable. +/// It comprises a list of MCAtom's, each representing a contiguous range of +/// either instructions or data. +/// An MCModule is created using MCObjectDisassembler::buildModule. +class MCModule { + /// \name Atom tracking + /// @{ + + /// \brief Atoms in this module, sorted by begin address. + /// FIXME: This doesn't handle overlapping atoms (which happen when a basic + /// block starts in the middle of an instruction of another basic block.) + typedef std::vector AtomListTy; + AtomListTy Atoms; + + // For access to map/remap. + friend class MCAtom; + + /// \brief Remap \p Atom to the given range, and update its Begin/End fields. + /// \param Atom An atom belonging to this module. + /// An atom should always use this method to update its bounds, because this + /// enables the owning MCModule to keep track of its atoms. + void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); + + /// \brief Insert an atom in the module, using its Begin and End addresses. + void map(MCAtom *NewAtom); + /// @} + + /// \name Basic block tracking + /// @{ + typedef std::vector BBsByAtomTy; + BBsByAtomTy BBsByAtom; + + // For access to basic block > atom tracking. + friend class MCBasicBlock; + friend class MCTextAtom; + + /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. + /// This is used to update succs/preds when \p Atom is split. + void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); + void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); + /// @} + + /// \name Function tracking + /// @{ + typedef std::vector> FunctionListTy; + FunctionListTy Functions; + /// @} + + /// The address of the entrypoint function. + uint64_t Entrypoint; + + MCModule (const MCModule &) LLVM_DELETED_FUNCTION; + MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; + + // MCObjectDisassembler creates MCModules. + friend class MCObjectDisassembler; + +public: + MCModule(); + ~MCModule(); + + /// \name Create a new MCAtom covering the specified offset range. + /// @{ + MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); + MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); + /// @} + + /// \name Access to the owned atom list, ordered by begin address. + /// @{ + const MCAtom *findAtomContaining(uint64_t Addr) const; + MCAtom *findAtomContaining(uint64_t Addr); + const MCAtom *findFirstAtomAfter(uint64_t Addr) const; + MCAtom *findFirstAtomAfter(uint64_t Addr); + + typedef AtomListTy::const_iterator const_atom_iterator; + typedef AtomListTy:: iterator atom_iterator; + const_atom_iterator atom_begin() const { return Atoms.begin(); } + atom_iterator atom_begin() { return Atoms.begin(); } + const_atom_iterator atom_end() const { return Atoms.end(); } + atom_iterator atom_end() { return Atoms.end(); } + /// @} + + /// \brief Create a new MCFunction. + MCFunction *createFunction(StringRef Name); + + /// \name Access to the owned function list. + /// @{ + typedef FunctionListTy::const_iterator const_func_iterator; + typedef FunctionListTy:: iterator func_iterator; + const_func_iterator func_begin() const { return Functions.begin(); } + func_iterator func_begin() { return Functions.begin(); } + const_func_iterator func_end() const { return Functions.end(); } + func_iterator func_end() { return Functions.end(); } + /// @} + + /// \brief Get the address of the entrypoint function, or 0 if there is none. + uint64_t getEntrypoint() const { return Entrypoint; } +}; + +} + +#endif diff --git a/include/llvm/MC/MCAnalysis/MCModuleYAML.h b/include/llvm/MC/MCAnalysis/MCModuleYAML.h new file mode 100644 index 0000000..4856277 --- /dev/null +++ b/include/llvm/MC/MCAnalysis/MCModuleYAML.h @@ -0,0 +1,40 @@ +//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- 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 declares classes for handling the YAML representation +/// of MCModule. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCANALYSIS_MCMODULEYAML_H +#define LLVM_MC_MCANALYSIS_MCMODULEYAML_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAnalysis/MCModule.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCInstrInfo; +class MCRegisterInfo; + +/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. +/// \returns The empty string on success, an error message on failure. +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +/// \brief Creates a new module and returns it in \p MCM. +/// \returns The empty string on success, an error message on failure. +StringRef yaml2mcmodule(std::unique_ptr &MCM, StringRef YamlContent, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index f7d3be2..06e473d 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -23,546 +23,496 @@ #include namespace llvm { - class MCExpr; - class MCSection; - class MCStreamer; - class MCSymbol; - class MCContext; - - namespace ExceptionHandling { - enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 }; +class MCExpr; +class MCSection; +class MCStreamer; +class MCSymbol; +class MCContext; + +namespace WinEH { +enum class EncodingType { + ET_Invalid, /// Invalid + ET_Alpha, /// Windows Alpha + ET_Alpha64, /// Windows AXP64 + ET_ARM, /// Windows NT (Windows on ARM) + ET_CE, /// Windows CE ARM, PowerPC, SH3, SH4 + ET_Itanium, /// Windows x64, Windows Itanium (IA-64) + ET_MIPS = ET_Alpha, +}; +} + +enum class ExceptionHandling { + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling +}; + +namespace LCOMM { +enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment }; +} + +/// This class is intended to be used as a base class for asm +/// properties and features specific to the target. +class MCAsmInfo { +protected: + //===------------------------------------------------------------------===// + // Properties to be set by the target writer, used to configure asm printer. + // + + /// Pointer size in bytes. Default is 4. + unsigned PointerSize; + + /// Size of the stack slot reserved for callee-saved registers, in bytes. + /// Default is same as pointer size. + unsigned CalleeSaveStackSlotSize; + + /// True if target is little endian. Default is true. + bool IsLittleEndian; + + /// True if target stack grow up. Default is false. + bool StackGrowsUp; + + /// True if this target has the MachO .subsections_via_symbols directive. + /// Default is false. + bool HasSubsectionsViaSymbols; + + /// True if this is a MachO target that supports the macho-specific .zerofill + /// directive for emitting BSS Symbols. Default is false. + bool HasMachoZeroFillDirective; + + /// True if this is a MachO target that supports the macho-specific .tbss + /// directive for emitting thread local BSS Symbols. Default is false. + bool HasMachoTBSSDirective; + + /// True if the compiler should emit a ".reference .constructors_used" or + /// ".reference .destructors_used" directive after the a static ctor/dtor + /// list. This directive is only emitted in Static relocation model. Default + /// is false. + bool HasStaticCtorDtorReferenceInStaticMode; + + /// True if the linker has a bug and requires that the debug_line section be + /// of a minimum size. In practice such a linker requires a non-empty line + /// sequence if a file is present. Default to false. + bool LinkerRequiresNonEmptyDwarfLines; + + /// This is the maximum possible length of an instruction, which is needed to + /// compute the size of an inline asm. Defaults to 4. + unsigned MaxInstLength; + + /// Every possible instruction length is a multiple of this value. Factored + /// out in .debug_frame and .debug_line. Defaults to 1. + unsigned MinInstAlignment; + + /// The '$' token, when not referencing an identifier or constant, refers to + /// the current PC. Defaults to false. + bool DollarIsPC; + + /// This string, if specified, is used to separate instructions from each + /// other when on the same line. Defaults to ';' + const char *SeparatorString; + + /// This indicates the comment character used by the assembler. Defaults to + /// "#" + const char *CommentString; + + /// This is appended to emitted labels. Defaults to ":" + const char *LabelSuffix; + + // Print the EH begin symbol with an assignment. Defaults to false. + bool UseAssignmentForEHBegin; + + /// This prefix is used for globals like constant pool entries that are + /// completely private to the .s file and should not have names in the .o + /// file. Defaults to "L" + const char *PrivateGlobalPrefix; + + /// This prefix is used for symbols that should be passed through the + /// assembler but be removed by the linker. This is 'l' on Darwin, currently + /// used for some ObjC metadata. The default of "" meast that for this system + /// a plain private symbol should be used. Defaults to "". + const char *LinkerPrivateGlobalPrefix; + + /// If these are nonempty, they contain a directive to emit before and after + /// an inline assembly statement. Defaults to "#APP\n", "#NO_APP\n" + const char *InlineAsmStart; + const char *InlineAsmEnd; + + /// These are assembly directives that tells the assembler to interpret the + /// following instructions differently. Defaults to ".code16", ".code32", + /// ".code64". + const char *Code16Directive; + const char *Code32Directive; + const char *Code64Directive; + + /// Which dialect of an assembler variant to use. Defaults to 0 + unsigned AssemblerDialect; + + /// This is true if the assembler allows @ characters in symbol names. + /// Defaults to false. + bool AllowAtInName; + + /// This is true if data region markers should be printed as + /// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels + /// instead. + bool UseDataRegionDirectives; + + //===--- Data Emission Directives -------------------------------------===// + + /// This should be set to the directive used to get some number of zero bytes + /// emitted to the current section. Common cases are "\t.zero\t" and + /// "\t.space\t". If this is set to null, the Data*bitsDirective's will be + /// used to emit zero bytes. Defaults to "\t.zero\t" + const char *ZeroDirective; + + /// This directive allows emission of an ascii string with the standard C + /// escape characters embedded into it. Defaults to "\t.ascii\t" + const char *AsciiDirective; + + /// If not null, this allows for special handling of zero terminated strings + /// on this target. This is commonly supported as ".asciz". If a target + /// doesn't support this, it can be set to null. Defaults to "\t.asciz\t" + const char *AscizDirective; + + /// These directives are used to output some unit of integer data to the + /// current section. If a data directive is set to null, smaller data + /// directives will be used to emit the large sizes. Defaults to "\t.byte\t", + /// "\t.short\t", "\t.long\t", "\t.quad\t" + const char *Data8bitsDirective; + const char *Data16bitsDirective; + const char *Data32bitsDirective; + const char *Data64bitsDirective; + + /// If non-null, a directive that is used to emit a word which should be + /// relocated as a 64-bit GP-relative offset, e.g. .gpdword on Mips. Defaults + /// to NULL. + const char *GPRel64Directive; + + /// If non-null, a directive that is used to emit a word which should be + /// relocated as a 32-bit GP-relative offset, e.g. .gpword on Mips or .gprel32 + /// on Alpha. Defaults to NULL. + const char *GPRel32Directive; + + /// This is true if this target uses "Sun Style" syntax for section switching + /// ("#alloc,#write" etc) instead of the normal ELF syntax (,"a,w") in + /// .section directives. Defaults to false. + bool SunStyleELFSectionSwitchSyntax; + + /// This is true if this target uses ELF '.section' directive before the + /// '.bss' one. It's used for PPC/Linux which doesn't support the '.bss' + /// directive only. Defaults to false. + bool UsesELFSectionDirectiveForBSS; + + bool NeedsDwarfSectionOffsetDirective; + + //===--- Alignment Information ----------------------------------------===// + + /// If this is true (the default) then the asmprinter emits ".align N" + /// directives, where N is the number of bytes to align to. Otherwise, it + /// emits ".align log2(N)", e.g. 3 to align to an 8 byte boundary. Defaults + /// to true. + bool AlignmentIsInBytes; + + /// If non-zero, this is used to fill the executable space created as the + /// result of a alignment directive. Defaults to 0 + unsigned TextAlignFillValue; + + //===--- Global Variable Emission Directives --------------------------===// + + /// This is the directive used to declare a global entity. Defaults to NULL. + const char *GlobalDirective; + + /// True if the assembler supports the .set directive. Defaults to true. + bool HasSetDirective; + + /// False if the assembler requires that we use + /// \code + /// Lc = a - b + /// .long Lc + /// \endcode + // + /// instead of + // + /// \code + /// .long a - b + /// \endcode + /// + /// Defaults to true. + bool HasAggressiveSymbolFolding; + + /// True is .comm's and .lcomms optional alignment is to be specified in bytes + /// instead of log2(n). Defaults to true. + bool COMMDirectiveAlignmentIsInBytes; + + /// Describes if the .lcomm directive for the target supports an alignment + /// argument and how it is interpreted. Defaults to NoAlignment. + LCOMM::LCOMMType LCOMMDirectiveAlignmentType; + + /// True if the target has .type and .size directives, this is true for most + /// ELF targets. Defaults to true. + bool HasDotTypeDotSizeDirective; + + /// True if the target has a single parameter .file directive, this is true + /// for ELF targets. Defaults to true. + bool HasSingleParameterDotFile; + + /// True if the target has a .ident directive, this is true for ELF targets. + /// Defaults to false. + bool HasIdentDirective; + + /// True if this target supports the MachO .no_dead_strip directive. Defaults + /// to false. + bool HasNoDeadStrip; + + /// This directive, if non-null, is used to declare a global as being a weak + /// undefined symbol. Defaults to NULL. + const char *WeakRefDirective; + + /// True if we have a directive to declare a global as being a weak defined + /// symbol. Defaults to false. + bool HasWeakDefDirective; + + /// True if we have a directive to declare a global as being a weak defined + /// symbol that can be hidden (unexported). Defaults to false. + bool HasWeakDefCanBeHiddenDirective; + + /// True if we have a .linkonce directive. This is used on cygwin/mingw. + /// Defaults to false. + bool HasLinkOnceDirective; + + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having + /// hidden visibility. Defaults to MCSA_Hidden. + MCSymbolAttr HiddenVisibilityAttr; + + /// This attribute, if not MCSA_Invalid, is used to declare an undefined + /// symbol as having hidden visibility. Defaults to MCSA_Hidden. + MCSymbolAttr HiddenDeclarationVisibilityAttr; + + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having + /// protected visibility. Defaults to MCSA_Protected + MCSymbolAttr ProtectedVisibilityAttr; + + //===--- Dwarf Emission Directives -----------------------------------===// + + /// True if target asm supports leb128 directives. Defaults to false. + bool HasLEB128; + + /// True if target supports emission of debugging information. Defaults to + /// false. + bool SupportsDebugInformation; + + /// Exception handling format for the target. Defaults to None. + ExceptionHandling ExceptionsType; + + /// Windows exception handling data (.pdata) encoding. Defaults to Invalid. + WinEH::EncodingType WinEHEncodingType; + + /// True if Dwarf2 output generally uses relocations for references to other + /// .debug_* sections. + bool DwarfUsesRelocationsAcrossSections; + + /// True if DWARF FDE symbol reference relocations should be replaced by an + /// absolute difference. + bool DwarfFDESymbolsUseAbsDiff; + + /// True if dwarf register numbers are printed instead of symbolic register + /// names in .cfi_* directives. Defaults to false. + bool DwarfRegNumForCFI; + + /// True if target uses parens to indicate the symbol variant instead of @. + /// For example, foo(plt) instead of foo@plt. Defaults to false. + bool UseParensForSymbolVariant; + + //===--- Prologue State ----------------------------------------------===// + + std::vector InitialFrameState; + + //===--- Integrated Assembler State ----------------------------------===// + + /// Should we use the integrated assembler? + /// The integrated assembler should be enabled by default (by the + /// constructors) when failing to parse a valid piece of assembly (inline + /// or otherwise) is considered a bug. It may then be overridden after + /// construction (see LLVMTargetMachine::initAsmInfo()). + bool UseIntegratedAssembler; + + /// Compress DWARF debug sections. Defaults to false. + bool CompressDebugSections; + +public: + explicit MCAsmInfo(); + virtual ~MCAsmInfo(); + + /// Get the pointer size in bytes. + unsigned getPointerSize() const { return PointerSize; } + + /// Get the callee-saved register stack slot + /// size in bytes. + unsigned getCalleeSaveStackSlotSize() const { + return CalleeSaveStackSlotSize; } - namespace LCOMM { - enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment }; + /// True if the target is little endian. + bool isLittleEndian() const { return IsLittleEndian; } + + /// True if target stack grow up. + bool isStackGrowthDirectionUp() const { return StackGrowsUp; } + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + + // Data directive accessors. + + const char *getData8bitsDirective() const { return Data8bitsDirective; } + const char *getData16bitsDirective() const { return Data16bitsDirective; } + const char *getData32bitsDirective() const { return Data32bitsDirective; } + const char *getData64bitsDirective() const { return Data64bitsDirective; } + const char *getGPRel64Directive() const { return GPRel64Directive; } + const char *getGPRel32Directive() const { return GPRel32Directive; } + + /// Targets can implement this method to specify a section to switch to if the + /// translation unit doesn't have any trampolines that require an executable + /// stack. + virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + return nullptr; } - /// MCAsmInfo - This class is intended to be used as a base class for asm - /// properties and features specific to the target. - class MCAsmInfo { - protected: - //===------------------------------------------------------------------===// - // Properties to be set by the target writer, used to configure asm printer. - // - - /// PointerSize - Pointer size in bytes. - /// Default is 4. - unsigned PointerSize; - - /// CalleeSaveStackSlotSize - Size of the stack slot reserved for - /// callee-saved registers, in bytes. - /// Default is same as pointer size. - unsigned CalleeSaveStackSlotSize; - - /// IsLittleEndian - True if target is little endian. - /// Default is true. - bool IsLittleEndian; - - /// StackGrowsUp - True if target stack grow up. - /// Default is false. - bool StackGrowsUp; - - /// HasSubsectionsViaSymbols - True if this target has the MachO - /// .subsections_via_symbols directive. - bool HasSubsectionsViaSymbols; // Default is false. - - /// HasMachoZeroFillDirective - True if this is a MachO target that supports - /// the macho-specific .zerofill directive for emitting BSS Symbols. - bool HasMachoZeroFillDirective; // Default is false. - - /// HasMachoTBSSDirective - True if this is a MachO target that supports - /// the macho-specific .tbss directive for emitting thread local BSS Symbols - bool HasMachoTBSSDirective; // Default is false. - - /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should - /// emit a ".reference .constructors_used" or ".reference .destructors_used" - /// directive after the a static ctor/dtor list. This directive is only - /// emitted in Static relocation model. - bool HasStaticCtorDtorReferenceInStaticMode; // Default is false. - - /// LinkerRequiresNonEmptyDwarfLines - True if the linker has a bug and - /// requires that the debug_line section be of a minimum size. In practice - /// such a linker requires a non-empty line sequence if a file is present. - bool LinkerRequiresNonEmptyDwarfLines; // Default to false. - - /// MaxInstLength - This is the maximum possible length of an instruction, - /// which is needed to compute the size of an inline asm. - unsigned MaxInstLength; // Defaults to 4. - - /// MinInstAlignment - Every possible instruction length is a multiple of - /// this value. Factored out in .debug_frame and .debug_line. - unsigned MinInstAlignment; // Defaults to 1. - - /// DollarIsPC - The '$' token, when not referencing an identifier or - /// constant, refers to the current PC. - bool DollarIsPC; // Defaults to false. - - /// SeparatorString - This string, if specified, is used to separate - /// instructions from each other when on the same line. - const char *SeparatorString; // Defaults to ';' - - /// CommentString - This indicates the comment character used by the - /// assembler. - const char *CommentString; // Defaults to "#" - - /// LabelSuffix - This is appended to emitted labels. - const char *LabelSuffix; // Defaults to ":" - - /// LabelSuffix - This is appended to emitted labels. - const char *DebugLabelSuffix; // Defaults to ":" - - /// This prefix is used for globals like constant pool entries that are - /// completely private to the .s file and should not have names in the .o - /// file. - const char *PrivateGlobalPrefix; // Defaults to "L" - - /// This prefix is used for symbols that should be passed through the - /// assembler but be removed by the linker. This is 'l' on Darwin, - /// currently used for some ObjC metadata. - /// The default of "" meast that for this system a plain private symbol - /// should be used. - const char *LinkerPrivateGlobalPrefix; // Defaults to "". - - /// InlineAsmStart/End - If these are nonempty, they contain a directive to - /// emit before and after an inline assembly statement. - const char *InlineAsmStart; // Defaults to "#APP\n" - const char *InlineAsmEnd; // Defaults to "#NO_APP\n" - - /// Code16Directive, Code32Directive, Code64Directive - These are assembly - /// directives that tells the assembler to interpret the following - /// instructions differently. - const char *Code16Directive; // Defaults to ".code16" - const char *Code32Directive; // Defaults to ".code32" - const char *Code64Directive; // Defaults to ".code64" - - /// AssemblerDialect - Which dialect of an assembler variant to use. - unsigned AssemblerDialect; // Defaults to 0 - - /// \brief This is true if the assembler allows @ characters in symbol - /// names. Defaults to false. - bool AllowAtInName; - - /// UseDataRegionDirectives - This is true if data region markers should - /// be printed as ".data_region/.end_data_region" directives. If false, - /// use "$d/$a" labels instead. - bool UseDataRegionDirectives; - - //===--- Data Emission Directives -------------------------------------===// - - /// ZeroDirective - this should be set to the directive used to get some - /// number of zero bytes emitted to the current section. Common cases are - /// "\t.zero\t" and "\t.space\t". If this is set to null, the - /// Data*bitsDirective's will be used to emit zero bytes. - const char *ZeroDirective; // Defaults to "\t.zero\t" - - /// AsciiDirective - This directive allows emission of an ascii string with - /// the standard C escape characters embedded into it. - const char *AsciiDirective; // Defaults to "\t.ascii\t" - - /// AscizDirective - If not null, this allows for special handling of - /// zero terminated strings on this target. This is commonly supported as - /// ".asciz". If a target doesn't support this, it can be set to null. - const char *AscizDirective; // Defaults to "\t.asciz\t" - - /// DataDirectives - These directives are used to output some unit of - /// integer data to the current section. If a data directive is set to - /// null, smaller data directives will be used to emit the large sizes. - const char *Data8bitsDirective; // Defaults to "\t.byte\t" - const char *Data16bitsDirective; // Defaults to "\t.short\t" - const char *Data32bitsDirective; // Defaults to "\t.long\t" - const char *Data64bitsDirective; // Defaults to "\t.quad\t" - - /// GPRel64Directive - if non-null, a directive that is used to emit a word - /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword - /// on Mips. - const char *GPRel64Directive; // Defaults to NULL. - - /// GPRel32Directive - if non-null, a directive that is used to emit a word - /// which should be relocated as a 32-bit GP-relative offset, e.g. .gpword - /// on Mips or .gprel32 on Alpha. - const char *GPRel32Directive; // Defaults to NULL. - - /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun - /// Style" syntax for section switching ("#alloc,#write" etc) instead of the - /// normal ELF syntax (,"a,w") in .section directives. - bool SunStyleELFSectionSwitchSyntax; // Defaults to false. - - /// UsesELFSectionDirectiveForBSS - This is true if this target uses ELF - /// '.section' directive before the '.bss' one. It's used for PPC/Linux - /// which doesn't support the '.bss' directive only. - bool UsesELFSectionDirectiveForBSS; // Defaults to false. - - bool NeedsDwarfSectionOffsetDirective; - - //===--- Alignment Information ----------------------------------------===// - - /// AlignmentIsInBytes - If this is true (the default) then the asmprinter - /// emits ".align N" directives, where N is the number of bytes to align to. - /// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte - /// boundary. - bool AlignmentIsInBytes; // Defaults to true - - /// TextAlignFillValue - If non-zero, this is used to fill the executable - /// space created as the result of a alignment directive. - unsigned TextAlignFillValue; // Defaults to 0 + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + + virtual const MCExpr *getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; + + bool usesSunStyleELFSectionSwitchSyntax() const { + return SunStyleELFSectionSwitchSyntax; + } - //===--- Global Variable Emission Directives --------------------------===// + bool usesELFSectionDirectiveForBSS() const { + return UsesELFSectionDirectiveForBSS; + } + + bool needsDwarfSectionOffsetDirective() const { + return NeedsDwarfSectionOffsetDirective; + } + + // Accessors. + + bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } + bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + bool hasStaticCtorDtorReferenceInStaticMode() const { + return HasStaticCtorDtorReferenceInStaticMode; + } + bool getLinkerRequiresNonEmptyDwarfLines() const { + return LinkerRequiresNonEmptyDwarfLines; + } + unsigned getMaxInstLength() const { return MaxInstLength; } + unsigned getMinInstAlignment() const { return MinInstAlignment; } + bool getDollarIsPC() const { return DollarIsPC; } + const char *getSeparatorString() const { return SeparatorString; } + + /// This indicates the column (zero-based) at which asm comments should be + /// printed. + unsigned getCommentColumn() const { return 40; } + + const char *getCommentString() const { return CommentString; } + const char *getLabelSuffix() const { return LabelSuffix; } + + bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } + const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + bool hasLinkerPrivateGlobalPrefix() const { + return LinkerPrivateGlobalPrefix[0] != '\0'; + } + const char *getLinkerPrivateGlobalPrefix() const { + if (hasLinkerPrivateGlobalPrefix()) + return LinkerPrivateGlobalPrefix; + return getPrivateGlobalPrefix(); + } + const char *getInlineAsmStart() const { return InlineAsmStart; } + const char *getInlineAsmEnd() const { return InlineAsmEnd; } + const char *getCode16Directive() const { return Code16Directive; } + const char *getCode32Directive() const { return Code32Directive; } + const char *getCode64Directive() const { return Code64Directive; } + unsigned getAssemblerDialect() const { return AssemblerDialect; } + bool doesAllowAtInName() const { return AllowAtInName; } + bool doesSupportDataRegionDirectives() const { + return UseDataRegionDirectives; + } + const char *getZeroDirective() const { return ZeroDirective; } + const char *getAsciiDirective() const { return AsciiDirective; } + const char *getAscizDirective() const { return AscizDirective; } + bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } + unsigned getTextAlignFillValue() const { return TextAlignFillValue; } + const char *getGlobalDirective() const { return GlobalDirective; } + bool hasSetDirective() const { return HasSetDirective; } + bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } + bool getCOMMDirectiveAlignmentIsInBytes() const { + return COMMDirectiveAlignmentIsInBytes; + } + LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { + return LCOMMDirectiveAlignmentType; + } + bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } + bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } + bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakRefDirective() const { return WeakRefDirective; } + bool hasWeakDefDirective() const { return HasWeakDefDirective; } + bool hasWeakDefCanBeHiddenDirective() const { + return HasWeakDefCanBeHiddenDirective; + } + bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } - /// GlobalDirective - This is the directive used to declare a global entity. - /// - const char *GlobalDirective; // Defaults to NULL. - - /// HasSetDirective - True if the assembler supports the .set directive. - bool HasSetDirective; // Defaults to true. - - /// HasAggressiveSymbolFolding - False if the assembler requires that we use - /// Lc = a - b - /// .long Lc - /// instead of - /// .long a - b - bool HasAggressiveSymbolFolding; // Defaults to true. + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; } + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { + return HiddenDeclarationVisibilityAttr; + } + MCSymbolAttr getProtectedVisibilityAttr() const { + return ProtectedVisibilityAttr; + } + bool hasLEB128() const { return HasLEB128; } + bool doesSupportDebugInformation() const { return SupportsDebugInformation; } + bool doesSupportExceptionHandling() const { + return ExceptionsType != ExceptionHandling::None; + } + ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } + WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } + bool isExceptionHandlingDwarf() const { + return (ExceptionsType == ExceptionHandling::DwarfCFI || + ExceptionsType == ExceptionHandling::ARM || + // Windows handler data still uses DWARF LSDA encoding. + ExceptionsType == ExceptionHandling::WinEH); + } + bool doesDwarfUseRelocationsAcrossSections() const { + return DwarfUsesRelocationsAcrossSections; + } + bool doDwarfFDESymbolsUseAbsDiff() const { return DwarfFDESymbolsUseAbsDiff; } + bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; } + bool useParensForSymbolVariant() const { return UseParensForSymbolVariant; } - /// COMMDirectiveAlignmentIsInBytes - True is .comm's and .lcomms optional - /// alignment is to be specified in bytes instead of log2(n). - bool COMMDirectiveAlignmentIsInBytes; // Defaults to true; + void addInitialFrameState(const MCCFIInstruction &Inst) { + InitialFrameState.push_back(Inst); + } - /// LCOMMDirectiveAlignment - Describes if the .lcomm directive for the - /// target supports an alignment argument and how it is interpreted. - LCOMM::LCOMMType LCOMMDirectiveAlignmentType; // Defaults to NoAlignment. - - /// HasDotTypeDotSizeDirective - True if the target has .type and .size - /// directives, this is true for most ELF targets. - bool HasDotTypeDotSizeDirective; // Defaults to true. + const std::vector &getInitialFrameState() const { + return InitialFrameState; + } - /// HasSingleParameterDotFile - True if the target has a single parameter - /// .file directive, this is true for ELF targets. - bool HasSingleParameterDotFile; // Defaults to true. + /// Return true if assembly (inline or otherwise) should be parsed. + bool useIntegratedAssembler() const { return UseIntegratedAssembler; } - /// hasIdentDirective - True if the target has a .ident directive, this is - /// true for ELF targets. - bool HasIdentDirective; // Defaults to false. + /// Set whether assembly (inline or otherwise) should be parsed. + virtual void setUseIntegratedAssembler(bool Value) { + UseIntegratedAssembler = Value; + } - /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip - /// directive. - bool HasNoDeadStrip; // Defaults to false. + bool compressDebugSections() const { return CompressDebugSections; } - /// WeakRefDirective - This directive, if non-null, is used to declare a - /// global as being a weak undefined symbol. - const char *WeakRefDirective; // Defaults to NULL. - - /// True if we have a directive to declare a global as being a weak - /// defined symbol. - bool HasWeakDefDirective; // Defaults to false. - - /// True if we have a directive to declare a global as being a weak - /// defined symbol that can be hidden (unexported). - bool HasWeakDefCanBeHiddenDirective; // Defaults to false. - - /// True if we have a .linkonce directive. This is used on cygwin/mingw. - bool HasLinkOnceDirective; // Defaults to false. - - /// HiddenVisibilityAttr - This attribute, if not MCSA_Invalid, is used to - /// declare a symbol as having hidden visibility. - MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. - - /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid, - /// is used to declare an undefined symbol as having hidden visibility. - MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden. - - - /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used - /// to declare a symbol as having protected visibility. - MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected - - //===--- Dwarf Emission Directives -----------------------------------===// - - /// HasLEB128 - True if target asm supports leb128 directives. - bool HasLEB128; // Defaults to false. - - /// SupportsDebugInformation - True if target supports emission of debugging - /// information. - bool SupportsDebugInformation; // Defaults to false. - - /// SupportsExceptionHandling - True if target supports exception handling. - ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None - - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally - /// uses relocations for references to other .debug_* sections. - bool DwarfUsesRelocationsAcrossSections; - - /// DwarfFDESymbolsUseAbsDiff - true if DWARF FDE symbol reference - /// relocations should be replaced by an absolute difference. - bool DwarfFDESymbolsUseAbsDiff; - - /// DwarfRegNumForCFI - True if dwarf register numbers are printed - /// instead of symbolic register names in .cfi_* directives. - bool DwarfRegNumForCFI; // Defaults to false; - - /// UseParensForSymbolVariant - True if target uses parens to indicate the - /// symbol variant instead of @. For example, foo(plt) instead of foo@plt. - bool UseParensForSymbolVariant; // Defaults to false; - - //===--- Prologue State ----------------------------------------------===// - - std::vector InitialFrameState; - - //===--- Integrated Assembler State ----------------------------------===// - /// Should we use the integrated assembler? - /// The integrated assembler should be enabled by default (by the - /// constructors) when failing to parse a valid piece of assembly (inline - /// or otherwise) is considered a bug. It may then be overridden after - /// construction (see LLVMTargetMachine::initAsmInfo()). - bool UseIntegratedAssembler; - - /// Compress DWARF debug sections. Defaults to false. - bool CompressDebugSections; - - public: - explicit MCAsmInfo(); - virtual ~MCAsmInfo(); - - /// getPointerSize - Get the pointer size in bytes. - unsigned getPointerSize() const { - return PointerSize; - } - - /// getCalleeSaveStackSlotSize - Get the callee-saved register stack slot - /// size in bytes. - unsigned getCalleeSaveStackSlotSize() const { - return CalleeSaveStackSlotSize; - } - - /// isLittleEndian - True if the target is little endian. - bool isLittleEndian() const { - return IsLittleEndian; - } - - /// isStackGrowthDirectionUp - True if target stack grow up. - bool isStackGrowthDirectionUp() const { - return StackGrowsUp; - } - - bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } - - // Data directive accessors. - // - const char *getData8bitsDirective() const { - return Data8bitsDirective; - } - const char *getData16bitsDirective() const { - return Data16bitsDirective; - } - const char *getData32bitsDirective() const { - return Data32bitsDirective; - } - const char *getData64bitsDirective() const { - return Data64bitsDirective; - } - const char *getGPRel64Directive() const { return GPRel64Directive; } - const char *getGPRel32Directive() const { return GPRel32Directive; } - - /// getNonexecutableStackSection - Targets can implement this method to - /// specify a section to switch to if the translation unit doesn't have any - /// trampolines that require an executable stack. - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const{ - return nullptr; - } - - virtual const MCExpr * - getExprForPersonalitySymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const; - - virtual const MCExpr * - getExprForFDESymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const; - - bool usesSunStyleELFSectionSwitchSyntax() const { - return SunStyleELFSectionSwitchSyntax; - } - - bool usesELFSectionDirectiveForBSS() const { - return UsesELFSectionDirectiveForBSS; - } - - bool needsDwarfSectionOffsetDirective() const { - return NeedsDwarfSectionOffsetDirective; - } - - // Accessors. - // - bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } - bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } - bool hasStaticCtorDtorReferenceInStaticMode() const { - return HasStaticCtorDtorReferenceInStaticMode; - } - bool getLinkerRequiresNonEmptyDwarfLines() const { - return LinkerRequiresNonEmptyDwarfLines; - } - unsigned getMaxInstLength() const { - return MaxInstLength; - } - unsigned getMinInstAlignment() const { - return MinInstAlignment; - } - bool getDollarIsPC() const { - return DollarIsPC; - } - const char *getSeparatorString() const { - return SeparatorString; - } - - /// This indicates the column (zero-based) at which asm comments should be - /// printed. - unsigned getCommentColumn() const { - return 40; - } - - const char *getCommentString() const { - return CommentString; - } - const char *getLabelSuffix() const { - return LabelSuffix; - } - - const char *getDebugLabelSuffix() const { - return DebugLabelSuffix; - } - const char *getPrivateGlobalPrefix() const { - return PrivateGlobalPrefix; - } - bool hasLinkerPrivateGlobalPrefix() const { - return LinkerPrivateGlobalPrefix[0] != '\0'; - } - const char *getLinkerPrivateGlobalPrefix() const { - if (hasLinkerPrivateGlobalPrefix()) - return LinkerPrivateGlobalPrefix; - return getPrivateGlobalPrefix(); - } - const char *getInlineAsmStart() const { - return InlineAsmStart; - } - const char *getInlineAsmEnd() const { - return InlineAsmEnd; - } - const char *getCode16Directive() const { - return Code16Directive; - } - const char *getCode32Directive() const { - return Code32Directive; - } - const char *getCode64Directive() const { - return Code64Directive; - } - unsigned getAssemblerDialect() const { - return AssemblerDialect; - } - bool doesAllowAtInName() const { - return AllowAtInName; - } - bool doesSupportDataRegionDirectives() const { - return UseDataRegionDirectives; - } - const char *getZeroDirective() const { - return ZeroDirective; - } - const char *getAsciiDirective() const { - return AsciiDirective; - } - const char *getAscizDirective() const { - return AscizDirective; - } - bool getAlignmentIsInBytes() const { - return AlignmentIsInBytes; - } - unsigned getTextAlignFillValue() const { - return TextAlignFillValue; - } - const char *getGlobalDirective() const { - return GlobalDirective; - } - bool hasSetDirective() const { return HasSetDirective; } - bool hasAggressiveSymbolFolding() const { - return HasAggressiveSymbolFolding; - } - bool getCOMMDirectiveAlignmentIsInBytes() const { - return COMMDirectiveAlignmentIsInBytes; - } - LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { - return LCOMMDirectiveAlignmentType; - } - bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} - bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } - bool hasIdentDirective() const { return HasIdentDirective; } - bool hasNoDeadStrip() const { return HasNoDeadStrip; } - const char *getWeakRefDirective() const { return WeakRefDirective; } - bool hasWeakDefDirective() const { return HasWeakDefDirective; } - bool hasWeakDefCanBeHiddenDirective() const { - return HasWeakDefCanBeHiddenDirective; - } - bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } - - MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} - MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { - return HiddenDeclarationVisibilityAttr; - } - MCSymbolAttr getProtectedVisibilityAttr() const { - return ProtectedVisibilityAttr; - } - bool hasLEB128() const { - return HasLEB128; - } - bool doesSupportDebugInformation() const { - return SupportsDebugInformation; - } - bool doesSupportExceptionHandling() const { - return ExceptionsType != ExceptionHandling::None; - } - ExceptionHandling::ExceptionsType getExceptionHandlingType() const { - return ExceptionsType; - } - bool isExceptionHandlingDwarf() const { - return - (ExceptionsType == ExceptionHandling::DwarfCFI || - ExceptionsType == ExceptionHandling::ARM || - ExceptionsType == ExceptionHandling::Win64); - } - bool doesDwarfUseRelocationsAcrossSections() const { - return DwarfUsesRelocationsAcrossSections; - } - bool doDwarfFDESymbolsUseAbsDiff() const { - return DwarfFDESymbolsUseAbsDiff; - } - bool useDwarfRegNumForCFI() const { - return DwarfRegNumForCFI; - } - bool useParensForSymbolVariant() const { - return UseParensForSymbolVariant; - } - - void addInitialFrameState(const MCCFIInstruction &Inst) { - InitialFrameState.push_back(Inst); - } - - const std::vector &getInitialFrameState() const { - return InitialFrameState; - } - - /// Return true if assembly (inline or otherwise) should be parsed. - bool useIntegratedAssembler() const { return UseIntegratedAssembler; } - - /// Set whether assembly (inline or otherwise) should be parsed. - virtual void setUseIntegratedAssembler(bool Value) { - UseIntegratedAssembler = Value; - } - - bool compressDebugSections() const { return CompressDebugSections; } - - void setCompressDebugSections(bool CompressDebugSections) { - this->CompressDebugSections = CompressDebugSections; - } - }; + void setCompressDebugSections(bool CompressDebugSections) { + this->CompressDebugSections = CompressDebugSections; + } +}; } #endif diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index be13b36..1cb34c2 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -802,7 +802,7 @@ public: /// @} - void dump(); + void dump() const; }; // FIXME: This really doesn't belong here. See comments below. diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h deleted file mode 100644 index e9d0fba..0000000 --- a/include/llvm/MC/MCAtom.h +++ /dev/null @@ -1,199 +0,0 @@ -//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCAtom class, which is used to -// represent a contiguous region in a decoded object that is uniformly data or -// instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCATOM_H -#define LLVM_MC_MCATOM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { - -class MCModule; - -class MCAtom; -class MCTextAtom; -class MCDataAtom; - -/// \brief Represents a contiguous range of either instructions (a TextAtom) -/// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. -class MCAtom { - virtual void anchor(); -public: - virtual ~MCAtom() {} - - enum AtomKind { TextAtom, DataAtom }; - AtomKind getKind() const { return Kind; } - - /// \brief Get the start address of the atom. - uint64_t getBeginAddr() const { return Begin; } - /// \brief Get the end address, i.e. the last one inside the atom. - uint64_t getEndAddr() const { return End; } - - /// \name Atom modification methods: - /// When modifying a TextAtom, keep instruction boundaries in mind. - /// For instance, split must me given the start address of an instruction. - /// @{ - - /// \brief Splits the atom in two at a given address. - /// \param SplitPt Address at which to start a new atom, splitting this one. - /// \returns The newly created atom starting at \p SplitPt. - virtual MCAtom *split(uint64_t SplitPt) = 0; - - /// \brief Truncates an atom, discarding everything after \p TruncPt. - /// \param TruncPt Last byte address to be contained in this atom. - virtual void truncate(uint64_t TruncPt) = 0; - /// @} - - /// \name Naming: - /// - /// This is mostly for display purposes, and may contain anything that hints - /// at what the atom contains: section or symbol name, BB start address, .. - /// @{ - StringRef getName() const { return Name; } - void setName(StringRef NewName) { Name = NewName.str(); } - /// @} - -protected: - const AtomKind Kind; - std::string Name; - MCModule *Parent; - uint64_t Begin, End; - - friend class MCModule; - MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) - : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } - - /// \name Atom remapping helpers - /// @{ - - /// \brief Remap the atom, using the given range, updating Begin/End. - /// One or both of the bounds can remain the same, but overlapping with other - /// atoms in the module is still forbidden. - void remap(uint64_t NewBegin, uint64_t NewEnd); - - /// \brief Remap the atom to prepare for a truncation at TruncPt. - /// Equivalent to: - /// \code - /// // Bound checks - /// remap(Begin, TruncPt); - /// \endcode - void remapForTruncate(uint64_t TruncPt); - - /// \brief Remap the atom to prepare for a split at SplitPt. - /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. - /// The current atom is truncated to \p LEnd. - void remapForSplit(uint64_t SplitPt, - uint64_t &LBegin, uint64_t &LEnd, - uint64_t &RBegin, uint64_t &REnd); - /// @} -}; - -/// \name Text atom -/// @{ - -/// \brief An entry in an MCTextAtom: a disassembled instruction. -/// NOTE: Both the Address and Size field are actually redundant when taken in -/// the context of the text atom, and may better be exposed in an iterator -/// instead of stored in the atom, which would replace this class. -class MCDecodedInst { -public: - MCInst Inst; - uint64_t Address; - uint64_t Size; - MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) - : Inst(Inst), Address(Address), Size(Size) {} -}; - -/// \brief An atom consisting of disassembled instructions. -class MCTextAtom : public MCAtom { -private: - typedef std::vector InstListTy; - InstListTy Insts; - - /// \brief The address of the next appended instruction, i.e., the - /// address immediately after the last instruction in the atom. - uint64_t NextInstAddress; -public: - /// Append an instruction, expanding the atom if necessary. - void addInst(const MCInst &Inst, uint64_t Size); - - /// \name Instruction list access - /// @{ - typedef InstListTy::const_iterator const_iterator; - const_iterator begin() const { return Insts.begin(); } - const_iterator end() const { return Insts.end(); } - - const MCDecodedInst &back() const { return Insts.back(); } - const MCDecodedInst &at(size_t n) const { return Insts.at(n); } - size_t size() const { return Insts.size(); } - /// @} - - /// \name Atom type specific split/truncate logic. - /// @{ - MCTextAtom *split(uint64_t SplitPt) override; - void truncate(uint64_t TruncPt) override; - /// @} - - // Class hierarchy. - static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } -private: - friend class MCModule; - // Private constructor - only callable by MCModule - MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} -}; -/// @} - -/// \name Data atom -/// @{ - -/// \brief An entry in an MCDataAtom. -// NOTE: This may change to a more complex type in the future. -typedef uint8_t MCData; - -/// \brief An atom consising of a sequence of bytes. -class MCDataAtom : public MCAtom { - std::vector Data; - -public: - /// Append a data entry, expanding the atom if necessary. - void addData(const MCData &D); - - /// Get a reference to the data in this atom. - ArrayRef getData() const { return Data; } - - /// \name Atom type specific split/truncate logic. - /// @{ - MCDataAtom *split(uint64_t SplitPt) override; - void truncate(uint64_t TruncPt) override; - /// @} - - // Class hierarchy. - static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } -private: - friend class MCModule; - // Private constructor - only callable by MCModule - MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(DataAtom, P, Begin, End) { - Data.reserve(End + 1 - Begin); - } -}; - -} - -#endif diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 7557e76..eb0340f 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -11,15 +11,18 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include +#include #include // FIXME: Shouldn't be needed. namespace llvm { @@ -129,11 +132,10 @@ namespace llvm { /// assembly source files. unsigned GenDwarfFileNumber; - /// The default initial text section that we generate dwarf debugging line - /// info for when generating dwarf assembly source files. - const MCSection *GenDwarfSection; - /// Symbols created for the start and end of this section. - MCSymbol *GenDwarfSectionStartSym, *GenDwarfSectionEndSym; + /// Symbols created for the start and end of each section, used for + /// generating the .debug_ranges and .debug_aranges sections. + MapVector > + SectionStartEndSyms; /// The information gathered from labels that will have dwarf label /// entries when generating dwarf assembly source files. @@ -159,10 +161,11 @@ namespace llvm { unsigned DwarfCompileUnitID; typedef std::pair SectionGroupPair; + typedef std::tuple SectionGroupTriple; StringMap MachOUniquingMap; std::map ELFUniquingMap; - std::map COFFUniquingMap; + std::map COFFUniquingMap; /// Do automatic reset in destructor bool AutoReset; @@ -273,9 +276,7 @@ namespace llvm { const MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, - StringRef COMDATSymName, - int Selection, - const MCSectionCOFF *Assoc = nullptr); + StringRef COMDATSymName, int Selection); const MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, @@ -376,16 +377,18 @@ namespace llvm { void setGenDwarfFileNumber(unsigned FileNumber) { GenDwarfFileNumber = FileNumber; } - const MCSection *getGenDwarfSection() { return GenDwarfSection; } - void setGenDwarfSection(const MCSection *Sec) { GenDwarfSection = Sec; } - MCSymbol *getGenDwarfSectionStartSym() { return GenDwarfSectionStartSym; } - void setGenDwarfSectionStartSym(MCSymbol *Sym) { - GenDwarfSectionStartSym = Sym; + MapVector > & + getGenDwarfSectionSyms() { + return SectionStartEndSyms; } - MCSymbol *getGenDwarfSectionEndSym() { return GenDwarfSectionEndSym; } - void setGenDwarfSectionEndSym(MCSymbol *Sym) { - GenDwarfSectionEndSym = Sym; + std::pair >::iterator, + bool> + addGenDwarfSection(const MCSection *Sec) { + return SectionStartEndSyms.insert( + std::make_pair(Sec, std::make_pair(nullptr, nullptr))); } + void finalizeDwarfSections(MCStreamer &MCOS); const std::vector &getMCGenDwarfLabelEntries() const { return MCGenDwarfLabelEntries; } diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 6df8a19..6cd9a9a 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -465,14 +465,13 @@ public: struct MCDwarfFrameInfo { MCDwarfFrameInfo() - : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), - Function(nullptr), Instructions(), PersonalityEncoding(), LsdaEncoding(0), - CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} + : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), + Instructions(), PersonalityEncoding(), LsdaEncoding(0), + CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; - const MCSymbol *Function; std::vector Instructions; unsigned PersonalityEncoding; unsigned LsdaEncoding; diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index be39128..66729fe 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -48,7 +48,6 @@ public: void ChangeSection(const MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol) override; - void EmitDebugLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h index 2f1f561..297c442 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -41,6 +41,7 @@ namespace llvm { ELF_STT_File = (ELF::STT_FILE << ELF_STT_Shift), ELF_STT_Common = (ELF::STT_COMMON << ELF_STT_Shift), ELF_STT_Tls = (ELF::STT_TLS << ELF_STT_Shift), + ELF_STT_GnuIFunc = (ELF::STT_GNU_IFUNC << ELF_STT_Shift), ELF_STT_Loproc = (ELF::STT_LOPROC << ELF_STT_Shift), ELF_STT_Hiproc = (ELF::STT_HIPROC << ELF_STT_Shift), diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index ca5cecb..e96ecb4 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -21,6 +21,7 @@ class MCAssembler; class MCContext; class MCSection; class MCSectionData; +class MCStreamer; class MCSymbol; class MCValue; class raw_ostream; @@ -524,7 +525,7 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const = 0; - virtual void AddValueSymbols(MCAssembler *) const = 0; + virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; virtual const MCSection *FindAssociatedSection() const = 0; virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; diff --git a/include/llvm/MC/MCFunction.h b/include/llvm/MC/MCFunction.h deleted file mode 100644 index bfa470b..0000000 --- a/include/llvm/MC/MCFunction.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- llvm/MC/MCFunction.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the data structures to hold a CFG reconstructed from -// machine code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCFUNCTION_H -#define LLVM_MC_MCFUNCTION_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCInst.h" -#include -#include -#include - -namespace llvm { - -class MCFunction; -class MCModule; -class MCTextAtom; - -/// \brief Basic block containing a sequence of disassembled instructions. -/// The basic block is backed by an MCTextAtom, which holds the instructions, -/// and the address range it covers. -/// Create a basic block using MCFunction::createBlock. -class MCBasicBlock { - const MCTextAtom *Insts; - - // MCFunction owns the basic block. - MCFunction *Parent; - friend class MCFunction; - MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); - - /// \name Predecessors/Successors, to represent the CFG. - /// @{ - typedef std::vector BasicBlockListTy; - BasicBlockListTy Successors; - BasicBlockListTy Predecessors; - /// @} -public: - - /// \brief Get the backing MCTextAtom, containing the instruction sequence. - const MCTextAtom *getInsts() const { return Insts; } - - /// \name Get the owning MCFunction. - /// @{ - const MCFunction *getParent() const { return Parent; } - MCFunction *getParent() { return Parent; } - /// @} - - /// MC CFG access: Predecessors/Successors. - /// @{ - typedef BasicBlockListTy::const_iterator succ_const_iterator; - succ_const_iterator succ_begin() const { return Successors.begin(); } - succ_const_iterator succ_end() const { return Successors.end(); } - - typedef BasicBlockListTy::const_iterator pred_const_iterator; - pred_const_iterator pred_begin() const { return Predecessors.begin(); } - pred_const_iterator pred_end() const { return Predecessors.end(); } - - void addSuccessor(const MCBasicBlock *MCBB); - bool isSuccessor(const MCBasicBlock *MCBB) const; - - void addPredecessor(const MCBasicBlock *MCBB); - bool isPredecessor(const MCBasicBlock *MCBB) const; - - /// \brief Split block, mirrorring NewAtom = Insts->split(..). - /// This moves all successors to \p SplitBB, and - /// adds a fallthrough to it. - /// \p SplitBB The result of splitting Insts, a basic block directly following - /// this basic block. - void splitBasicBlock(MCBasicBlock *SplitBB); - /// @} -}; - -/// \brief Represents a function in machine code, containing MCBasicBlocks. -/// MCFunctions are created by MCModule. -class MCFunction { - MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; - MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; - - std::string Name; - MCModule *ParentModule; - typedef std::vector> BasicBlockListTy; - BasicBlockListTy Blocks; - - // MCModule owns the function. - friend class MCModule; - MCFunction(StringRef Name, MCModule *Parent); - -public: - /// \brief Create an MCBasicBlock backed by Insts and add it to this function. - /// \param Insts Sequence of straight-line code backing the basic block. - /// \returns The newly created basic block. - MCBasicBlock &createBlock(const MCTextAtom &Insts); - - StringRef getName() const { return Name; } - - /// \name Get the owning MC Module. - /// @{ - const MCModule *getParent() const { return ParentModule; } - MCModule *getParent() { return ParentModule; } - /// @} - - /// \name Access to the function's basic blocks. No ordering is enforced, - /// except that the first block is the entry block. - /// @{ - /// \brief Get the entry point basic block. - const MCBasicBlock *getEntryBlock() const { return front(); } - MCBasicBlock *getEntryBlock() { return front(); } - - bool empty() const { return Blocks.empty(); } - - typedef BasicBlockListTy::const_iterator const_iterator; - typedef BasicBlockListTy:: iterator iterator; - const_iterator begin() const { return Blocks.begin(); } - iterator begin() { return Blocks.begin(); } - const_iterator end() const { return Blocks.end(); } - iterator end() { return Blocks.end(); } - - const MCBasicBlock* front() const { return Blocks.front().get(); } - MCBasicBlock* front() { return Blocks.front().get(); } - const MCBasicBlock* back() const { return Blocks.back().get(); } - MCBasicBlock* back() { return Blocks.back().get(); } - - /// \brief Find the basic block, if any, that starts at \p StartAddr. - const MCBasicBlock *find(uint64_t StartAddr) const; - MCBasicBlock *find(uint64_t StartAddr); - /// @} -}; - -} - -#endif diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 3b0d933..50fd527 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -132,8 +132,19 @@ public: /// the given @p Layout. uint64_t getEmitSize(const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { - std::string Buffer; - raw_string_ostream OutStream(Buffer); + class raw_counting_ostream : public raw_ostream { + uint64_t Count; + + void write_impl(const char *, size_t size) override { Count += size; } + + uint64_t current_pos() const override { return Count; } + + public: + raw_counting_ostream() : Count(0) {} + ~raw_counting_ostream() { flush(); } + }; + + raw_counting_ostream OutStream; Emit_impl(OutStream, ObjWriter, Layout); return OutStream.tell(); } diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index e7d5bbd..12a7f0e 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -111,6 +111,8 @@ class MachObjectWriter : public MCObjectWriter { /// @} + MachSymbolData *findSymbolData(const MCSymbol &Sym); + public: MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, bool _IsLittleEndian) diff --git a/include/llvm/MC/MCModule.h b/include/llvm/MC/MCModule.h deleted file mode 100644 index aa389cb..0000000 --- a/include/llvm/MC/MCModule.h +++ /dev/null @@ -1,134 +0,0 @@ -//===-- llvm/MC/MCModule.h - MCModule class ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCModule class, which is used to -// represent a complete, disassembled object file or executable. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCMODULE_H -#define LLVM_MC_MCMODULE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" -#include -#include - -namespace llvm { - -class MCAtom; -class MCBasicBlock; -class MCDataAtom; -class MCFunction; -class MCObjectDisassembler; -class MCTextAtom; - -/// \brief A completely disassembled object file or executable. -/// It comprises a list of MCAtom's, each representing a contiguous range of -/// either instructions or data. -/// An MCModule is created using MCObjectDisassembler::buildModule. -class MCModule { - /// \name Atom tracking - /// @{ - - /// \brief Atoms in this module, sorted by begin address. - /// FIXME: This doesn't handle overlapping atoms (which happen when a basic - /// block starts in the middle of an instruction of another basic block.) - typedef std::vector AtomListTy; - AtomListTy Atoms; - - // For access to map/remap. - friend class MCAtom; - - /// \brief Remap \p Atom to the given range, and update its Begin/End fields. - /// \param Atom An atom belonging to this module. - /// An atom should always use this method to update its bounds, because this - /// enables the owning MCModule to keep track of its atoms. - void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); - - /// \brief Insert an atom in the module, using its Begin and End addresses. - void map(MCAtom *NewAtom); - /// @} - - /// \name Basic block tracking - /// @{ - typedef std::vector BBsByAtomTy; - BBsByAtomTy BBsByAtom; - - // For access to basic block > atom tracking. - friend class MCBasicBlock; - friend class MCTextAtom; - - /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. - /// This is used to update succs/preds when \p Atom is split. - void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); - void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); - /// @} - - /// \name Function tracking - /// @{ - typedef std::vector> FunctionListTy; - FunctionListTy Functions; - /// @} - - /// The address of the entrypoint function. - uint64_t Entrypoint; - - MCModule (const MCModule &) LLVM_DELETED_FUNCTION; - MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; - - // MCObjectDisassembler creates MCModules. - friend class MCObjectDisassembler; - -public: - MCModule(); - ~MCModule(); - - /// \name Create a new MCAtom covering the specified offset range. - /// @{ - MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); - MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); - /// @} - - /// \name Access to the owned atom list, ordered by begin address. - /// @{ - const MCAtom *findAtomContaining(uint64_t Addr) const; - MCAtom *findAtomContaining(uint64_t Addr); - const MCAtom *findFirstAtomAfter(uint64_t Addr) const; - MCAtom *findFirstAtomAfter(uint64_t Addr); - - typedef AtomListTy::const_iterator const_atom_iterator; - typedef AtomListTy:: iterator atom_iterator; - const_atom_iterator atom_begin() const { return Atoms.begin(); } - atom_iterator atom_begin() { return Atoms.begin(); } - const_atom_iterator atom_end() const { return Atoms.end(); } - atom_iterator atom_end() { return Atoms.end(); } - /// @} - - /// \brief Create a new MCFunction. - MCFunction *createFunction(StringRef Name); - - /// \name Access to the owned function list. - /// @{ - typedef FunctionListTy::const_iterator const_func_iterator; - typedef FunctionListTy:: iterator func_iterator; - const_func_iterator func_begin() const { return Functions.begin(); } - func_iterator func_begin() { return Functions.begin(); } - const_func_iterator func_end() const { return Functions.end(); } - func_iterator func_end() { return Functions.end(); } - /// @} - - /// \brief Get the address of the entrypoint function, or 0 if there is none. - uint64_t getEntrypoint() const { return Entrypoint; } -}; - -} - -#endif diff --git a/include/llvm/MC/MCModuleYAML.h b/include/llvm/MC/MCModuleYAML.h deleted file mode 100644 index c4ae829..0000000 --- a/include/llvm/MC/MCModuleYAML.h +++ /dev/null @@ -1,40 +0,0 @@ -//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- 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 declares classes for handling the YAML representation -/// of MCModule. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCMODULEYAML_H -#define LLVM_MC_MCMODULEYAML_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCModule.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -class MCInstrInfo; -class MCRegisterInfo; - -/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. -/// \returns The empty string on success, an error message on failure. -StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, - const MCInstrInfo &MII, const MCRegisterInfo &MRI); - -/// \brief Creates a new module and returns it in \p MCM. -/// \returns The empty string on success, an error message on failure. -StringRef yaml2mcmodule(std::unique_ptr &MCM, StringRef YamlContent, - const MCInstrInfo &MII, const MCRegisterInfo &MRI); - -} // end namespace llvm - -#endif diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 1a56040..4d1715e 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -14,13 +14,13 @@ #ifndef LLVM_MC_MCBJECTFILEINFO_H #define LLVM_MC_MCBJECTFILEINFO_H +#include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" namespace llvm { class MCContext; class MCSection; class StringRef; - class Triple; class MCObjectFileInfo { protected: @@ -33,12 +33,6 @@ protected: /// weak_definition of constant 0 for an omitted EH frame. bool SupportsWeakOmittedEHFrame; - /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the - /// "EH_frame" symbol for EH information should be an assembler temporary (aka - /// private linkage, aka an L or .L label) or false if it should be a normal - /// non-.globl label. This defaults to true. - bool IsFunctionEHFrameSymbolPrivate; - /// SupportsCompactUnwindWithoutEHFrame - True if the target object file /// supports emitting a compact unwind section without an associated EH frame /// section. @@ -201,9 +195,6 @@ public: void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, MCContext &ctx); - bool isFunctionEHFrameSymbolPrivate() const { - return IsFunctionEHFrameSymbolPrivate; - } bool getSupportsWeakOmittedEHFrame() const { return SupportsWeakOmittedEHFrame; } @@ -380,6 +371,7 @@ private: Reloc::Model RelocM; CodeModel::Model CMModel; MCContext *Ctx; + Triple TT; void InitMachOMCObjectFileInfo(Triple T); void InitELFMCObjectFileInfo(Triple T); @@ -388,6 +380,9 @@ private: /// InitEHFrameSection - Initialize EHFrameSection on demand. /// void InitEHFrameSection(); + +public: + const Triple &getTargetTriple() const { return TT; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index e41a8ba..8d37c85 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -78,16 +78,15 @@ protected: /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment() const; - const MCExpr *AddValueSymbols(const MCExpr *Value); - public: + void visitUsedSymbol(const MCSymbol &Sym) override; + MCAssembler &getAssembler() { return *Assembler; } /// @name MCStreamer Interface /// @{ void EmitLabel(MCSymbol *Symbol) override; - void EmitDebugLabel(MCSymbol *Symbol) override; void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()) override; @@ -126,6 +125,10 @@ public: void EmitFill(uint64_t NumBytes, uint8_t FillValue) override; void EmitZeros(uint64_t NumBytes) override; void FinishImpl() override; + + virtual bool mayHaveInstructions() const { + return getCurrentSectionData()->hasInstructions(); + } }; } // end namespace llvm diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 59b5c09..0b550ba 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -28,7 +28,7 @@ class AsmLexer : public MCAsmLexer { const MCAsmInfo &MAI; const char *CurPtr; - const MemoryBuffer *CurBuf; + StringRef CurBuf; bool isAtStartOfLine; void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; @@ -42,7 +42,7 @@ public: AsmLexer(const MCAsmInfo &MAI); ~AsmLexer(); - void setBuffer(const MemoryBuffer *buf, const char *ptr = nullptr); + void setBuffer(StringRef Buf, const char *ptr = nullptr); StringRef LexUntilEndOfStatement() override; StringRef LexUntilEndOfLine(); diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index f751786..9836795 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -30,23 +30,24 @@ class SMRange; class SourceMgr; class Twine; +class InlineAsmIdentifierInfo { +public: + void *OpDecl; + bool IsVarDecl; + unsigned Length, Size, Type; + + void clear() { + OpDecl = nullptr; + IsVarDecl = false; + Length = 1; + Size = 0; + Type = 0; + } +}; + /// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: - typedef struct { - void *OpDecl; - bool IsVarDecl; - unsigned Length, Size, Type; - - void clear() { - OpDecl = nullptr; - IsVarDecl = false; - Length = 1; - Size = 0; - Type = 0; - } - } InlineAsmIdentifierInfo; - virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, @@ -56,9 +57,6 @@ public: unsigned &Offset) = 0; }; -typedef MCAsmParserSemaCallback::InlineAsmIdentifierInfo - InlineAsmIdentifierInfo; - /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. class MCAsmParser { diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index a428f9e..d205e2a 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -42,24 +42,15 @@ class MCSymbol; /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 mutable int Selection; - /// Assoc - This is name of the associated section, if it is a COMDAT - /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 with an - /// associative Selection (IMAGE_COMDAT_SELECT_ASSOCIATIVE). - mutable const MCSectionCOFF *Assoc; - private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - const MCSymbol *COMDATSymbol, int Selection, - const MCSectionCOFF *Assoc, SectionKind K) + const MCSymbol *COMDATSymbol, int Selection, SectionKind K) : MCSection(SV_COFF, K), SectionName(Section), Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), - Selection(Selection), Assoc(Assoc) { + Selection(Selection) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); - assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == - (Assoc != nullptr) && - "associative COMDAT section must have an associated section"); } ~MCSectionCOFF(); @@ -76,11 +67,10 @@ class MCSymbol; return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } + const MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } int getSelection() const { return Selection; } - const MCSectionCOFF *getAssocSection() const { return Assoc; } - void setSelection(int Selection, - const MCSectionCOFF *Assoc = nullptr) const; + void setSelection(int Selection) const; void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, const MCExpr *Subsection) const override; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 2a8367a..216de75 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -86,6 +86,27 @@ public: virtual void finish(); }; +class AArch64TargetStreamer : public MCTargetStreamer { +public: + AArch64TargetStreamer(MCStreamer &S); + ~AArch64TargetStreamer(); + + + void finish() override; + + /// Callback used to implement the ldr= pseudo. + /// Add a new entry to the constant pool for the current section and return an + /// MCExpr that can be used to refer to the constant pool location. + const MCExpr *addConstantPoolEntry(const MCExpr *); + + /// Callback used to implemnt the .ltorg directive. + /// Emit contents of constant pool for the current section. + void emitCurrentConstantPool(); + +private: + std::unique_ptr ConstantPools; +}; + // FIXME: declared here because it is used from // lib/CodeGen/AsmPrinter/ARMException.cpp. class ARMTargetStreamer : public MCTargetStreamer { @@ -164,8 +185,6 @@ class MCStreamer { void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); void EnsureValidW64UnwindInfo(); - MCSymbol *LastSymbol; - // SymbolOrdering - Tracks an index to represent the order // a symbol was emitted in. Zero means we did not emit that symbol. DenseMap SymbolOrdering; @@ -182,9 +201,7 @@ protected: const MCExpr *ForceExpAbs(const MCExpr *Expr); - void RecordProcStart(MCDwarfFrameInfo &Frame); virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - void RecordProcEnd(MCDwarfFrameInfo &Frame); virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); MCWin64EHUnwindInfo *getCurrentW64UnwindInfo() { @@ -197,6 +214,9 @@ protected: public: virtual ~MCStreamer(); + void visitUsedExpr(const MCExpr &Expr); + virtual void visitUsedSymbol(const MCSymbol &Sym); + void setTargetStreamer(MCTargetStreamer *TS) { TargetStreamer.reset(TS); } @@ -223,6 +243,10 @@ public: return *W64UnwindInfos[i]; } + ArrayRef getW64UnwindInfos() const { + return W64UnwindInfos; + } + void generateCompactUnwindEncodings(MCAsmBackend *MAB); /// @name Assembly File Formatting. @@ -294,7 +318,7 @@ public: /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; + virtual void ChangeSection(const MCSection *, const MCExpr *); /// pushSection - Save the current and previous section on the /// section stack. @@ -374,12 +398,10 @@ public: // add the section we're emitting it to later. virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); /// EmitAssemblerFlag - Note in the output the specified @p Flag. - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); /// EmitLinkerOptions - Emit the given list @p Options of strings as linker /// options into the output. @@ -394,7 +416,7 @@ public: /// EmitThumbFunc - Note in the output that the specified @p Func is /// a Thumb mode function (ARM target only). - virtual void EmitThumbFunc(MCSymbol *Func) = 0; + virtual void EmitThumbFunc(MCSymbol *Func); /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. /// @@ -416,7 +438,7 @@ public: /// /// @param Alias - The alias that is being created. /// @param Symbol - The symbol being aliased. - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. virtual bool EmitSymbolAttribute(MCSymbol *Symbol, @@ -426,25 +448,25 @@ public: /// /// @param Symbol - The symbol to have its n_desc field set. /// @param DescValue - The value to set into the n_desc field. - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); /// BeginCOFFSymbolDef - Start emitting COFF symbol definition /// /// @param Symbol - The symbol to have its External & Type fields set. - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. /// /// @param StorageClass - The storage class the symbol should have. - virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; + virtual void EmitCOFFSymbolStorageClass(int StorageClass); /// EmitCOFFSymbolType - Emit the type of the symbol. /// /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) - virtual void EmitCOFFSymbolType(int Type) = 0; + virtual void EmitCOFFSymbolType(int Type); /// EndCOFFSymbolDef - Marks the end of the symbol definition. - virtual void EndCOFFSymbolDef() = 0; + virtual void EndCOFFSymbolDef(); /// EmitCOFFSectionIndex - Emits a COFF section index. /// @@ -461,7 +483,7 @@ public: /// This corresponds to an assembler statement such as: /// .size symbol, expression /// - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); /// \brief Emit a Linker Optimization Hint (LOH) directive. /// \param Args - Arguments of the LOH. @@ -482,7 +504,7 @@ public: /// @param Size - The size of the common symbol. /// @param ByteAlignment - The alignment of the common symbol in bytes. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; + unsigned ByteAlignment); /// EmitZerofill - Emit the zerofill section and an optional symbol. /// @@ -503,7 +525,7 @@ public: /// @param ByteAlignment - The alignment of the thread local common symbol /// if non-zero. This must be a power of 2 on some targets. virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) = 0; + uint64_t Size, unsigned ByteAlignment = 0); /// @} /// @name Generating Data @@ -513,7 +535,7 @@ public: /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. - virtual void EmitBytes(StringRef Data) = 0; + virtual void EmitBytes(StringRef Data); /// EmitValue - Emit the expression @p Value into the output as a native /// integer of the given @p Size bytes. @@ -526,7 +548,7 @@ public: /// match a native machine width. /// @param Loc - The location of the expression for error reporting. virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - const SMLoc &Loc = SMLoc()) = 0; + const SMLoc &Loc = SMLoc()); void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); @@ -541,9 +563,9 @@ public: /// .long foo void EmitAbsValue(const MCExpr *Value, unsigned Size); - virtual void EmitULEB128Value(const MCExpr *Value) = 0; + virtual void EmitULEB128Value(const MCExpr *Value); - virtual void EmitSLEB128Value(const MCExpr *Value) = 0; + virtual void EmitSLEB128Value(const MCExpr *Value); /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. @@ -598,7 +620,7 @@ public: /// emitted. virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) = 0; + unsigned MaxBytesToEmit = 0); /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment /// is reached. @@ -612,7 +634,7 @@ public: /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) = 0; + unsigned MaxBytesToEmit = 0); /// EmitValueToOffset - Emit some number of copies of @p Value until the /// byte offset @p Offset is reached. @@ -624,13 +646,13 @@ public: /// @param Value - The value to use when filling bytes. /// @return false on success, true if the offset was invalid. virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) = 0; + unsigned char Value = 0); /// @} /// EmitFileDirective - Switch to a new logical file. This is used to /// implement the '.file "foo.c"' assembler directive. - virtual void EmitFileDirective(StringRef Filename) = 0; + virtual void EmitFileDirective(StringRef Filename); /// Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. @@ -677,38 +699,38 @@ public: virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); virtual void EmitCFIWindowSave(); - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); + virtual void EmitWinCFIStartProc(const MCSymbol *Symbol); + virtual void EmitWinCFIEndProc(); + virtual void EmitWinCFIStartChained(); + virtual void EmitWinCFIEndChained(); + virtual void EmitWinCFIPushReg(unsigned Register); + virtual void EmitWinCFISetFrame(unsigned Register, unsigned Offset); + virtual void EmitWinCFIAllocStack(unsigned Size); + virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset); + virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset); + virtual void EmitWinCFIPushFrame(bool Code); + virtual void EmitWinCFIEndProlog(); + + virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); + virtual void EmitWinEHHandlerData(); /// EmitInstruction - Emit the given @p Instruction into the current /// section. - virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) = 0; + virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// \brief Set the bundle alignment mode from now on in the section. /// The argument is the power of 2 to which the alignment is set. The /// value 0 means turn the bundle alignment off. - virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; + virtual void EmitBundleAlignMode(unsigned AlignPow2); /// \brief The following instructions are a bundle-locked group. /// /// \param AlignToEnd - If true, the bundle-locked group will be aligned to /// the end of a bundle. - virtual void EmitBundleLock(bool AlignToEnd) = 0; + virtual void EmitBundleLock(bool AlignToEnd); /// \brief Ends a bundle-locked group. - virtual void EmitBundleUnlock() = 0; + virtual void EmitBundleUnlock(); /// EmitRawText - If this file is backed by a assembly streamer, this dumps /// the specified string in the output .s file. This capability is @@ -719,9 +741,11 @@ public: virtual void Flush() {} /// FinishImpl - Streamer specific finalization. - virtual void FinishImpl() = 0; + virtual void FinishImpl(); /// Finish - Finish emission of machine code. void Finish(); + + virtual bool mayHaveInstructions() const { return true; } }; /// createNullStreamer - Create a dummy machine code streamer, which does diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 18ef6c2..384cc1b 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -14,6 +14,8 @@ #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" +#include + namespace llvm { class AsmToken; class MCInst; @@ -23,6 +25,8 @@ class SMLoc; class StringRef; template class SmallVectorImpl; +typedef SmallVectorImpl> OperandVector; + enum AsmRewriteKind { AOK_Delete = 0, // Rewrite should be ignored. AOK_Align, // Rewrite align as .align. @@ -131,8 +135,7 @@ public: /// ownership of them to the caller. /// \return True on failure. virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, - SMLoc NameLoc, - SmallVectorImpl &Operands) = 0; + SMLoc NameLoc, OperandVector &Operands) = 0; /// ParseDirective - Parse a target specific assembler directive /// @@ -156,17 +159,16 @@ public: /// /// On failure, the target parser is responsible for emitting a diagnostic /// explaining the match failure. - virtual bool - MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - SmallVectorImpl &Operands, - MCStreamer &Out, unsigned &ErrorInfo, - bool MatchingInlineAsm) = 0; + virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + unsigned &ErrorInfo, + bool MatchingInlineAsm) = 0; /// Allow a target to add special case operand matching for things that /// tblgen doesn't/can't handle effectively. For example, literal /// immediates on ARM. TableGen expects a token operand, but the parser /// will recognize them as immediates. - virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op, + virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) { return Match_InvalidOperand; } @@ -178,7 +180,7 @@ public: } virtual void convertToMapAndConstraints(unsigned Kind, - const SmallVectorImpl &Operands) = 0; + const OperandVector &Operands) = 0; virtual const MCExpr *applyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind, diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index 80cc8be..eb4348e 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -29,6 +29,7 @@ public: bool ShowMCEncoding : 1; bool ShowMCInst : 1; bool AsmVerbose : 1; + int DwarfVersion; MCTargetOptions(); }; @@ -41,7 +42,8 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(MCUseDwarfDirectory) && ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && - ARE_EQUAL(AsmVerbose)); + ARE_EQUAL(AsmVerbose) && + ARE_EQUAL(DwarfVersion)); #undef ARE_EQUAL } diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index 17a117a..6d4eb0e 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -33,11 +33,20 @@ cl::opt RelaxAll("mc-relax-all", cl::desc("When used with filetype=obj, " "relax all fixups in the emitted object file")); +cl::opt DwarfVersion("dwarf-version", cl::desc("Dwarf version"), + cl::init(0)); + +cl::opt ShowMCInst("asm-show-inst", + cl::desc("Emit internal instruction representation to " + "assembly file")); + static inline MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; Options.SanitizeAddress = (AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress); Options.MCRelaxAll = RelaxAll; + Options.DwarfVersion = DwarfVersion; + Options.ShowMCInst = ShowMCInst; return Options; } diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 34e39bb..7d2d0e4 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -35,7 +35,6 @@ public: void InitSections() override; void EmitLabel(MCSymbol *Symbol) override; - void EmitDebugLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; @@ -57,7 +56,7 @@ public: unsigned ByteAlignment) override; void EmitFileDirective(StringRef Filename) override; void EmitIdent(StringRef IdentString) override; - void EmitWin64EHHandlerData() override; + void EmitWinEHHandlerData() override; void FinishImpl() override; /// \} diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h new file mode 100644 index 0000000..065e9e0 --- /dev/null +++ b/include/llvm/MC/StringTableBuilder.h @@ -0,0 +1,59 @@ +//===-- StringTableBuilder.h - String table building utility ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_STRINGTABLE_BUILDER_H +#define LLVM_MC_STRINGTABLE_BUILDER_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include + +namespace llvm { + +/// \brief Utility for building string tables with deduplicated suffixes. +class StringTableBuilder { + SmallString<256> StringTable; + StringMap StringIndexMap; + +public: + /// \brief Add a string to the builder. Returns a StringRef to the internal + /// copy of s. Can only be used before the table is finalized. + StringRef add(StringRef s) { + assert(!isFinalized()); + return StringIndexMap.GetOrCreateValue(s, 0).getKey(); + } + + /// \brief Analyze the strings and build the final table. No more strings can + /// be added after this point. + void finalize(); + + /// \brief Retrieve the string table data. Can only be used after the table + /// is finalized. + StringRef data() { + assert(isFinalized()); + return StringTable; + } + + /// \brief Get the offest of a string in the string table. Can only be used + /// after the table is finalized. + size_t getOffset(StringRef s) { + assert(isFinalized()); + assert(StringIndexMap.count(s) && "String is not in table!"); + return StringIndexMap[s]; + } + +private: + bool isFinalized() { + return !StringTable.empty(); + } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/MC/YAML.h b/include/llvm/MC/YAML.h new file mode 100644 index 0000000..383cdc6 --- /dev/null +++ b/include/llvm/MC/YAML.h @@ -0,0 +1,94 @@ +#ifndef LLVM_MC_YAML_H +#define LLVM_MC_YAML_H + +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace yaml { +/// \brief Specialized YAMLIO scalar type for representing a binary blob. +/// +/// A typical use case would be to represent the content of a section in a +/// binary file. +/// This class has custom YAMLIO traits for convenient reading and writing. +/// It renders as a string of hex digits in a YAML file. +/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not +/// require the quotation marks, so for simplicity when outputting they are +/// omitted). +/// When reading, any string whose content is an even number of hex digits +/// will be accepted. +/// For example, all of the following are acceptable: +/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D') +/// +/// A significant advantage of using this class is that it never allocates +/// temporary strings or buffers for any of its functionality. +/// +/// Example: +/// +/// The YAML mapping: +/// \code +/// Foo: DEADBEEFCAFEBABE +/// \endcode +/// +/// Could be modeled in YAMLIO by the struct: +/// \code +/// struct FooHolder { +/// BinaryRef Foo; +/// }; +/// namespace llvm { +/// namespace yaml { +/// template <> +/// struct MappingTraits { +/// static void mapping(IO &IO, FooHolder &FH) { +/// IO.mapRequired("Foo", FH.Foo); +/// } +/// }; +/// } // end namespace yaml +/// } // end namespace llvm +/// \endcode +class BinaryRef { + friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS); + /// \brief Either raw binary data, or a string of hex bytes (must always + /// be an even number of characters). + ArrayRef Data; + /// \brief Discriminator between the two states of the `Data` member. + bool DataIsHexString; + +public: + BinaryRef(ArrayRef Data) : Data(Data), DataIsHexString(false) {} + BinaryRef(StringRef Data) + : Data(reinterpret_cast(Data.data()), Data.size()), + DataIsHexString(true) {} + BinaryRef() : DataIsHexString(true) {} + /// \brief The number of bytes that are represented by this BinaryRef. + /// This is the number of bytes that writeAsBinary() will write. + ArrayRef::size_type binary_size() const { + if (DataIsHexString) + return Data.size() / 2; + return Data.size(); + } + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as binary to the given raw_ostream. + void writeAsBinary(raw_ostream &OS) const; + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as hex to the given raw_ostream. + /// + /// For example, a possible output could be `DEADBEEFCAFEBABE`. + void writeAsHex(raw_ostream &OS) const; +}; + +inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) { + // Special case for default constructed BinaryRef. + if (LHS.Data.empty() && RHS.Data.empty()) + return true; + + return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data; +} + +template <> struct ScalarTraits { + static void output(const BinaryRef &, void *, llvm::raw_ostream &); + static StringRef input(StringRef, void *, BinaryRef &); + static bool mustQuote(StringRef S) { return needsQuotes(S); } +}; +} +} +#endif diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 652b659..af6c995 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -72,7 +72,7 @@ public: Child getNext() const; - error_code getName(StringRef &Result) const; + ErrorOr getName() const; StringRef getRawName() const { return getHeader()->getName(); } sys::TimeValue getLastModified() const { return getHeader()->getLastModified(); @@ -89,11 +89,11 @@ public: return StringRef(Data.data() + StartOfFile, getSize()); } - error_code getMemoryBuffer(std::unique_ptr &Result, - bool FullPath = false) const; + ErrorOr> + getMemoryBuffer(bool FullPath = false) const; - error_code getAsBinary(std::unique_ptr &Result, - LLVMContext *Context = nullptr) const; + ErrorOr> + getAsBinary(LLVMContext *Context = nullptr) const; }; class child_iterator { @@ -137,8 +137,8 @@ public: : Parent(p) , SymbolIndex(symi) , StringIndex(stri) {} - error_code getName(StringRef &Result) const; - error_code getMember(child_iterator &Result) const; + StringRef getName() const; + ErrorOr getMember() const; Symbol getNext() const; }; @@ -164,8 +164,8 @@ public: } }; - Archive(MemoryBuffer *source, error_code &ec); - static ErrorOr create(MemoryBuffer *Source); + Archive(std::unique_ptr Source, std::error_code &EC); + static ErrorOr create(std::unique_ptr Source); enum Kind { K_GNU, diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 8ac84e7..9be2fbe 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -32,12 +32,11 @@ private: Binary(const Binary &other) LLVM_DELETED_FUNCTION; unsigned int TypeID; - bool BufferOwned; protected: - MemoryBuffer *Data; + std::unique_ptr Data; - Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); + Binary(unsigned int Type, std::unique_ptr Source); enum { ID_Archive, @@ -79,6 +78,7 @@ public: virtual ~Binary(); StringRef getData() const; + MemoryBuffer *releaseBuffer() { return Data.release(); } StringRef getFileName() const; // Cast methods. @@ -128,7 +128,7 @@ public: /// @param Source The data to create the Binary from. Ownership is transferred /// to the Binary if successful. If an error is returned, /// Source is destroyed by createBinary before returning. -ErrorOr createBinary(MemoryBuffer *Source, +ErrorOr createBinary(std::unique_ptr &Source, LLVMContext *Context = nullptr); ErrorOr createBinary(StringRef Path); diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index bd9c677..e2da070 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -353,65 +353,74 @@ private: uint32_t NumberOfImportDirectory; const export_directory_table_entry *ExportDirectory; - error_code getString(uint32_t offset, StringRef &Res) const; + std::error_code getString(uint32_t offset, StringRef &Res) const; const coff_symbol *toSymb(DataRefImpl Symb) const; const coff_section *toSec(DataRefImpl Sec) const; const coff_relocation *toRel(DataRefImpl Rel) const; - error_code initSymbolTablePtr(); - error_code initImportTablePtr(); - error_code initExportTablePtr(); + std::error_code initSymbolTablePtr(); + std::error_code initImportTablePtr(); + std::error_code initExportTablePtr(); protected: void moveSymbolNext(DataRefImpl &Symb) const override; - error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; - error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; - error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const override; + std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const override; + std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const override; - error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const override; + std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; void moveSectionNext(DataRefImpl &Sec) const override; - error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; - error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; - error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; - error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; - error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const override; + std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; - error_code + std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const override; - error_code + std::error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const override; - error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const override; - error_code getLibraryPath(DataRefImpl LibData, - StringRef &Result) const override; + std::error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const override; + std::error_code getLibraryPath(DataRefImpl LibData, + StringRef &Result) const override; public: - COFFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); + COFFObjectFile(std::unique_ptr Object, std::error_code &EC); basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; library_iterator needed_library_begin() const override; @@ -433,30 +442,33 @@ public: export_directory_iterator export_directory_begin() const; export_directory_iterator export_directory_end() const; - error_code getHeader(const coff_file_header *&Res) const; - error_code getCOFFHeader(const coff_file_header *&Res) const; - error_code getPE32Header(const pe32_header *&Res) const; - error_code getPE32PlusHeader(const pe32plus_header *&Res) const; - error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; - error_code getSection(int32_t index, const coff_section *&Res) const; - error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; + std::error_code getHeader(const coff_file_header *&Res) const; + std::error_code getCOFFHeader(const coff_file_header *&Res) const; + std::error_code getPE32Header(const pe32_header *&Res) const; + std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; + std::error_code getDataDirectory(uint32_t index, + const data_directory *&Res) const; + std::error_code getSection(int32_t index, const coff_section *&Res) const; + std::error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; template - error_code getAuxSymbol(uint32_t index, const T *&Res) const { + std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { const coff_symbol *s; - error_code ec = getSymbol(index, s); + std::error_code ec = getSymbol(index, s); Res = reinterpret_cast(s); return ec; } - error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; + std::error_code getSymbolName(const coff_symbol *symbol, + StringRef &Res) const; ArrayRef getSymbolAuxData(const coff_symbol *symbol) const; - error_code getSectionName(const coff_section *Sec, StringRef &Res) const; - error_code getSectionContents(const coff_section *Sec, - ArrayRef &Res) const; + std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; + std::error_code getSectionContents(const coff_section *Sec, + ArrayRef &Res) const; - error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; - error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; - error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; + std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + std::error_code getHintName(uint32_t Rva, uint16_t &Hint, + StringRef &Name) const; static inline bool classof(const Binary *v) { return v->isCOFF(); } }; @@ -471,12 +483,12 @@ public: bool operator==(const ImportDirectoryEntryRef &Other) const; void moveNext(); - error_code getName(StringRef &Result) const; + std::error_code getName(StringRef &Result) const; - error_code + std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; - error_code + std::error_code getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; private: @@ -496,11 +508,11 @@ public: bool operator==(const ExportDirectoryEntryRef &Other) const; void moveNext(); - error_code getDllName(StringRef &Result) const; - error_code getOrdinalBase(uint32_t &Result) const; - error_code getOrdinal(uint32_t &Result) const; - error_code getExportRVA(uint32_t &Result) const; - error_code getSymbolName(StringRef &Result) const; + std::error_code getDllName(StringRef &Result) const; + std::error_code getOrdinalBase(uint32_t &Result) const; + std::error_code getOrdinal(uint32_t &Result) const; + std::error_code getExportRVA(uint32_t &Result) const; + std::error_code getSymbolName(StringRef &Result) const; private: const export_directory_table_entry *ExportTable; diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h index 3f48e07..4aba08f 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -15,7 +15,7 @@ #define LLVM_OBJECT_COFFYAML_H #include "llvm/ADT/Optional.h" -#include "llvm/Object/YAML.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/COFF.h" namespace llvm { @@ -49,7 +49,7 @@ namespace COFFYAML { struct Section { COFF::section Header; unsigned Alignment; - object::yaml::BinaryRef SectionData; + yaml::BinaryRef SectionData; std::vector Relocations; StringRef Name; Section(); diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index ee97d4e..fbc48e6 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -40,11 +40,12 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); // Subclasses of ELFFile may need this for template instantiation inline std::pair -getElfArchType(MemoryBuffer *Object) { - if (Object->getBufferSize() < ELF::EI_NIDENT) - return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], - (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); +getElfArchType(StringRef Object) { + if (Object.size() < ELF::EI_NIDENT) + return std::make_pair((uint8_t)ELF::ELFCLASSNONE, + (uint8_t)ELF::ELFDATANONE); + return std::make_pair((uint8_t)Object[ELF::EI_CLASS], + (uint8_t)Object[ELF::EI_DATA]); } template @@ -133,6 +134,7 @@ public: typedef Elf_Vernaux_Impl Elf_Vernaux; typedef Elf_Versym_Impl Elf_Versym; typedef ELFEntityIterator Elf_Dyn_Iter; + typedef iterator_range Elf_Dyn_Range; typedef ELFEntityIterator Elf_Rela_Iter; typedef ELFEntityIterator Elf_Rel_Iter; typedef ELFEntityIterator Elf_Shdr_Iter; @@ -229,10 +231,10 @@ private: typedef SmallVector Sections_t; typedef DenseMap IndexMap_t; - MemoryBuffer *Buf; + StringRef Buf; const uint8_t *base() const { - return reinterpret_cast(Buf->getBufferStart()); + return reinterpret_cast(Buf.data()); } const Elf_Ehdr *Header; @@ -316,7 +318,7 @@ public: std::pair getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; - ELFFile(MemoryBuffer *Object, error_code &ec); + ELFFile(StringRef Object, std::error_code &ec); bool isMipsELF64() const { return Header->e_machine == ELF::EM_MIPS && @@ -342,6 +344,9 @@ public: /// \param NULLEnd use one past the first DT_NULL entry as the end instead of /// the section size. Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; + Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const { + return make_range(begin_dynamic_table(), end_dynamic_table(NULLEnd)); + } Elf_Sym_Iter begin_dynamic_symbols() const { if (DynSymRegion.Addr) @@ -532,7 +537,7 @@ ELFFile::getSymbol(uint32_t Index) const { template ErrorOr > ELFFile::getSectionContents(const Elf_Shdr *Sec) const { - if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) + if (Sec->sh_offset + Sec->sh_size > Buf.size()) return object_error::parse_failed; const uint8_t *Start = base() + Sec->sh_offset; return ArrayRef(Start, Sec->sh_size); @@ -598,7 +603,7 @@ void ELFFile::VerifyStrTab(const Elf_Shdr *sh) const { template uint64_t ELFFile::getNumSections() const { assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shnum == ELF::SHN_UNDEF && Header->e_shoff > 0) { assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); return SectionHeaderTable->sh_size; } @@ -617,18 +622,13 @@ typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { } template -ELFFile::ELFFile(MemoryBuffer *Object, error_code &ec) - : Buf(Object), - SectionHeaderTable(nullptr), - dot_shstrtab_sec(nullptr), - dot_strtab_sec(nullptr), - dot_symtab_sec(nullptr), - SymbolTableSectionHeaderIndex(nullptr), - dot_gnu_version_sec(nullptr), - dot_gnu_version_r_sec(nullptr), - dot_gnu_version_d_sec(nullptr), +ELFFile::ELFFile(StringRef Object, std::error_code &ec) + : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr), + dot_strtab_sec(nullptr), dot_symtab_sec(nullptr), + SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr), + dot_gnu_version_r_sec(nullptr), dot_gnu_version_d_sec(nullptr), dt_soname(nullptr) { - const uint64_t FileSize = Buf->getBufferSize(); + const uint64_t FileSize = Buf.size(); if (sizeof(Elf_Ehdr) > FileSize) // FIXME: Proper error handling. @@ -744,7 +744,7 @@ ELFFile::ELFFile(MemoryBuffer *Object, error_code &ec) } } - ec = error_code::success(); + ec = std::error_code(); } // Get the symbol table index in the symtab section given a symbol @@ -823,17 +823,13 @@ ELFFile::end_dynamic_table(bool NULLEnd) const { template StringRef ELFFile::getLoadName() const { if (!dt_soname) { + dt_soname = ""; // Find the DT_SONAME entry - Elf_Dyn_Iter it = begin_dynamic_table(); - Elf_Dyn_Iter ie = end_dynamic_table(); - while (it != ie && it->getTag() != ELF::DT_SONAME) - ++it; - - if (it != ie) { - dt_soname = getDynamicString(it->getVal()); - } else { - dt_soname = ""; - } + for (const auto &Entry : dynamic_table()) + if (Entry.getTag() == ELF::DT_SONAME) { + dt_soname = getDynamicString(Entry.getVal()); + break; + } } return dt_soname; } diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 302caba..cfb6b08 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -57,50 +57,63 @@ protected: ELFFile EF; void moveSymbolNext(DataRefImpl &Symb) const override; - error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; - error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; - error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; - error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const override; + std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const override; + std::error_code getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const override; + std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const override; - error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const override; + std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; - error_code getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const override; - error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const override; + std::error_code getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const override; + std::error_code getLibraryPath(DataRefImpl Data, + StringRef &Res) const override; void moveSectionNext(DataRefImpl &Sec) const override; - error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; - error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; - error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; - error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; - error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const override; + std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; section_iterator getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; - error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; + std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; + std::error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const override; uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -164,7 +177,7 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); + ELFObjectFile(std::unique_ptr Object, std::error_code &EC); const Elf_Sym *getSymbol(DataRefImpl Symb) const; @@ -180,10 +193,9 @@ public: library_iterator needed_library_begin() const override; library_iterator needed_library_end() const override; - error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; - error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; - + std::error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; @@ -212,8 +224,8 @@ void ELFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { } template -error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { +std::error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); if (!Name) return Name.getError(); @@ -222,9 +234,9 @@ error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, } template -error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { +std::error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { DataRefImpl Symb = SymRef.getRawDataRefImpl(); const Elf_Sym *symb = getSymbol(Symb); ErrorOr Ver = @@ -236,8 +248,8 @@ error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, } template -error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { +std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); switch (EF.getSymbolTableIndex(ESym)) { case ELF::SHN_COMMON: @@ -265,8 +277,8 @@ error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, } template -error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { +std::error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { Elf_Sym_Iter Sym = toELFSymIter(Symb); if (Sym->st_shndx == ELF::SHN_COMMON) Res = Sym->st_value; @@ -276,15 +288,16 @@ error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, } template -error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { +std::error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { Result = toELFSymIter(Symb)->st_size; return object_error::success; } template -error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +std::error_code +ELFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { @@ -343,8 +356,9 @@ uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { } template -error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { +std::error_code +ELFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { const Elf_Sym *ESym = getSymbol(Symb); const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) @@ -363,8 +377,8 @@ void ELFObjectFile::moveSectionNext(DataRefImpl &Sec) const { } template -error_code ELFObjectFile::getSectionName(DataRefImpl Sec, - StringRef &Result) const { +std::error_code ELFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); if (!Name) return Name.getError(); @@ -373,44 +387,46 @@ error_code ELFObjectFile::getSectionName(DataRefImpl Sec, } template -error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { +std::error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_addr; return object_error::success; } template -error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { +std::error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_size; return object_error::success; } template -error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { +std::error_code +ELFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); return object_error::success; } template -error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { +std::error_code +ELFObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_addralign; return object_error::success; } template -error_code ELFObjectFile::isSectionText(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; return object_error::success; } template -error_code ELFObjectFile::isSectionData(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_PROGBITS; @@ -418,8 +434,8 @@ error_code ELFObjectFile::isSectionData(DataRefImpl Sec, } template -error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_NOBITS; @@ -427,7 +443,7 @@ error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, } template -error_code +std::error_code ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, bool &Result) const { Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; @@ -435,31 +451,31 @@ ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, } template -error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; return object_error::success; } template -error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; return object_error::success; } template -error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); return object_error::success; } template -error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +std::error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); uintX_t Index = ESym->st_shndx; @@ -553,8 +569,9 @@ ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { } template -error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { +std::error_code +ELFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { uint64_t ROffset = getROffset(Rel); const Elf_Ehdr *Header = EF.getHeader(); @@ -570,8 +587,9 @@ error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, } template -error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { +std::error_code +ELFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); Result = getROffset(Rel); @@ -592,8 +610,8 @@ uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { } template -error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { +std::error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default: @@ -616,7 +634,7 @@ StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { } template -error_code ELFObjectFile::getRelocationTypeName( +std::error_code ELFObjectFile::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl &Result) const { const Elf_Shdr *sec = getRelSection(Rel); uint32_t type; @@ -638,8 +656,9 @@ error_code ELFObjectFile::getRelocationTypeName( } template -error_code ELFObjectFile::getRelocationAddend(DataRefImpl Rel, - int64_t &Result) const { +std::error_code +ELFObjectFile::getRelocationAddend(DataRefImpl Rel, + int64_t &Result) const { const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default: @@ -656,7 +675,7 @@ error_code ELFObjectFile::getRelocationAddend(DataRefImpl Rel, } template -error_code ELFObjectFile::getRelocationValueString( +std::error_code ELFObjectFile::getRelocationValueString( DataRefImpl Rel, SmallVectorImpl &Result) const { const Elf_Shdr *sec = getRelSection(Rel); uint8_t type; @@ -754,13 +773,13 @@ ELFObjectFile::getRela(DataRefImpl Rela) const { } template -ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec, - bool BufferOwned) +ELFObjectFile::ELFObjectFile(std::unique_ptr Object, + std::error_code &EC) : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object, BufferOwned), - EF(Object, ec) {} + std::move(Object)), + EF(Data->getBuffer(), EC) {} template basic_symbol_iterator ELFObjectFile::symbol_begin_impl() const { @@ -817,8 +836,8 @@ library_iterator ELFObjectFile::needed_library_begin() const { } template -error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { +std::error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { Elf_Dyn_Iter DI = toELFDynIter(Data); Elf_Dyn_Iter DE = EF.end_dynamic_table(); @@ -832,8 +851,8 @@ error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, } template -error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { +std::error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); return object_error::success; } @@ -898,6 +917,7 @@ StringRef ELFObjectFile::getFileFormatName() const { template unsigned ELFObjectFile::getArch() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_machine) { case ELF::EM_386: return Triple::x86; @@ -910,11 +930,16 @@ unsigned ELFObjectFile::getArch() const { case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: - return (ELFT::TargetEndianness == support::little) ? Triple::mipsel - : Triple::mips; + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + return IsLittleEndian ? Triple::mipsel : Triple::mips; + case ELF::ELFCLASS64: + return IsLittleEndian ? Triple::mips64el : Triple::mips64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } case ELF::EM_PPC64: - return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le - : Triple::ppc64; + return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; @@ -931,8 +956,8 @@ unsigned ELFObjectFile::getArch() const { /// FIXME: Maybe we should have a base ElfObjectFile that is not a template /// and make these member functions? -inline error_code getELFRelocationAddend(const RelocationRef R, - int64_t &Addend) { +inline std::error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); // Little-endian 32-bit @@ -975,9 +1000,10 @@ getELFDynamicSymbolIterators(SymbolicFile *Obj) { /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. -inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, StringRef &Version, - bool &IsDefault) { +inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, + StringRef &Version, + bool &IsDefault) { // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 524e55b..fc8cc95 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -16,7 +16,7 @@ #ifndef LLVM_OBJECT_ELFYAML_H #define LLVM_OBJECT_ELFYAML_H -#include "llvm/Object/YAML.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/ELF.h" namespace llvm { @@ -44,6 +44,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. @@ -62,6 +63,7 @@ struct Symbol { StringRef Section; llvm::yaml::Hex64 Value; llvm::yaml::Hex64 Size; + ELF_STV Visibility; }; struct LocalGlobalWeakSymbols { std::vector Local; @@ -76,13 +78,12 @@ struct Section { ELF_SHF Flags; llvm::yaml::Hex64 Address; StringRef Link; - StringRef Info; llvm::yaml::Hex64 AddressAlign; Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); }; struct RawContentSection : Section { - object::yaml::BinaryRef Content; + yaml::BinaryRef Content; llvm::yaml::Hex64 Size; RawContentSection() : Section(SectionKind::RawContent) {} static bool classof(const Section *S) { @@ -96,6 +97,7 @@ struct Relocation { StringRef Symbol; }; struct RelocationSection : Section { + StringRef Info; std::vector Relocations; RelocationSection() : Section(SectionKind::Relocation) {} static bool classof(const Section *S) { @@ -168,6 +170,11 @@ struct ScalarEnumerationTraits { }; template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_STV &Value); +}; + +template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 779c747..701da12 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -14,38 +14,32 @@ #ifndef LLVM_OBJECT_ERROR_H #define LLVM_OBJECT_ERROR_H -#include "llvm/Support/system_error.h" +#include namespace llvm { namespace object { -const error_category &object_category(); +const std::error_category &object_category(); -struct object_error { - enum Impl { - success = 0, - arch_not_found, - invalid_file_type, - parse_failed, - unexpected_eof - }; - Impl V; - - object_error(Impl V) : V(V) {} - operator Impl() const { return V; } +enum class object_error { + success = 0, + arch_not_found, + invalid_file_type, + parse_failed, + unexpected_eof }; -inline error_code make_error_code(object_error e) { - return error_code(static_cast(e), object_category()); +inline std::error_code make_error_code(object_error e) { + return std::error_code(static_cast(e), object_category()); } } // end namespace object. -template <> struct is_error_code_enum : std::true_type {}; +} // end namespace llvm. +namespace std { template <> -struct is_error_code_enum : std::true_type {}; - -} // end namespace llvm. +struct is_error_code_enum : std::true_type {}; +} #endif diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 78f5b2b..b33cc26 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -25,20 +25,33 @@ namespace object { class IRObjectFile : public SymbolicFile { std::unique_ptr M; std::unique_ptr Mang; + std::vector> AsmSymbols; public: - IRObjectFile(MemoryBuffer *Object, error_code &EC, LLVMContext &Context, - bool BufferOwned); + IRObjectFile(std::unique_ptr Object, std::unique_ptr M); + ~IRObjectFile(); void moveSymbolNext(DataRefImpl &Symb) const override; - error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - const GlobalValue &getSymbolGV(DataRefImpl Symb) const; + const GlobalValue *getSymbolGV(DataRefImpl Symb) const; basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; + const Module &getModule() const { + return const_cast(this)->getModule(); + } + Module &getModule() { + return *M; + } + static inline bool classof(const Binary *v) { return v->isIR(); } + + static ErrorOr + createIRObjectFile(std::unique_ptr Object, + LLVMContext &Context); }; } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 710ad7e..e93ebb8 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -40,9 +40,9 @@ public: void moveNext(); - error_code getOffset(uint32_t &Result) const; - error_code getLength(uint16_t &Result) const; - error_code getKind(uint16_t &Result) const; + std::error_code getOffset(uint32_t &Result) const; + std::error_code getLength(uint16_t &Result) const; + std::error_code getKind(uint16_t &Result) const; DataRefImpl getRawDataRefImpl() const; const ObjectFile *getObjectFile() const; @@ -56,54 +56,75 @@ public: MachO::load_command C; // The command itself. }; - MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, - error_code &EC, bool BufferOwned = true); + MachOObjectFile(std::unique_ptr Object, bool IsLittleEndian, + bool Is64Bits, std::error_code &EC); void moveSymbolNext(DataRefImpl &Symb) const override; - error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; - error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; - error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; - error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; - error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const override; + std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const override; + + // MachO specific. + std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + + std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const override; + std::error_code getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const override; + std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const override; + std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; void moveSectionNext(DataRefImpl &Sec) const override; - error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; - error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; - error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; - error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; - error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const override; + std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; - error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; + std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; + std::error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const override; + std::error_code getRelocationHidden(DataRefImpl Rel, + bool &Result) const override; + + std::error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const override; + std::error_code getLibraryPath(DataRefImpl LibData, + StringRef &Res) const override; - error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const override; - error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const override; + // MachO specific. + std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res); // TODO: Would be useful to have an iterator based version // of the load command interface too. @@ -180,6 +201,8 @@ public: getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const; + MachO::dylib_command + getDylibIDLoadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -198,15 +221,27 @@ public: bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; + static StringRef guessLibraryShortName(StringRef Name, bool &isFramework, + StringRef &Suffix); + static Triple::ArchType getArch(uint32_t CPUType); + static Triple getArch(uint32_t CPUType, uint32_t CPUSubType); + static Triple getArch(StringRef ArchFlag); + static Triple getHostArch(); static bool classof(const Binary *v) { return v->isMachO(); } + const char *getSectionPointer(DataRefImpl Rel) const; + private: - typedef SmallVector SectionList; + typedef SmallVector SectionList; SectionList Sections; + typedef SmallVector LibraryList; + LibraryList Libraries; + typedef SmallVector LibraryShortName; + LibraryShortName LibrariesShortNames; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; @@ -234,7 +269,7 @@ inline void DiceRef::moveNext() { // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for // the methods that get the values of the fields of the reference. -inline error_code DiceRef::getOffset(uint32_t &Result) const { +inline std::error_code DiceRef::getOffset(uint32_t &Result) const { const MachOObjectFile *MachOOF = static_cast(OwningObject); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); @@ -242,7 +277,7 @@ inline error_code DiceRef::getOffset(uint32_t &Result) const { return object_error::success; } -inline error_code DiceRef::getLength(uint16_t &Result) const { +inline std::error_code DiceRef::getLength(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast(OwningObject); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); @@ -250,7 +285,7 @@ inline error_code DiceRef::getLength(uint16_t &Result) const { return object_error::success; } -inline error_code DiceRef::getKind(uint16_t &Result) const { +inline std::error_code DiceRef::getKind(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast(OwningObject); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index d27c824..e6677f5 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/Object/Binary.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" @@ -52,10 +53,14 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } + std::string getArchTypeName() const { + Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); + return T.getArchName(); + } - error_code getAsObjectFile(std::unique_ptr &Result) const; + ErrorOr> getAsObjectFile() const; - error_code getAsArchive(std::unique_ptr &Result) const; + std::error_code getAsArchive(std::unique_ptr &Result) const; }; class object_iterator { @@ -79,8 +84,10 @@ public: } }; - MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); - static ErrorOr create(MemoryBuffer *Source); + MachOUniversalBinary(std::unique_ptr Source, + std::error_code &ec); + static ErrorOr + create(std::unique_ptr Source); object_iterator begin_objects() const { return ObjectForArch(this, 0); @@ -96,8 +103,8 @@ public: return V->isMachOUniversalBinary(); } - error_code getObjectForArch(Triple::ArchType Arch, - std::unique_ptr &Result) const; + ErrorOr> + getObjectForArch(Triple::ArchType Arch) const; }; } diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 10209b9..646abf8 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -46,26 +46,26 @@ public: void moveNext(); - error_code getAddress(uint64_t &Result) const; - error_code getOffset(uint64_t &Result) const; + std::error_code getAddress(uint64_t &Result) const; + std::error_code getOffset(uint64_t &Result) const; symbol_iterator getSymbol() const; - error_code getType(uint64_t &Result) const; + std::error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing /// relocations, usually because it is the trailing part of a multipart /// relocation that will be printed as part of the leading relocation. - error_code getHidden(bool &Result) const; + std::error_code getHidden(bool &Result) const; /// @brief Get a string that represents the type of this relocation. /// /// This is for display purposes only. - error_code getTypeName(SmallVectorImpl &Result) const; + std::error_code getTypeName(SmallVectorImpl &Result) const; /// @brief Get a string that represents the calculation of the value of this /// relocation. /// /// This is for display purposes only. - error_code getValueString(SmallVectorImpl &Result) const; + std::error_code getValueString(SmallVectorImpl &Result) const; DataRefImpl getRawDataRefImpl() const; const ObjectFile *getObjectFile() const; @@ -92,24 +92,24 @@ public: void moveNext(); - error_code getName(StringRef &Result) const; - error_code getAddress(uint64_t &Result) const; - error_code getSize(uint64_t &Result) const; - error_code getContents(StringRef &Result) const; + std::error_code getName(StringRef &Result) const; + std::error_code getAddress(uint64_t &Result) const; + std::error_code getSize(uint64_t &Result) const; + std::error_code getContents(StringRef &Result) const; /// @brief Get the alignment of this section as the actual value (not log 2). - error_code getAlignment(uint64_t &Result) const; + std::error_code getAlignment(uint64_t &Result) const; // FIXME: Move to the normalization layer when it's created. - error_code isText(bool &Result) const; - error_code isData(bool &Result) const; - error_code isBSS(bool &Result) const; - error_code isRequiredForExecution(bool &Result) const; - error_code isVirtual(bool &Result) const; - error_code isZeroInit(bool &Result) const; - error_code isReadOnlyData(bool &Result) const; + std::error_code isText(bool &Result) const; + std::error_code isData(bool &Result) const; + std::error_code isBSS(bool &Result) const; + std::error_code isRequiredForExecution(bool &Result) const; + std::error_code isVirtual(bool &Result) const; + std::error_code isZeroInit(bool &Result) const; + std::error_code isReadOnlyData(bool &Result) const; - error_code containsSymbol(SymbolRef S, bool &Result) const; + std::error_code containsSymbol(SymbolRef S, bool &Result) const; relocation_iterator relocation_begin() const; relocation_iterator relocation_end() const; @@ -141,18 +141,18 @@ public: SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); - error_code getName(StringRef &Result) const; + std::error_code getName(StringRef &Result) const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). - error_code getAddress(uint64_t &Result) const; + std::error_code getAddress(uint64_t &Result) const; /// @brief Get the alignment of this symbol as the actual value (not log 2). - error_code getAlignment(uint32_t &Result) const; - error_code getSize(uint64_t &Result) const; - error_code getType(SymbolRef::Type &Result) const; + std::error_code getAlignment(uint32_t &Result) const; + std::error_code getSize(uint64_t &Result) const; + std::error_code getType(SymbolRef::Type &Result) const; /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. - error_code getSection(section_iterator &Result) const; + std::error_code getSection(section_iterator &Result) const; const ObjectFile *getObject() const; }; @@ -190,10 +190,10 @@ public: bool operator==(const LibraryRef &Other) const; bool operator<(const LibraryRef &Other) const; - error_code getNext(LibraryRef &Result) const; + std::error_code getNext(LibraryRef &Result) const; // Get the path to this library, as stored in the object file. - error_code getPath(StringRef &Result) const; + std::error_code getPath(StringRef &Result) const; DataRefImpl getRawDataRefImpl() const; }; @@ -208,7 +208,7 @@ class ObjectFile : public SymbolicFile { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); + ObjectFile(unsigned int Type, std::unique_ptr Source); const uint8_t *base() const { return reinterpret_cast(Data->getBufferStart()); @@ -223,35 +223,49 @@ protected: // Implementations assume that the DataRefImpl is valid and has not been // modified externally. It's UB otherwise. friend class SymbolRef; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; - error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const = 0; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const = 0; + virtual std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const = 0; + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; + virtual std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const = 0; + virtual std::error_code getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const; + virtual std::error_code getSymbolSize(DataRefImpl Symb, + uint64_t &Res) const = 0; + virtual std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const = 0; + virtual std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const = 0; // Same as above for SectionRef. friend class SectionRef; virtual void moveSectionNext(DataRefImpl &Sec) const = 0; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res)const=0; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const = 0; + virtual std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const = 0; + virtual std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const = 0; + virtual std::error_code getSectionSize(DataRefImpl Sec, + uint64_t &Res) const = 0; + virtual std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const = 0; + virtual std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const = 0; + virtual std::error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; + virtual std::error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; + virtual std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; + virtual std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const = 0; // A section is 'virtual' if its contents aren't present in the object image. - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const =0; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const = 0; + virtual std::error_code isSectionVirtual(DataRefImpl Sec, + bool &Res) const = 0; + virtual std::error_code isSectionZeroInit(DataRefImpl Sec, + bool &Res) const = 0; + virtual std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const = 0; + virtual std::error_code sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; @@ -259,26 +273,31 @@ protected: // Same as above for RelocationRef. friend class RelocationRef; virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const =0; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const =0; + virtual std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const = 0; + virtual std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const = 0; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const = 0; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const = 0; - virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const { + virtual std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const = 0; + virtual std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const = 0; + virtual std::error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const = 0; + virtual std::error_code getRelocationHidden(DataRefImpl Rel, + bool &Result) const { Result = false; return object_error::success; } // Same for LibraryRef friend class LibraryRef; - virtual error_code getLibraryNext(DataRefImpl Lib, LibraryRef &Res) const = 0; - virtual error_code getLibraryPath(DataRefImpl Lib, StringRef &Res) const = 0; + virtual std::error_code getLibraryNext(DataRefImpl Lib, + LibraryRef &Res) const = 0; + virtual std::error_code getLibraryPath(DataRefImpl Lib, + StringRef &Res) const = 0; public: typedef iterator_range symbol_iterator_range; @@ -314,11 +333,12 @@ public: /// return true. /// @brief Create ObjectFile from path. static ErrorOr createObjectFile(StringRef ObjectPath); - static ErrorOr createObjectFile(MemoryBuffer *Object, - bool BufferOwned, - sys::fs::file_magic Type); - static ErrorOr createObjectFile(MemoryBuffer *Object) { - return createObjectFile(Object, true, sys::fs::file_magic::unknown); + static ErrorOr + createObjectFile(std::unique_ptr &Object, + sys::fs::file_magic Type); + static ErrorOr + createObjectFile(std::unique_ptr &Object) { + return createObjectFile(Object, sys::fs::file_magic::unknown); } @@ -327,39 +347,39 @@ public: } public: - static ErrorOr createCOFFObjectFile(MemoryBuffer *Object, - bool BufferOwned = true); - static ErrorOr createELFObjectFile(MemoryBuffer *Object, - bool BufferOwned = true); - static ErrorOr createMachOObjectFile(MemoryBuffer *Object, - bool BufferOwned = true); + static ErrorOr + createCOFFObjectFile(std::unique_ptr Object); + static ErrorOr + createELFObjectFile(std::unique_ptr &Object); + static ErrorOr + createMachOObjectFile(std::unique_ptr &Object); }; // Inline function definitions. inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) : BasicSymbolRef(SymbolP, Owner) {} -inline error_code SymbolRef::getName(StringRef &Result) const { +inline std::error_code SymbolRef::getName(StringRef &Result) const { return getObject()->getSymbolName(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getAddress(uint64_t &Result) const { +inline std::error_code SymbolRef::getAddress(uint64_t &Result) const { return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getAlignment(uint32_t &Result) const { +inline std::error_code SymbolRef::getAlignment(uint32_t &Result) const { return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getSize(uint64_t &Result) const { +inline std::error_code SymbolRef::getSize(uint64_t &Result) const { return getObject()->getSymbolSize(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getSection(section_iterator &Result) const { +inline std::error_code SymbolRef::getSection(section_iterator &Result) const { return getObject()->getSymbolSection(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getType(SymbolRef::Type &Result) const { +inline std::error_code SymbolRef::getType(SymbolRef::Type &Result) const { return getObject()->getSymbolType(getRawDataRefImpl(), Result); } @@ -391,55 +411,56 @@ inline void SectionRef::moveNext() { return OwningObject->moveSectionNext(SectionPimpl); } -inline error_code SectionRef::getName(StringRef &Result) const { +inline std::error_code SectionRef::getName(StringRef &Result) const { return OwningObject->getSectionName(SectionPimpl, Result); } -inline error_code SectionRef::getAddress(uint64_t &Result) const { +inline std::error_code SectionRef::getAddress(uint64_t &Result) const { return OwningObject->getSectionAddress(SectionPimpl, Result); } -inline error_code SectionRef::getSize(uint64_t &Result) const { +inline std::error_code SectionRef::getSize(uint64_t &Result) const { return OwningObject->getSectionSize(SectionPimpl, Result); } -inline error_code SectionRef::getContents(StringRef &Result) const { +inline std::error_code SectionRef::getContents(StringRef &Result) const { return OwningObject->getSectionContents(SectionPimpl, Result); } -inline error_code SectionRef::getAlignment(uint64_t &Result) const { +inline std::error_code SectionRef::getAlignment(uint64_t &Result) const { return OwningObject->getSectionAlignment(SectionPimpl, Result); } -inline error_code SectionRef::isText(bool &Result) const { +inline std::error_code SectionRef::isText(bool &Result) const { return OwningObject->isSectionText(SectionPimpl, Result); } -inline error_code SectionRef::isData(bool &Result) const { +inline std::error_code SectionRef::isData(bool &Result) const { return OwningObject->isSectionData(SectionPimpl, Result); } -inline error_code SectionRef::isBSS(bool &Result) const { +inline std::error_code SectionRef::isBSS(bool &Result) const { return OwningObject->isSectionBSS(SectionPimpl, Result); } -inline error_code SectionRef::isRequiredForExecution(bool &Result) const { +inline std::error_code SectionRef::isRequiredForExecution(bool &Result) const { return OwningObject->isSectionRequiredForExecution(SectionPimpl, Result); } -inline error_code SectionRef::isVirtual(bool &Result) const { +inline std::error_code SectionRef::isVirtual(bool &Result) const { return OwningObject->isSectionVirtual(SectionPimpl, Result); } -inline error_code SectionRef::isZeroInit(bool &Result) const { +inline std::error_code SectionRef::isZeroInit(bool &Result) const { return OwningObject->isSectionZeroInit(SectionPimpl, Result); } -inline error_code SectionRef::isReadOnlyData(bool &Result) const { +inline std::error_code SectionRef::isReadOnlyData(bool &Result) const { return OwningObject->isSectionReadOnlyData(SectionPimpl, Result); } -inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { +inline std::error_code SectionRef::containsSymbol(SymbolRef S, + bool &Result) const { return OwningObject->sectionContainsSymbol(SectionPimpl, S.getRawDataRefImpl(), Result); } @@ -474,11 +495,11 @@ inline void RelocationRef::moveNext() { return OwningObject->moveRelocationNext(RelocationPimpl); } -inline error_code RelocationRef::getAddress(uint64_t &Result) const { +inline std::error_code RelocationRef::getAddress(uint64_t &Result) const { return OwningObject->getRelocationAddress(RelocationPimpl, Result); } -inline error_code RelocationRef::getOffset(uint64_t &Result) const { +inline std::error_code RelocationRef::getOffset(uint64_t &Result) const { return OwningObject->getRelocationOffset(RelocationPimpl, Result); } @@ -486,21 +507,21 @@ inline symbol_iterator RelocationRef::getSymbol() const { return OwningObject->getRelocationSymbol(RelocationPimpl); } -inline error_code RelocationRef::getType(uint64_t &Result) const { +inline std::error_code RelocationRef::getType(uint64_t &Result) const { return OwningObject->getRelocationType(RelocationPimpl, Result); } -inline error_code RelocationRef::getTypeName(SmallVectorImpl &Result) - const { +inline std::error_code +RelocationRef::getTypeName(SmallVectorImpl &Result) const { return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline error_code RelocationRef::getValueString(SmallVectorImpl &Result) - const { +inline std::error_code +RelocationRef::getValueString(SmallVectorImpl &Result) const { return OwningObject->getRelocationValueString(RelocationPimpl, Result); } -inline error_code RelocationRef::getHidden(bool &Result) const { +inline std::error_code RelocationRef::getHidden(bool &Result) const { return OwningObject->getRelocationHidden(RelocationPimpl, Result); } @@ -525,11 +546,11 @@ inline bool LibraryRef::operator<(const LibraryRef &Other) const { return LibraryPimpl < Other.LibraryPimpl; } -inline error_code LibraryRef::getNext(LibraryRef &Result) const { +inline std::error_code LibraryRef::getNext(LibraryRef &Result) const { return OwningObject->getLibraryNext(LibraryPimpl, Result); } -inline error_code LibraryRef::getPath(StringRef &Result) const { +inline std::error_code LibraryRef::getPath(StringRef &Result) const { return OwningObject->getLibraryPath(LibraryPimpl, Result); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index a3aaf17..5ca2450 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -253,12 +253,14 @@ private: /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); return RelocToApply(Value + Addend, 8); } diff --git a/include/llvm/Object/StringTableBuilder.h b/include/llvm/Object/StringTableBuilder.h deleted file mode 100644 index c61e216..0000000 --- a/include/llvm/Object/StringTableBuilder.h +++ /dev/null @@ -1,59 +0,0 @@ -//===-- StringTableBuilder.h - String table building utility ------*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_STRINGTABLE_BUILDER_H -#define LLVM_OBJECT_STRINGTABLE_BUILDER_H - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringMap.h" -#include - -namespace llvm { - -/// \brief Utility for building string tables with deduplicated suffixes. -class StringTableBuilder { - SmallString<256> StringTable; - StringMap StringIndexMap; - -public: - /// \brief Add a string to the builder. Returns a StringRef to the internal - /// copy of s. Can only be used before the table is finalized. - StringRef add(StringRef s) { - assert(!isFinalized()); - return StringIndexMap.GetOrCreateValue(s, 0).getKey(); - } - - /// \brief Analyze the strings and build the final table. No more strings can - /// be added after this point. - void finalize(); - - /// \brief Retrieve the string table data. Can only be used after the table - /// is finalized. - StringRef data() { - assert(isFinalized()); - return StringTable; - } - - /// \brief Get the offest of a string in the string table. Can only be used - /// after the table is finalized. - size_t getOffset(StringRef s) { - assert(isFinalized()); - assert(StringIndexMap.count(s) && "String is not in table!"); - return StringIndexMap[s]; - } - -private: - bool isFinalized() { - return !StringTable.empty(); - } -}; - -} // end llvm namespace - -#endif diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 28400e1..77eef4a 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -86,7 +86,8 @@ public: SF_Weak = 1U << 2, // Weak symbol SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage - SF_FormatSpecific = 1U << 5 // Specific to the object file format + SF_Indirect = 1U << 5, // Symbol is an alias to another symbol + SF_FormatSpecific = 1U << 6 // Specific to the object file format // (e.g. section symbols) }; @@ -98,7 +99,7 @@ public: void moveNext(); - error_code printName(raw_ostream &OS) const; + std::error_code printName(raw_ostream &OS) const; /// Get symbol flags (bitwise OR of SymbolRef::Flags) uint32_t getFlags() const; @@ -114,13 +115,13 @@ const uint64_t UnknownAddressOrSize = ~0ULL; class SymbolicFile : public Binary { public: virtual ~SymbolicFile(); - SymbolicFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned); + SymbolicFile(unsigned int Type, std::unique_ptr Source); // virtual interface. virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; - virtual error_code printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const = 0; + virtual std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const = 0; virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; @@ -135,20 +136,19 @@ public: basic_symbol_iterator symbol_end() const { return symbol_end_impl(); } + typedef iterator_range basic_symbol_iterator_range; + basic_symbol_iterator_range symbols() const { + return basic_symbol_iterator_range(symbol_begin(), symbol_end()); + } // construction aux. - static ErrorOr createIRObjectFile(MemoryBuffer *Object, - LLVMContext &Context, - bool BufferOwned = true); - - static ErrorOr createSymbolicFile(MemoryBuffer *Object, - bool BufferOwned, - sys::fs::file_magic Type, - LLVMContext *Context); - - static ErrorOr createSymbolicFile(MemoryBuffer *Object) { - return createSymbolicFile(Object, true, sys::fs::file_magic::unknown, - nullptr); + static ErrorOr + createSymbolicFile(std::unique_ptr &Object, + sys::fs::file_magic Type, LLVMContext *Context); + + static ErrorOr + createSymbolicFile(std::unique_ptr &Object) { + return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr); } static ErrorOr createSymbolicFile(StringRef ObjectPath); @@ -173,7 +173,7 @@ inline void BasicSymbolRef::moveNext() { return OwningObject->moveSymbolNext(SymbolPimpl); } -inline error_code BasicSymbolRef::printName(raw_ostream &OS) const { +inline std::error_code BasicSymbolRef::printName(raw_ostream &OS) const { return OwningObject->printSymbolName(OS, SymbolPimpl); } diff --git a/include/llvm/Object/YAML.h b/include/llvm/Object/YAML.h deleted file mode 100644 index 1792e8b..0000000 --- a/include/llvm/Object/YAML.h +++ /dev/null @@ -1,117 +0,0 @@ -//===- YAML.h - YAMLIO utilities for object files ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares utility classes for handling the YAML representation of -// object files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_YAML_H -#define LLVM_OBJECT_YAML_H - -#include "llvm/Support/YAMLTraits.h" - -namespace llvm { -namespace object { -namespace yaml { - -/// \brief Specialized YAMLIO scalar type for representing a binary blob. -/// -/// A typical use case would be to represent the content of a section in a -/// binary file. -/// This class has custom YAMLIO traits for convenient reading and writing. -/// It renders as a string of hex digits in a YAML file. -/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not -/// require the quotation marks, so for simplicity when outputting they are -/// omitted). -/// When reading, any string whose content is an even number of hex digits -/// will be accepted. -/// For example, all of the following are acceptable: -/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D') -/// -/// A significant advantage of using this class is that it never allocates -/// temporary strings or buffers for any of its functionality. -/// -/// Example: -/// -/// The YAML mapping: -/// \code -/// Foo: DEADBEEFCAFEBABE -/// \endcode -/// -/// Could be modeled in YAMLIO by the struct: -/// \code -/// struct FooHolder { -/// BinaryRef Foo; -/// }; -/// namespace llvm { -/// namespace yaml { -/// template <> -/// struct MappingTraits { -/// static void mapping(IO &IO, FooHolder &FH) { -/// IO.mapRequired("Foo", FH.Foo); -/// } -/// }; -/// } // end namespace yaml -/// } // end namespace llvm -/// \endcode -class BinaryRef { - friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS); - /// \brief Either raw binary data, or a string of hex bytes (must always - /// be an even number of characters). - ArrayRef Data; - /// \brief Discriminator between the two states of the `Data` member. - bool DataIsHexString; - -public: - BinaryRef(ArrayRef Data) : Data(Data), DataIsHexString(false) {} - BinaryRef(StringRef Data) - : Data(reinterpret_cast(Data.data()), Data.size()), - DataIsHexString(true) {} - BinaryRef() : DataIsHexString(true) {} - /// \brief The number of bytes that are represented by this BinaryRef. - /// This is the number of bytes that writeAsBinary() will write. - ArrayRef::size_type binary_size() const { - if (DataIsHexString) - return Data.size() / 2; - return Data.size(); - } - /// \brief Write the contents (regardless of whether it is binary or a - /// hex string) as binary to the given raw_ostream. - void writeAsBinary(raw_ostream &OS) const; - /// \brief Write the contents (regardless of whether it is binary or a - /// hex string) as hex to the given raw_ostream. - /// - /// For example, a possible output could be `DEADBEEFCAFEBABE`. - void writeAsHex(raw_ostream &OS) const; -}; - -inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) { - // Special case for default constructed BinaryRef. - if (LHS.Data.empty() && RHS.Data.empty()) - return true; - - return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data; -} - -} -} - -namespace yaml { -template <> struct ScalarTraits { - static void output(const object::yaml::BinaryRef &, void *, - llvm::raw_ostream &); - static StringRef input(StringRef, void *, object::yaml::BinaryRef &); - static bool mustQuote(StringRef S) { return needsQuotes(S); } -}; -} - -} - -#endif diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index ab40a1a..d46b0e8 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -150,6 +150,12 @@ public: return arg_iterator(Args.end(), *this); } + iterator_range filtered(OptSpecifier Id0 = 0U, + OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return make_range(filtered_begin(Id0, Id1, Id2), filtered_end()); + } + /// @} /// @name Arg Removal /// @{ @@ -328,6 +334,7 @@ public: unsigned MakeIndex(StringRef String0) const; unsigned MakeIndex(StringRef String0, StringRef String1) const; + using ArgList::MakeArgString; const char *MakeArgString(StringRef Str) const override; /// @} @@ -365,6 +372,7 @@ public: /// (to be freed). void AddSynthesizedArg(Arg *A); + using ArgList::MakeArgString; const char *MakeArgString(StringRef Str) const override; /// AddFlagArg - Construct a new FlagArg for the given option \p Id and diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h new file mode 100644 index 0000000..d53daf1 --- /dev/null +++ b/include/llvm/PassInfo.h @@ -0,0 +1,147 @@ +//===- llvm/PassInfo.h - Pass Info class ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines and implements the PassInfo class. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PASSINFO_H +#define LLVM_PASSINFO_H + +#include +#include + +namespace llvm { + +class Pass; +class TargetMachine; + +//===--------------------------------------------------------------------------- +/// PassInfo class - An instance of this class exists for every pass known by +/// the system, and can be obtained from a live Pass by calling its +/// getPassInfo() method. These objects are set up by the RegisterPass<> +/// template. +/// +class PassInfo { +public: + typedef Pass* (*NormalCtor_t)(); + typedef Pass *(*TargetMachineCtor_t)(TargetMachine *); + +private: + const char *const PassName; // Nice name for Pass + const char *const PassArgument; // Command Line argument to run this pass + const void *PassID; + const bool IsCFGOnlyPass; // Pass only looks at the CFG. + const bool IsAnalysis; // True if an analysis pass. + const bool IsAnalysisGroup; // True if an analysis group. + std::vector ItfImpl;// Interfaces implemented by this pass + + NormalCtor_t NormalCtor; + TargetMachineCtor_t TargetMachineCtor; + +public: + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. + PassInfo(const char *name, const char *arg, const void *pi, + NormalCtor_t normal, bool isCFGOnly, bool is_analysis, + TargetMachineCtor_t machine = nullptr) + : PassName(name), PassArgument(arg), PassID(pi), + IsCFGOnlyPass(isCFGOnly), + IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal), + TargetMachineCtor(machine) {} + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. This version is for use by analysis groups; it + /// does not auto-register the pass. + PassInfo(const char *name, const void *pi) + : PassName(name), PassArgument(""), PassID(pi), + IsCFGOnlyPass(false), + IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(nullptr), + TargetMachineCtor(nullptr) {} + + /// getPassName - Return the friendly name for the pass, never returns null + /// + const char *getPassName() const { return PassName; } + + /// getPassArgument - Return the command line option that may be passed to + /// 'opt' that will cause this pass to be run. This will return null if there + /// is no argument. + /// + const char *getPassArgument() const { return PassArgument; } + + /// getTypeInfo - Return the id object for the pass... + /// TODO : Rename + const void *getTypeInfo() const { return PassID; } + + /// Return true if this PassID implements the specified ID pointer. + bool isPassID(const void *IDPtr) const { + return PassID == IDPtr; + } + + /// isAnalysisGroup - Return true if this is an analysis group, not a normal + /// pass. + /// + bool isAnalysisGroup() const { return IsAnalysisGroup; } + bool isAnalysis() const { return IsAnalysis; } + + /// isCFGOnlyPass - return true if this pass only looks at the CFG for the + /// function. + bool isCFGOnlyPass() const { return IsCFGOnlyPass; } + + /// getNormalCtor - Return a pointer to a function, that when called, creates + /// an instance of the pass and returns it. This pointer may be null if there + /// is no default constructor for the pass. + /// + NormalCtor_t getNormalCtor() const { + return NormalCtor; + } + void setNormalCtor(NormalCtor_t Ctor) { + NormalCtor = Ctor; + } + + /// getTargetMachineCtor - Return a pointer to a function, that when called + /// with a TargetMachine, creates an instance of the pass and returns it. + /// This pointer may be null if there is no constructor with a TargetMachine + /// for the pass. + /// + TargetMachineCtor_t getTargetMachineCtor() const { return TargetMachineCtor; } + void setTargetMachineCtor(TargetMachineCtor_t Ctor) { + TargetMachineCtor = Ctor; + } + + /// createPass() - Use this method to create an instance of this pass. + Pass *createPass() const { + assert((!isAnalysisGroup() || NormalCtor) && + "No default implementation found for analysis group!"); + assert(NormalCtor && + "Cannot call createPass on PassInfo without default ctor!"); + return NormalCtor(); + } + + /// addInterfaceImplemented - This method is called when this pass is + /// registered as a member of an analysis group with the RegisterAnalysisGroup + /// template. + /// + void addInterfaceImplemented(const PassInfo *ItfPI) { + ItfImpl.push_back(ItfPI); + } + + /// getInterfacesImplemented - Return a list of all of the analysis group + /// interfaces implemented by this pass. + /// + const std::vector &getInterfacesImplemented() const { + return ItfImpl; + } + +private: + void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; + PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; +}; + +} + +#endif diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index 7f2a014..1558c51 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -18,8 +18,14 @@ #define LLVM_PASSREGISTRY_H #include "llvm-c/Core.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/PassInfo.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/RWMutex.h" +#include namespace llvm { @@ -33,11 +39,26 @@ struct PassRegistrationListener; /// threads simultaneously, you will need to use a separate PassRegistry on /// each thread. class PassRegistry { - mutable void *pImpl; - void *getImpl() const; + mutable sys::SmartRWMutex Lock; + + /// PassInfoMap - Keep track of the PassInfo object for each registered pass. + typedef DenseMap MapType; + MapType PassInfoMap; + + typedef StringMap StringMapType; + StringMapType PassInfoStringMap; + + /// AnalysisGroupInfo - Keep track of information for each analysis group. + struct AnalysisGroupInfo { + SmallPtrSet Implementations; + }; + DenseMap AnalysisGroupInfoMap; + + std::vector> ToFree; + std::vector Listeners; public: - PassRegistry() : pImpl(nullptr) { } + PassRegistry() { } ~PassRegistry(); /// getPassRegistry - Access the global registry object, which is diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index 8efb45f..449bc92 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -23,6 +23,7 @@ #include "Pass.h" #include "llvm/InitializePasses.h" +#include "llvm/PassInfo.h" #include "llvm/PassRegistry.h" #include "llvm/Support/Atomic.h" #include "llvm/Support/Valgrind.h" @@ -31,120 +32,6 @@ namespace llvm { class TargetMachine; -//===--------------------------------------------------------------------------- -/// PassInfo class - An instance of this class exists for every pass known by -/// the system, and can be obtained from a live Pass by calling its -/// getPassInfo() method. These objects are set up by the RegisterPass<> -/// template, defined below. -/// -class PassInfo { -public: - typedef Pass* (*NormalCtor_t)(); - typedef Pass *(*TargetMachineCtor_t)(TargetMachine *); - -private: - const char *const PassName; // Nice name for Pass - const char *const PassArgument; // Command Line argument to run this pass - const void *PassID; - const bool IsCFGOnlyPass; // Pass only looks at the CFG. - const bool IsAnalysis; // True if an analysis pass. - const bool IsAnalysisGroup; // True if an analysis group. - std::vector ItfImpl;// Interfaces implemented by this pass - - NormalCtor_t NormalCtor; - TargetMachineCtor_t TargetMachineCtor; - -public: - /// PassInfo ctor - Do not call this directly, this should only be invoked - /// through RegisterPass. - PassInfo(const char *name, const char *arg, const void *pi, - NormalCtor_t normal, bool isCFGOnly, bool is_analysis, - TargetMachineCtor_t machine = nullptr) - : PassName(name), PassArgument(arg), PassID(pi), - IsCFGOnlyPass(isCFGOnly), - IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal), - TargetMachineCtor(machine) {} - /// PassInfo ctor - Do not call this directly, this should only be invoked - /// through RegisterPass. This version is for use by analysis groups; it - /// does not auto-register the pass. - PassInfo(const char *name, const void *pi) - : PassName(name), PassArgument(""), PassID(pi), - IsCFGOnlyPass(false), - IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(nullptr), - TargetMachineCtor(nullptr) {} - - /// getPassName - Return the friendly name for the pass, never returns null - /// - const char *getPassName() const { return PassName; } - - /// getPassArgument - Return the command line option that may be passed to - /// 'opt' that will cause this pass to be run. This will return null if there - /// is no argument. - /// - const char *getPassArgument() const { return PassArgument; } - - /// getTypeInfo - Return the id object for the pass... - /// TODO : Rename - const void *getTypeInfo() const { return PassID; } - - /// Return true if this PassID implements the specified ID pointer. - bool isPassID(const void *IDPtr) const { - return PassID == IDPtr; - } - - /// isAnalysisGroup - Return true if this is an analysis group, not a normal - /// pass. - /// - bool isAnalysisGroup() const { return IsAnalysisGroup; } - bool isAnalysis() const { return IsAnalysis; } - - /// isCFGOnlyPass - return true if this pass only looks at the CFG for the - /// function. - bool isCFGOnlyPass() const { return IsCFGOnlyPass; } - - /// getNormalCtor - Return a pointer to a function, that when called, creates - /// an instance of the pass and returns it. This pointer may be null if there - /// is no default constructor for the pass. - /// - NormalCtor_t getNormalCtor() const { - return NormalCtor; - } - void setNormalCtor(NormalCtor_t Ctor) { - NormalCtor = Ctor; - } - - /// getTargetMachineCtor - Return a pointer to a function, that when called - /// with a TargetMachine, creates an instance of the pass and returns it. - /// This pointer may be null if there is no constructor with a TargetMachine - /// for the pass. - /// - TargetMachineCtor_t getTargetMachineCtor() const { return TargetMachineCtor; } - void setTargetMachineCtor(TargetMachineCtor_t Ctor) { - TargetMachineCtor = Ctor; - } - - /// createPass() - Use this method to create an instance of this pass. - Pass *createPass() const; - - /// addInterfaceImplemented - This method is called when this pass is - /// registered as a member of an analysis group with the RegisterAnalysisGroup - /// template. - /// - void addInterfaceImplemented(const PassInfo *ItfPI) { - ItfImpl.push_back(ItfPI); - } - - /// getInterfacesImplemented - Return a list of all of the analysis group - /// interfaces implemented by this pass. - /// - const std::vector &getInterfacesImplemented() const { - return ItfImpl; - } - -private: - void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; - PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; -}; #define CALL_ONCE_INITIALIZATION(function) \ static volatile sys::cas_flag initialized = 0; \ @@ -325,19 +212,12 @@ struct RegisterAnalysisGroup : public RegisterAGBase { /// clients that are interested in which passes get registered and unregistered /// at runtime (which can be because of the RegisterPass constructors being run /// as the program starts up, or may be because a shared object just got -/// loaded). Deriving from the PassRegistrationListener class automatically -/// registers your object to receive callbacks indicating when passes are loaded -/// and removed. +/// loaded). /// struct PassRegistrationListener { - /// PassRegistrationListener ctor - Add the current object to the list of - /// PassRegistrationListeners... - PassRegistrationListener(); - - /// dtor - Remove object from list of listeners... - /// - virtual ~PassRegistrationListener(); + PassRegistrationListener() {} + virtual ~PassRegistrationListener() {} /// Callback functions - These functions are invoked whenever a pass is loaded /// or removed from the current executable. diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 8457678..eafb768 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -16,14 +16,12 @@ #ifndef LLVM_PROFILEDATA_INSTRPROF_H_ #define LLVM_PROFILEDATA_INSTRPROF_H_ -#include "llvm/Support/system_error.h" +#include namespace llvm { +const std::error_category &instrprof_category(); -const error_category &instrprof_category(); - -struct instrprof_error { - enum ErrorType { +enum class instrprof_error { success = 0, eof, bad_magic, @@ -37,21 +35,17 @@ struct instrprof_error { hash_mismatch, count_mismatch, counter_overflow - }; - ErrorType V; - - instrprof_error(ErrorType V) : V(V) {} - operator ErrorType() const { return V; } }; -inline error_code make_error_code(instrprof_error E) { - return error_code(static_cast(E), instrprof_category()); +inline std::error_code make_error_code(instrprof_error E) { + return std::error_code(static_cast(E), instrprof_category()); } -template <> struct is_error_code_enum : std::true_type {}; -template <> struct is_error_code_enum - : std::true_type {}; - } // end namespace llvm +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} + #endif // LLVM_PROFILEDATA_INSTRPROF_H_ diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 3e18c76..7a5a71d 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -60,28 +60,29 @@ public: /// Base class and interface for reading profiling data of any known instrprof /// format. Provides an iterator over InstrProfRecords. class InstrProfReader { - error_code LastError; + std::error_code LastError; + public: InstrProfReader() : LastError(instrprof_error::success) {} virtual ~InstrProfReader() {} /// Read the header. Required before reading first record. - virtual error_code readHeader() = 0; + virtual std::error_code readHeader() = 0; /// Read a single record. - virtual error_code readNextRecord(InstrProfRecord &Record) = 0; + virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0; /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } protected: - /// Set the current error_code and return same. - error_code error(error_code EC) { + /// Set the current std::error_code and return same. + std::error_code error(std::error_code EC) { LastError = EC; return EC; } /// Clear the current error code and return a successful one. - error_code success() { return error(instrprof_error::success); } + std::error_code success() { return error(instrprof_error::success); } public: /// Return true if the reader has finished reading the profile data. @@ -89,12 +90,12 @@ public: /// Return true if the reader encountered an error reading profiling data. bool hasError() { return LastError && !isEOF(); } /// Get the current error code. - error_code getError() { return LastError; } + std::error_code getError() { return LastError; } /// Factory method to create an appropriately typed reader for the given /// instrprof file. - static error_code create(std::string Path, - std::unique_ptr &Result); + static std::error_code create(std::string Path, + std::unique_ptr &Result); }; /// Reader for the simple text based instrprof format. @@ -122,9 +123,9 @@ public: : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, '#') {} /// Read the header. - error_code readHeader() override { return success(); } + std::error_code readHeader() override { return success(); } /// Read a single record. - error_code readNextRecord(InstrProfRecord &Record) override; + std::error_code readNextRecord(InstrProfRecord &Record) override; }; /// Reader for the raw instrprof binary format from runtime. @@ -167,23 +168,23 @@ private: const char *NamesStart; const char *ProfileEnd; - RawInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - RawInstrProfReader &operator=(const TextInstrProfReader &) + RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; + RawInstrProfReader &operator=(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; public: RawInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) { } static bool hasFormat(const MemoryBuffer &DataBuffer); - error_code readHeader() override; - error_code readNextRecord(InstrProfRecord &Record) override; + std::error_code readHeader() override; + std::error_code readNextRecord(InstrProfRecord &Record) override; private: - error_code readNextHeader(const char *CurrentPos); - error_code readHeader(const RawHeader &Header); + std::error_code readNextHeader(const char *CurrentPos); + std::error_code readHeader(const RawHeader &Header); template IntT swap(IntT Int) const { - return ShouldSwapBytes ? sys::SwapByteOrder(Int) : Int; + return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; } const uint64_t *getCounter(IntPtrT CounterPtr) const { ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); @@ -281,19 +282,19 @@ public: static bool hasFormat(const MemoryBuffer &DataBuffer); /// Read the file header. - error_code readHeader() override; + std::error_code readHeader() override; /// Read a single record. - error_code readNextRecord(InstrProfRecord &Record) override; + std::error_code readNextRecord(InstrProfRecord &Record) override; /// Fill Counts with the profile data for the given function name. - error_code getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, - std::vector &Counts); + std::error_code getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, + std::vector &Counts); /// Return the maximum of all known function counts. uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } /// Factory method to create an indexed reader. - static error_code create(std::string Path, - std::unique_ptr &Result); + static std::error_code + create(std::string Path, std::unique_ptr &Result); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index fa37bf1..6e68bee 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -38,8 +38,9 @@ public: /// Add function counts for the given function. If there are already counts /// for this function and the hash and number of counts match, each counter is /// summed. - error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, - ArrayRef Counters); + std::error_code addFunctionCounts(StringRef FunctionName, + uint64_t FunctionHash, + ArrayRef Counters); /// Ensure that all data is written to disk. void write(raw_fd_ostream &OS); }; diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index 1631200..f63e0a6 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -159,6 +159,11 @@ enum { AddressDirect = 1, // Address imported data directly AddressGOT = 2, // Address imported data indirectly (via GOT) + // Tag_ABI_PCS_wchar_t, (=18), uleb128 + WCharProhibited = 0, // wchar_t is not used + WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2 + WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 + // Tag_ABI_FP_denormal, (=20), uleb128 PreserveFPSign = 2, // sign when flushed-to-zero is preserved @@ -166,6 +171,16 @@ enum { AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI]) AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings + // Tag_ABI_enum_size, (=26), uleb128 + EnumProhibited = 0, // The user prohibited the use of enums when building + // this entity. + EnumSmallest = 1, // Enum is smallest container big enough to hold all + // values. + Enum32Bit = 2, // Enum is at least 32 bits. + Enum32BitABI = 3, // Every enumeration visible across an ABI-complying + // interface contains a value needing 32 bits to encode + // it; other enums can be containerized. + // Tag_ABI_HardFP_use, (=27), uleb128 HardFPImplied = 0, // FP use should be implied by Tag_FP_arch HardFPSinglePrecision = 1, // Single-precision only diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h new file mode 100644 index 0000000..78deb8d --- /dev/null +++ b/include/llvm/Support/ARMWinEH.h @@ -0,0 +1,384 @@ +//===-- llvm/Support/WinARMEH.h - Windows on ARM EH Constants ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINARMEH_H +#define LLVM_SUPPORT_WINARMEH_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace ARM { +namespace WinEH { +enum class RuntimeFunctionFlag { + RFF_Unpacked, /// unpacked entry + RFF_Packed, /// packed entry + RFF_PackedFragment, /// packed entry representing a fragment + RFF_Reserved, /// reserved +}; + +enum class ReturnType { + RT_POP, /// return via pop {pc} (L flag must be set) + RT_B, /// 16-bit branch + RT_BW, /// 32-bit branch + RT_NoEpilogue, /// no epilogue (fragment) +}; + +/// RuntimeFunction - An entry in the table of procedure data (.pdata) +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------------------------------------------------------+ +/// | Function Start RVA | +/// +-------------------+-+-+-+-----+-+---+---------------------+---+ +/// | Stack Adjust |C|L|R| Reg |H|Ret| Function Length |Flg| +/// +-------------------+-+-+-+-----+-+---+---------------------+---+ +/// +/// Flag : 2-bit field with the following meanings: +/// - 00 = packed unwind data not used; reamining bits point to .xdata record +/// - 01 = packed unwind data +/// - 10 = packed unwind data, function assumed to have no prologue; useful +/// for function fragments that are discontiguous with the start of the +/// function +/// - 11 = reserved +/// Function Length : 11-bit field providing the length of the entire function +/// in bytes, divided by 2; if the function is greater than +/// 4KB, a full .xdata record must be used instead +/// Ret : 2-bit field indicating how the function returns +/// - 00 = return via pop {pc} (the L bit must be set) +/// - 01 = return via 16-bit branch +/// - 10 = return via 32-bit branch +/// - 11 = no epilogue; useful for function fragments that may only contain a +/// prologue but the epilogue is elsewhere +/// H : 1-bit flag indicating whether the function "homes" the integer parameter +/// registers (r0-r3), allocating 16-bytes on the stack +/// Reg : 3-bit field indicating the index of the last saved non-volatile +/// register. If the R bit is set to 0, then only integer registers are +/// saved (r4-rN, where N is 4 + Reg). If the R bit is set to 1, then +/// only floating-point registers are being saved (d8-dN, where N is +/// 8 + Reg). The special case of the R bit being set to 1 and Reg equal +/// to 7 indicates that no registers are saved. +/// R : 1-bit flag indicating whether the non-volatile registers are integer or +/// floating-point. 0 indicates integer, 1 indicates floating-point. The +/// special case of the R-flag being set and Reg being set to 7 indicates +/// that no non-volatile registers are saved. +/// L : 1-bit flag indicating whether the function saves/restores the link +/// register (LR) +/// C : 1-bit flag indicating whether the function includes extra instructions +/// to setup a frame chain for fast walking. If this flag is set, r11 is +/// implicitly added to the list of saved non-volatile integer registers. +/// Stack Adjust : 10-bit field indicating the number of bytes of stack that are +/// allocated for this function. Only values between 0x000 and +/// 0x3f3 can be directly encoded. If the value is 0x3f4 or +/// greater, then the low 4 bits have special meaning as follows: +/// - Bit 0-1 +/// indicate the number of words' of adjustment (1-4), minus 1 +/// - Bit 2 +/// indicates if the prologue combined adjustment into push +/// - Bit 3 +/// indicates if the epilogue combined adjustment into pop +/// +/// RESTRICTIONS: +/// - IF C is SET: +/// + L flag must be set since frame chaining requires r11 and lr +/// + r11 must NOT be included in the set of registers described by Reg +/// - IF Ret is 0: +/// + L flag must be set + +// NOTE: RuntimeFunction is meant to be a simple class that provides raw access +// to all fields in the structure. The accessor methods reflect the names of +// the bitfields that they correspond to. Although some obvious simplifications +// are possible via merging of methods, it would prevent the use of this class +// to fully inspect the contents of the data structure which is particularly +// useful for scenarios such as llvm-readobj to aid in testing. + +class RuntimeFunction { +public: + const support::ulittle32_t BeginAddress; + const support::ulittle32_t UnwindData; + + RuntimeFunction(const support::ulittle32_t *Data) + : BeginAddress(Data[0]), UnwindData(Data[1]) {} + + RuntimeFunction(const support::ulittle32_t BeginAddress, + const support::ulittle32_t UnwindData) + : BeginAddress(BeginAddress), UnwindData(UnwindData) {} + + RuntimeFunctionFlag Flag() const { + return RuntimeFunctionFlag(UnwindData & 0x3); + } + + uint32_t ExceptionInformationRVA() const { + assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked && + "unpacked form required for this operation"); + return (UnwindData & ~0x3); + } + + uint32_t PackedUnwindData() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return (UnwindData & ~0x3); + } + uint32_t FunctionLength() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return (((UnwindData & 0x00001ffc) >> 2) << 1); + } + ReturnType Ret() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + assert(((UnwindData & 0x00006000) || L()) && "L must be set to 1"); + return ReturnType((UnwindData & 0x00006000) >> 13); + } + bool H() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00008000) >> 15); + } + uint8_t Reg() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00070000) >> 16); + } + bool R() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00080000) >> 19); + } + bool L() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00100000) >> 20); + } + bool C() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + assert(((~UnwindData & 0x00200000) || L()) && + "L flag must be set, chaining requires r11 and LR"); + assert(((~UnwindData & 0x00200000) || (Reg() < 7) || R()) && + "r11 must not be included in Reg; C implies r11"); + return ((UnwindData & 0x00200000) >> 21); + } + uint16_t StackAdjust() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0xffc00000) >> 22); + } +}; + +/// PrologueFolding - pseudo-flag derived from Stack Adjust indicating that the +/// prologue has stack adjustment combined into the push +inline bool PrologueFolding(const RuntimeFunction &RF) { + return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x4); +} +/// Epilogue - pseudo-flag derived from Stack Adjust indicating that the +/// epilogue has stack adjustment combined into the pop +inline bool EpilogueFolding(const RuntimeFunction &RF) { + return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x8); +} +/// StackAdjustment - calculated stack adjustment in words. The stack +/// adjustment should be determined via this function to account for the special +/// handling the special encoding when the value is >= 0x3f4. +inline uint16_t StackAdjustment(const RuntimeFunction &RF) { + uint16_t Adjustment = RF.StackAdjust(); + if (Adjustment >= 0x3f4) + return (Adjustment & 0x3) ? ((Adjustment & 0x3) << 2) - 1 : 0; + return Adjustment; +} + +/// SavedRegisterMask - Utility function to calculate the set of saved general +/// purpose (r0-r15) and VFP (d0-d31) registers. +std::pair SavedRegisterMask(const RuntimeFunction &RF); + +/// ExceptionDataRecord - An entry in the table of exception data (.xdata) +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +-------+---------+-+-+-+---+-----------------------------------+ +/// | C Wrd | Epi Cnt |F|E|X|Ver| Function Length | +/// +-------+--------+'-'-'-'---'---+-------------------------------+ +/// | Reserved |Ex. Code Words| (Extended Epilogue Count) | +/// +-------+--------+--------------+-------------------------------+ +/// +/// Function Length : 18-bit field indicating the total length of the function +/// in bytes divided by 2. If a function is larger than +/// 512KB, then multiple pdata and xdata records must be used. +/// Vers : 2-bit field describing the version of the remaining structure. Only +/// version 0 is currently defined (values 1-3 are not permitted). +/// X : 1-bit field indicating the presence of exception data +/// E : 1-bit field indicating that the single epilogue is packed into the +/// header +/// F : 1-bit field indicating that the record describes a function fragment +/// (implies that no prologue is present, and prologue processing should be +/// skipped) +/// Epilogue Count : 5-bit field that differs in meaning based on the E field. +/// +/// If E is set, then this field specifies the index of the +/// first unwind code describing the (only) epilogue. +/// +/// Otherwise, this field indicates the number of exception +/// scopes. If more than 31 scopes exist, then this field and +/// the Code Words field must both be set to 0 to indicate that +/// an extension word is required. +/// Code Words : 4-bit field that species the number of 32-bit words needed to +/// contain all the unwind codes. If more than 15 words (63 code +/// bytes) are required, then this field and the Epilogue Count +/// field must both be set to 0 to indicate that an extension word +/// is required. +/// Extended Epilogue Count, Extended Code Words : +/// Valid only if Epilog Count and Code Words are both +/// set to 0. Provides an 8-bit extended code word +/// count and 16-bits for epilogue count +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +----------------+------+---+---+-------------------------------+ +/// | Ep Start Idx | Cond |Res| Epilogue Start Offset | +/// +----------------+------+---+-----------------------------------+ +/// +/// If the E bit is unset in the header, the header is followed by a series of +/// epilogue scopes, which are sorted by their offset. +/// +/// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative +/// to the start of the function in bytes divided by two +/// Res : 2-bit field reserved for future expansion (must be set to 0) +/// Condition : 4-bit field providing the condition under which the epilogue is +/// executed. Unconditional epilogues should set this field to 0xe. +/// Epilogues must be entirely conditional or unconditional, and in +/// Thumb-2 mode. The epilogue beings with the first instruction +/// after the IT opcode. +/// Epilogue Start Index : 8-bit field indicating the byte index of the first +/// unwind code describing the epilogue +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------+---------------+---------------+---------------+ +/// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 | +/// +---------------+---------------+---------------+---------------+ +/// +/// Following the epilogue scopes, the byte code describing the unwinding +/// follows. This is padded to align up to word alignment. Bytes are stored in +/// little endian. +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------------------------------------------------------+ +/// | Exception Handler RVA (requires X = 1) | +/// +---------------------------------------------------------------+ +/// | (possibly followed by data required for exception handler) | +/// +---------------------------------------------------------------+ +/// +/// If the X bit is set in the header, the unwind byte code is followed by the +/// exception handler information. This constants of one Exception Handler RVA +/// which is the address to the exception handler, followed immediately by the +/// variable length data associated with the exception handler. +/// + +struct EpilogueScope { + const support::ulittle32_t ES; + + EpilogueScope(const support::ulittle32_t Data) : ES(Data) {} + uint32_t EpilogueStartOffset() const { + return (ES & 0x0003ffff); + } + uint8_t Res() const { + return ((ES & 0x000c0000) >> 18); + } + uint8_t Condition() const { + return ((ES & 0x00f00000) >> 20); + } + uint8_t EpilogueStartIndex() const { + return ((ES & 0xff000000) >> 24); + } +}; + +struct ExceptionDataRecord; +inline size_t HeaderWords(const ExceptionDataRecord &XR); + +struct ExceptionDataRecord { + const support::ulittle32_t *Data; + + ExceptionDataRecord(const support::ulittle32_t *Data) : Data(Data) {} + + uint32_t FunctionLength() const { + return (Data[0] & 0x0003ffff); + } + + uint8_t Vers() const { + return (Data[0] & 0x000C0000) >> 18; + } + + bool X() const { + return ((Data[0] & 0x00100000) >> 20); + } + + bool E() const { + return ((Data[0] & 0x00200000) >> 21); + } + + bool F() const { + return ((Data[0] & 0x00400000) >> 22); + } + + uint8_t EpilogueCount() const { + if (HeaderWords(*this) == 1) + return (Data[0] & 0x0f800000) >> 23; + return Data[1] & 0x0000ffff; + } + + uint8_t CodeWords() const { + if (HeaderWords(*this) == 1) + return (Data[0] & 0xf0000000) >> 28; + return (Data[1] & 0x00ff0000) >> 16; + } + + ArrayRef EpilogueScopes() const { + assert(E() == 0 && "epilogue scopes are only present when the E bit is 0"); + size_t Offset = HeaderWords(*this); + return ArrayRef(&Data[Offset], EpilogueCount()); + } + + ArrayRef UnwindByteCode() const { + const size_t Offset = HeaderWords(*this) + + (E() ? 0 : EpilogueCount()); + const support::ulittle8_t *ByteCode = + reinterpret_cast(&Data[Offset]); + return ArrayRef(ByteCode, + CodeWords() * sizeof(uint32_t)); + } + + uint32_t ExceptionHandlerRVA() const { + assert(X() && "Exception Handler RVA is only valid if the X bit is set"); + return Data[HeaderWords(*this) + EpilogueCount() + CodeWords()]; + } + + uint32_t ExceptionHandlerParameter() const { + assert(X() && "Exception Handler RVA is only valid if the X bit is set"); + return Data[HeaderWords(*this) + EpilogueCount() + CodeWords() + 1]; + } +}; + +inline size_t HeaderWords(const ExceptionDataRecord &XR) { + return (XR.Data[0] & 0xff800000) ? 1 : 2; +} +} +} +} + +#endif + diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index f0e5c7d..e09ef07 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -553,7 +553,8 @@ namespace COFF { IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, /// Code integrity checks are enforced. IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, - IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, ///< Image is NX compatible. + ///< Image is NX compatible. + IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, /// Isolation aware, but do not isolate the image. IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200, /// Does not use structured exception handling (SEH). No SEH handler may be @@ -561,7 +562,12 @@ namespace COFF { IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400, /// Do not bind the image. IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800, - IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, ///< A WDM driver. + ///< Image should execute in an AppContainer. + IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000, + ///< A WDM driver. + IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, + ///< Image supports Control Flow Guard. + IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000, /// Terminal Server aware. IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 }; diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 1edcd45..25bf32a 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -61,6 +61,12 @@ #define LLVM_MSC_PREREQ(version) 0 #endif +#ifndef _MSC_VER +#define LLVM_NOEXCEPT noexcept +#else +#define LLVM_NOEXCEPT +#endif + /// \brief Does the compiler support r-value reference *this? /// /// Sadly, this is separate from just r-value reference support because GCC diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index 2820366..a184d0d 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -136,7 +136,19 @@ ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); -ConversionResult ConvertUTF8toUTF32 ( +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceExhausted. + */ +ConversionResult ConvertUTF8toUTF32Partial( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceIllegal. + */ +ConversionResult ConvertUTF8toUTF32( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index c132373..3869ebd 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -87,6 +87,9 @@ public: /// requested stack size). /// /// See RunSafely() and llvm_execute_on_thread(). + /// + /// On Darwin, if PRIO_DARWIN_BG is set on the calling thread, it will be + /// propagated to the new thread as well. bool RunSafelyOnThread(function_ref, unsigned RequestedStackSize = 0); bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, unsigned RequestedStackSize = 0) { diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index a26070c..1f0c8eb 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -37,6 +37,16 @@ #include #endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#else +#error "Compiler must provide an implementation of stdint.h" +#endif + #ifndef _MSC_VER /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS @@ -55,14 +65,6 @@ /* Note that includes , if this is a C99 system. */ #include -#ifdef HAVE_INTTYPES_H -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - #ifdef _AIX #include "llvm/Support/AIXDataTypesFix.h" #endif @@ -77,11 +79,6 @@ typedef u_int64_t uint64_t; #endif #else /* _MSC_VER */ -/* Visual C++ doesn't provide standard integer headers, but it does provide - built-in data types. */ -#ifdef HAVE_STDINT_H -#include -#endif #include #include #include @@ -90,93 +87,21 @@ typedef u_int64_t uint64_t; #else #include #endif -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef signed char int8_t; -typedef unsigned char uint8_t; + #if defined(_WIN64) - typedef signed __int64 ssize_t; +typedef signed __int64 ssize_t; #else - typedef signed int ssize_t; -#endif -#ifndef INT8_MAX -# define INT8_MAX 127 -#endif -#ifndef INT8_MIN -# define INT8_MIN -128 -#endif -#ifndef UINT8_MAX -# define UINT8_MAX 255 -#endif -#ifndef INT16_MAX -# define INT16_MAX 32767 -#endif -#ifndef INT16_MIN -# define INT16_MIN -32768 -#endif -#ifndef UINT16_MAX -# define UINT16_MAX 65535 -#endif -#ifndef INT32_MAX -# define INT32_MAX 2147483647 -#endif -#ifndef INT32_MIN -/* MSC treats -2147483648 as -(2147483648U). */ -# define INT32_MIN (-INT32_MAX - 1) -#endif -#ifndef UINT32_MAX -# define UINT32_MAX 4294967295U -#endif -/* Certain compatibility updates to VC++ introduce the `cstdint' - * header, which defines the INT*_C macros. On default installs they - * are absent. */ -#ifndef INT8_C -# define INT8_C(C) C##i8 -#endif -#ifndef UINT8_C -# define UINT8_C(C) C##ui8 -#endif -#ifndef INT16_C -# define INT16_C(C) C##i16 -#endif -#ifndef UINT16_C -# define UINT16_C(C) C##ui16 -#endif -#ifndef INT32_C -# define INT32_C(C) C##i32 -#endif -#ifndef UINT32_C -# define UINT32_C(C) C##ui32 -#endif -#ifndef INT64_C -# define INT64_C(C) C##i64 -#endif -#ifndef UINT64_C -# define UINT64_C(C) C##ui64 -#endif - -#ifndef PRId64 -# define PRId64 "I64d" -#endif -#ifndef PRIi64 -# define PRIi64 "I64i" -#endif -#ifndef PRIo64 -# define PRIo64 "I64o" -#endif -#ifndef PRIu64 -# define PRIu64 "I64u" -#endif -#ifndef PRIx64 -# define PRIx64 "I64x" -#endif -#ifndef PRIX64 -# define PRIX64 "I64X" -#endif +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#ifndef HAVE_INTTYPES_H +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index 7fc9b72..09cfcdf 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -37,6 +37,16 @@ #include #endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#else +#error "Compiler must provide an implementation of stdint.h" +#endif + #ifndef _MSC_VER /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS @@ -55,14 +65,6 @@ /* Note that includes , if this is a C99 system. */ #include -#ifdef HAVE_INTTYPES_H -#include -#endif - -#ifdef HAVE_STDINT_H -#include -#endif - #ifdef _AIX #include "llvm/Support/AIXDataTypesFix.h" #endif @@ -77,8 +79,6 @@ typedef u_int64_t uint64_t; #endif #else /* _MSC_VER */ -/* Visual C++ doesn't provide standard integer headers, but it does provide - built-in data types. */ #include #include #include @@ -87,94 +87,21 @@ typedef u_int64_t uint64_t; #else #include #endif -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef signed char int8_t; -typedef unsigned char uint8_t; + #if defined(_WIN64) - typedef signed __int64 ssize_t; +typedef signed __int64 ssize_t; #else - typedef signed int ssize_t; -#endif - -#ifndef INT8_MAX -# define INT8_MAX 127 -#endif -#ifndef INT8_MIN -# define INT8_MIN -128 -#endif -#ifndef UINT8_MAX -# define UINT8_MAX 255 -#endif -#ifndef INT16_MAX -# define INT16_MAX 32767 -#endif -#ifndef INT16_MIN -# define INT16_MIN -32768 -#endif -#ifndef UINT16_MAX -# define UINT16_MAX 65535 -#endif -#ifndef INT32_MAX -# define INT32_MAX 2147483647 -#endif -#ifndef INT32_MIN -/* MSC treats -2147483648 as -(2147483648U). */ -# define INT32_MIN (-INT32_MAX - 1) -#endif -#ifndef UINT32_MAX -# define UINT32_MAX 4294967295U -#endif -/* Certain compatibility updates to VC++ introduce the `cstdint' - * header, which defines the INT*_C macros. On default installs they - * are absent. */ -#ifndef INT8_C -# define INT8_C(C) C##i8 -#endif -#ifndef UINT8_C -# define UINT8_C(C) C##ui8 -#endif -#ifndef INT16_C -# define INT16_C(C) C##i16 -#endif -#ifndef UINT16_C -# define UINT16_C(C) C##ui16 -#endif -#ifndef INT32_C -# define INT32_C(C) C##i32 -#endif -#ifndef UINT32_C -# define UINT32_C(C) C##ui32 -#endif -#ifndef INT64_C -# define INT64_C(C) C##i64 -#endif -#ifndef UINT64_C -# define UINT64_C(C) C##ui64 -#endif - -#ifndef PRId64 -# define PRId64 "I64d" -#endif -#ifndef PRIi64 -# define PRIi64 "I64i" -#endif -#ifndef PRIo64 -# define PRIo64 "I64o" -#endif -#ifndef PRIu64 -# define PRIu64 "I64u" -#endif -#ifndef PRIx64 -# define PRIx64 "I64x" -#endif -#ifndef PRIX64 -# define PRIX64 "I64X" -#endif +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#ifndef HAVE_INTTYPES_H +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index ca31644..cd9f756 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -57,7 +57,6 @@ enum LLVMConstants : uint32_t { DW_TAG_user_base = 0x1000, // Recommended base for user tags. DWARF_VERSION = 4, // Default dwarf version we output. - DW_CIE_VERSION = 1, // Common frame information version. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 0b3e55b..67cc651 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -124,6 +124,8 @@ enum { }; // Machine architectures +// See current registered ELF machine architectures at: +// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html enum { EM_NONE = 0, // No machine EM_M32 = 1, // AT&T WE 32100 @@ -287,7 +289,26 @@ enum { EM_RL78 = 197, // Renesas RL78 family EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor EM_78KOR = 199, // Renesas 78KOR family - EM_56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) + EM_BA1 = 201, // Beyond BA1 CPU architecture + EM_BA2 = 202, // Beyond BA2 CPU architecture + EM_XCORE = 203, // XMOS xCORE processor family + EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) family + EM_INTEL205 = 205, // Reserved by Intel + EM_INTEL206 = 206, // Reserved by Intel + EM_INTEL207 = 207, // Reserved by Intel + EM_INTEL208 = 208, // Reserved by Intel + EM_INTEL209 = 209, // Reserved by Intel + EM_KM32 = 210, // KM211 KM32 32-bit processor + EM_KMX32 = 211, // KM211 KMX32 32-bit processor + EM_KMX16 = 212, // KM211 KMX16 16-bit processor + EM_KMX8 = 213, // KM211 KMX8 8-bit processor + EM_KVARC = 214, // KM211 KVARC processor + EM_CDP = 215, // Paneve CDP architecture family + EM_COGE = 216, // Cognitive Smart Memory Processor + EM_COOL = 217, // iCelero CoolEngine + EM_NORC = 218, // Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219 // CSR Kalimba architecture family }; // Object file classes. @@ -1278,6 +1299,7 @@ enum : unsigned { SHT_MIPS_REGINFO = 0x70000006, // Register usage information SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. @@ -1595,7 +1617,8 @@ enum { // MIPS program header types. PT_MIPS_REGINFO = 0x70000000, // Register usage information. PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. - PT_MIPS_OPTIONS = 0x70000002 // Options segment. + PT_MIPS_OPTIONS = 0x70000002, // Options segment. + PT_MIPS_ABIFLAGS = 0x70000003 // Abiflags segment. }; // Segment flag bits. diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 2c5ab74..455d0fc 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -38,7 +38,7 @@ namespace endian { template inline value_type byte_swap(value_type value) { if (endian != native && sys::IsBigEndianHost != (endian == big)) - return sys::SwapByteOrder(value); + sys::swapByteOrder(value); return value; } diff --git a/include/llvm/Support/Errc.h b/include/llvm/Support/Errc.h new file mode 100644 index 0000000..80bfe2a --- /dev/null +++ b/include/llvm/Support/Errc.h @@ -0,0 +1,86 @@ +//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// While std::error_code works OK on all platforms we use, there are some +// some problems with std::errc that can be avoided by using our own +// enumeration: +// +// * std::errc is a namespace in some implementations. That meas that ADL +// doesn't work and it is sometimes necessary to write std::make_error_code +// or in templates: +// using std::make_error_code; +// make_error_code(...); +// +// with this enum it is safe to always just use make_error_code. +// +// * Some implementations define fewer names than others. This header has +// the intersection of all the ones we support. +// +// * std::errc is just marked with is_error_condition_enum. This means that +// common patters like AnErrorCode == errc::no_such_file_or_directory take +// 4 virtual calls instead of two comparisons. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRC_H +#define LLVM_SUPPORT_ERRC_H + +#include + +namespace llvm { +enum class errc { + argument_list_too_long = int(std::errc::argument_list_too_long), + argument_out_of_domain = int(std::errc::argument_out_of_domain), + bad_address = int(std::errc::bad_address), + bad_file_descriptor = int(std::errc::bad_file_descriptor), + broken_pipe = int(std::errc::broken_pipe), + device_or_resource_busy = int(std::errc::device_or_resource_busy), + directory_not_empty = int(std::errc::directory_not_empty), + executable_format_error = int(std::errc::executable_format_error), + file_exists = int(std::errc::file_exists), + file_too_large = int(std::errc::file_too_large), + filename_too_long = int(std::errc::filename_too_long), + function_not_supported = int(std::errc::function_not_supported), + illegal_byte_sequence = int(std::errc::illegal_byte_sequence), + inappropriate_io_control_operation = + int(std::errc::inappropriate_io_control_operation), + interrupted = int(std::errc::interrupted), + invalid_argument = int(std::errc::invalid_argument), + invalid_seek = int(std::errc::invalid_seek), + io_error = int(std::errc::io_error), + is_a_directory = int(std::errc::is_a_directory), + no_child_process = int(std::errc::no_child_process), + no_lock_available = int(std::errc::no_lock_available), + no_space_on_device = int(std::errc::no_space_on_device), + no_such_device_or_address = int(std::errc::no_such_device_or_address), + no_such_device = int(std::errc::no_such_device), + no_such_file_or_directory = int(std::errc::no_such_file_or_directory), + no_such_process = int(std::errc::no_such_process), + not_a_directory = int(std::errc::not_a_directory), + not_enough_memory = int(std::errc::not_enough_memory), + operation_not_permitted = int(std::errc::operation_not_permitted), + permission_denied = int(std::errc::permission_denied), + read_only_file_system = int(std::errc::read_only_file_system), + resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur), + resource_unavailable_try_again = + int(std::errc::resource_unavailable_try_again), + result_out_of_range = int(std::errc::result_out_of_range), + too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system), + too_many_files_open = int(std::errc::too_many_files_open), + too_many_links = int(std::errc::too_many_links) +}; + +inline std::error_code make_error_code(errc E) { + return std::error_code(static_cast(E), std::generic_category()); +} +} + +namespace std { +template <> struct is_error_code_enum : std::true_type {}; +} +#endif diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index ac3a4d8..9afd52d 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -30,9 +30,6 @@ namespace llvm { /// install_fatal_error_handler - Installs a new error handler to be used /// whenever a serious (non-recoverable) error is encountered by LLVM. /// - /// If you are using llvm_start_multithreaded, you should register the handler - /// before doing that. - /// /// If no error handler is installed the default is to print the error message /// to stderr, and call exit(1). If an error handler is installed then it is /// the handler's responsibility to log the message, it will no longer be @@ -50,8 +47,6 @@ namespace llvm { void *user_data = nullptr); /// Restores default error handling behaviour. - /// This must not be called between llvm_start_multithreaded() and - /// llvm_stop_multithreaded(). void remove_fatal_error_handler(); /// ScopedFatalErrorHandler - This is a simple helper class which just diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index becd957..0742a2d 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -18,8 +18,8 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/AlignOf.h" -#include "llvm/Support/system_error.h" #include +#include #include namespace llvm { @@ -94,15 +94,16 @@ private: public: template - ErrorOr(E ErrorCode, typename std::enable_if::value || - is_error_condition_enum::value, - void *>::type = 0) + ErrorOr(E ErrorCode, + typename std::enable_if::value || + std::is_error_condition_enum::value, + void *>::type = 0) : HasError(true) { - new (getErrorStorage()) error_code(make_error_code(ErrorCode)); + new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); } - ErrorOr(llvm::error_code EC) : HasError(true) { - new (getErrorStorage()) error_code(EC); + ErrorOr(std::error_code EC) : HasError(true) { + new (getErrorStorage()) std::error_code(EC); } ErrorOr(T Val) : HasError(false) { @@ -162,8 +163,8 @@ public: reference get() { return *getStorage(); } const_reference get() const { return const_cast >(this)->get(); } - error_code getError() const { - return HasError ? *getErrorStorage() : error_code::success(); + std::error_code getError() const { + return HasError ? *getErrorStorage() : std::error_code(); } pointer operator ->() { @@ -184,7 +185,7 @@ private: } else { // Get other's error. HasError = true; - new (getErrorStorage()) error_code(Other.getError()); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -216,7 +217,7 @@ private: } else { // Get other's error. HasError = true; - new (getErrorStorage()) error_code(Other.getError()); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -247,28 +248,29 @@ private: return reinterpret_cast(TStorage.buffer); } - error_code *getErrorStorage() { + std::error_code *getErrorStorage() { assert(HasError && "Cannot get error when a value exists!"); - return reinterpret_cast(ErrorStorage.buffer); + return reinterpret_cast(ErrorStorage.buffer); } - const error_code *getErrorStorage() const { + const std::error_code *getErrorStorage() const { return const_cast *>(this)->getErrorStorage(); } union { AlignedCharArrayUnion TStorage; - AlignedCharArrayUnion ErrorStorage; + AlignedCharArrayUnion ErrorStorage; }; bool HasError : 1; }; -template -typename std::enable_if::value || - is_error_condition_enum::value, bool>::type -operator ==(ErrorOr &Err, E Code) { - return error_code(Err) == Code; +template +typename std::enable_if::value || + std::is_error_condition_enum::value, + bool>::type +operator==(ErrorOr &Err, E Code) { + return std::error_code(Err) == Code; } } // end namespace llvm diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h deleted file mode 100644 index 8560ee0..0000000 --- a/include/llvm/Support/FEnv.h +++ /dev/null @@ -1,56 +0,0 @@ -//===- llvm/Support/FEnv.h - Host floating-point exceptions ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides an operating system independent interface to -// floating-point exception interfaces. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_FENV_H -#define LLVM_SUPPORT_FENV_H - -#include "llvm/Config/config.h" -#include -#ifdef HAVE_FENV_H -#include -#endif - -// FIXME: Clang's #include handling apparently doesn't work for libstdc++'s -// fenv.h; see PR6907 for details. -#if defined(__clang__) && defined(_GLIBCXX_FENV_H) -#undef HAVE_FENV_H -#endif - -namespace llvm { -namespace sys { - -/// llvm_fenv_clearexcept - Clear the floating-point exception state. -static inline void llvm_fenv_clearexcept() { -#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT - feclearexcept(FE_ALL_EXCEPT); -#endif - errno = 0; -} - -/// llvm_fenv_testexcept - Test if a floating-point exception was raised. -static inline bool llvm_fenv_testexcept() { - int errno_val = errno; - if (errno_val == ERANGE || errno_val == EDOM) - return true; -#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT && HAVE_DECL_FE_INEXACT - if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) - return true; -#endif - return false; -} - -} // End sys namespace -} // End llvm namespace - -#endif diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index a8a48fa..0a9a979 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -20,8 +20,6 @@ #include "llvm/Support/FileSystem.h" namespace llvm { -class error_code; - /// FileOutputBuffer - This interface provides simple way to create an in-memory /// buffer which will be written to a file. During the lifetime of these /// objects, the content or existence of the specified file is undefined. That @@ -39,9 +37,9 @@ public: /// Factory method to create an OutputBuffer object which manages a read/write /// buffer of the specified size. When committed, the buffer will be written /// to the file at the specified path. - static error_code create(StringRef FilePath, size_t Size, - std::unique_ptr &Result, - unsigned Flags = 0); + static std::error_code create(StringRef FilePath, size_t Size, + std::unique_ptr &Result, + unsigned Flags = 0); /// Returns a pointer to the start of the buffer. uint8_t *getBufferStart() { @@ -68,7 +66,7 @@ public: /// is called, the file is deleted in the destructor. The optional parameter /// is used if it turns out you want the file size to be smaller than /// initially requested. - error_code commit(int64_t NewSmallerSize = -1); + std::error_code commit(int64_t NewSmallerSize = -1); /// If this object was previously committed, the destructor just deletes /// this object. If this object was not committed, the destructor diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 806a3e3..556701c 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -33,11 +33,11 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeValue.h" -#include "llvm/Support/system_error.h" #include #include #include #include +#include #include #include @@ -49,26 +49,18 @@ namespace llvm { namespace sys { namespace fs { -/// An "enum class" enumeration for the file system's view of the type. -struct file_type { - enum Impl { - status_error, - file_not_found, - regular_file, - directory_file, - symlink_file, - block_file, - character_file, - fifo_file, - socket_file, - type_unknown - }; - - file_type(Impl V) : V(V) {} - operator Impl() const { return V; } - -private: - Impl V; +/// An enumeration for the file system's view of the type. +enum class file_type { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown }; /// space_info - Self explanatory. @@ -142,7 +134,7 @@ public: }; /// file_status - Represents the result of a call to stat and friends. It has -/// a platform specific member to store the result. +/// a platform-specific member to store the result. class file_status { #if defined(LLVM_ON_UNIX) @@ -281,8 +273,8 @@ private: /// /// @param path A path that is modified to be an absolute path. /// @returns errc::success if \a path has been made absolute, otherwise a -/// platform specific error_code. -error_code make_absolute(SmallVectorImpl &path); +/// platform-specific error_code. +std::error_code make_absolute(SmallVectorImpl &path); /// @brief Normalize path separators in \a Path /// @@ -290,7 +282,7 @@ error_code make_absolute(SmallVectorImpl &path); /// This is particularly useful when cross-compiling Windows on Linux, but is /// safe to invoke on Windows, which accepts both characters as a path /// separator. -error_code normalize_separators(SmallVectorImpl &Path); +std::error_code normalize_separators(SmallVectorImpl &Path); /// @brief Create all the non-existent directories in path. /// @@ -298,7 +290,8 @@ error_code normalize_separators(SmallVectorImpl &Path); /// @returns errc::success if is_directory(path), otherwise a platform /// specific error_code. If IgnoreExisting is false, also returns /// error if the directory already existed. -error_code create_directories(const Twine &path, bool IgnoreExisting = true); +std::error_code create_directories(const Twine &path, + bool IgnoreExisting = true); /// @brief Create the directory in path. /// @@ -306,7 +299,7 @@ error_code create_directories(const Twine &path, bool IgnoreExisting = true); /// @returns errc::success if is_directory(path), otherwise a platform /// specific error_code. If IgnoreExisting is false, also returns /// error if the directory already existed. -error_code create_directory(const Twine &path, bool IgnoreExisting = true); +std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); /// @brief Create a link from \a from to \a to. /// @@ -319,36 +312,42 @@ error_code create_directory(const Twine &path, bool IgnoreExisting = true); /// @param from The path to hard link from. This is created. /// @returns errc::success if the link was created, otherwise a platform /// specific error_code. -error_code create_link(const Twine &to, const Twine &from); +std::error_code create_link(const Twine &to, const Twine &from); /// @brief Get the current path. /// /// @param result Holds the current path on return. /// @returns errc::success if the current path has been stored in result, -/// otherwise a platform specific error_code. -error_code current_path(SmallVectorImpl &result); +/// otherwise a platform-specific error_code. +std::error_code current_path(SmallVectorImpl &result); /// @brief Remove path. Equivalent to POSIX remove(). /// /// @param path Input path. /// @returns errc::success if path has been removed or didn't exist, otherwise a -/// platform specific error code. If IgnoreNonExisting is false, also +/// platform-specific error code. If IgnoreNonExisting is false, also /// returns error if the file didn't exist. -error_code remove(const Twine &path, bool IgnoreNonExisting = true); +std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). /// /// @param from The path to rename from. /// @param to The path to rename to. This is created. -error_code rename(const Twine &from, const Twine &to); +std::error_code rename(const Twine &from, const Twine &to); + +/// @brief Copy the contents of \a From to \a To. +/// +/// @param From The path to copy from. +/// @param To The path to copy to. This is created. +std::error_code copy_file(const Twine &From, const Twine &To); /// @brief Resize path to size. File is resized as if by POSIX truncate(). /// /// @param path Input path. /// @param size Size to resize to. /// @returns errc::success if \a path has been resized to \a size, otherwise a -/// platform specific error_code. -error_code resize_file(const Twine &path, uint64_t size); +/// platform-specific error_code. +std::error_code resize_file(const Twine &path, uint64_t size); /// @} /// @name Physical Observers @@ -367,8 +366,8 @@ bool exists(file_status status); /// @param result Set to true if the file represented by status exists, false if /// it does not. Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code exists(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code exists(const Twine &path, bool &result); /// @brief Simpler version of exists for clients that don't need to /// differentiate between an error and false. @@ -409,8 +408,8 @@ bool equivalent(file_status A, file_status B); /// @param result Set to true if stat(A) and stat(B) have the same device and /// inode (or equivalent). /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code equivalent(const Twine &A, const Twine &B, bool &result); +/// platform-specific error_code. +std::error_code equivalent(const Twine &A, const Twine &B, bool &result); /// @brief Simpler version of equivalent for clients that don't need to /// differentiate between an error and false. @@ -431,8 +430,8 @@ bool is_directory(file_status status); /// @param result Set to true if \a path is a directory, false if it is not. /// Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_directory(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_directory(const Twine &path, bool &result); /// @brief Simpler version of is_directory for clients that don't need to /// differentiate between an error and false. @@ -453,8 +452,8 @@ bool is_regular_file(file_status status); /// @param result Set to true if \a path is a regular file, false if it is not. /// Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_regular_file(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_regular_file(const Twine &path, bool &result); /// @brief Simpler version of is_regular_file for clients that don't need to /// differentiate between an error and false. @@ -479,41 +478,41 @@ bool is_other(file_status status); /// @param result Set to true if \a path exists, but is not a directory, regular /// file, or a symlink, false if it does not. Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_other(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_other(const Twine &path, bool &result); /// @brief Get file status as if by POSIX stat(). /// /// @param path Input path. /// @param result Set to the file status. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code status(const Twine &path, file_status &result); +/// platform-specific error_code. +std::error_code status(const Twine &path, file_status &result); /// @brief A version for when a file descriptor is already available. -error_code status(int FD, file_status &Result); +std::error_code status(int FD, file_status &Result); /// @brief Get file size. /// /// @param Path Input path. /// @param Result Set to the size of the file in \a Path. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -inline error_code file_size(const Twine &Path, uint64_t &Result) { +/// platform-specific error_code. +inline std::error_code file_size(const Twine &Path, uint64_t &Result) { file_status Status; - error_code EC = status(Path, Status); + std::error_code EC = status(Path, Status); if (EC) return EC; Result = Status.getSize(); - return error_code::success(); + return std::error_code(); } /// @brief Set the file modification and access time. /// /// @returns errc::success if the file times were successfully set, otherwise a -/// platform specific error_code or errc::not_supported on platforms -/// where the functionality isn't available. -error_code setLastModificationAndAccessTime(int FD, TimeValue Time); +/// platform-specific error_code or errc::function_not_supported on +/// platforms where the functionality isn't available. +std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); /// @brief Is status available? /// @@ -526,8 +525,8 @@ bool status_known(file_status s); /// @param path Input path. /// @param result Set to true if status() != status_error. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code status_known(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code status_known(const Twine &path, bool &result); /// @brief Create a uniquely named file. /// @@ -549,14 +548,14 @@ error_code status_known(const Twine &path, bool &result); /// @param ResultFD Set to the opened file's file descriptor. /// @param ResultPath Set to the opened file's absolute path. /// @returns errc::success if Result{FD,Path} have been successfully set, -/// otherwise a platform specific error_code. -error_code createUniqueFile(const Twine &Model, int &ResultFD, - SmallVectorImpl &ResultPath, - unsigned Mode = all_read | all_write); +/// otherwise a platform-specific error_code. +std::error_code createUniqueFile(const Twine &Model, int &ResultFD, + SmallVectorImpl &ResultPath, + unsigned Mode = all_read | all_write); /// @brief Simpler version for clients that don't want an open file. -error_code createUniqueFile(const Twine &Model, - SmallVectorImpl &ResultPath); +std::error_code createUniqueFile(const Twine &Model, + SmallVectorImpl &ResultPath); /// @brief Create a file in the system temporary directory. /// @@ -566,16 +565,16 @@ error_code createUniqueFile(const Twine &Model, /// /// This should be used for things like a temporary .s that is removed after /// running the assembler. -error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - int &ResultFD, - SmallVectorImpl &ResultPath); +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + int &ResultFD, + SmallVectorImpl &ResultPath); /// @brief Simpler version for clients that don't want an open file. -error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - SmallVectorImpl &ResultPath); +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl &ResultPath); -error_code createUniqueDirectory(const Twine &Prefix, - SmallVectorImpl &ResultPath); +std::error_code createUniqueDirectory(const Twine &Prefix, + SmallVectorImpl &ResultPath); enum OpenFlags : unsigned { F_None = 0, @@ -606,31 +605,10 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { return A; } -error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, - unsigned Mode = 0666); +std::error_code openFileForWrite(const Twine &Name, int &ResultFD, + OpenFlags Flags, unsigned Mode = 0666); -error_code openFileForRead(const Twine &Name, int &ResultFD); - -/// @brief Are \a path's first bytes \a magic? -/// -/// @param path Input path. -/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code has_magic(const Twine &path, const Twine &magic, bool &result); - -/// @brief Get \a path's first \a len bytes. -/// -/// @param path Input path. -/// @param len Number of magic bytes to get. -/// @param result Set to the first \a len bytes in the file pointed to by -/// \a path. Or the entire file if file_size(path) < len, in which -/// case result.size() returns the size of the file. -/// @returns errc::success if result has been successfully set, -/// errc::value_too_large if len is larger then the file pointed to by -/// \a path, otherwise a platform specific error_code. -error_code get_magic(const Twine &path, uint32_t len, - SmallVectorImpl &result); +std::error_code openFileForRead(const Twine &Name, int &ResultFD); /// @brief Identify the type of a binary file based on how magical it is. file_magic identify_magic(StringRef magic); @@ -640,10 +618,10 @@ file_magic identify_magic(StringRef magic); /// @param path Input path. /// @param result Set to the type of file, or file_magic::unknown. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code identify_magic(const Twine &path, file_magic &result); +/// platform-specific error_code. +std::error_code identify_magic(const Twine &path, file_magic &result); -error_code getUniqueID(const Twine Path, UniqueID &Result); +std::error_code getUniqueID(const Twine Path, UniqueID &Result); /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. @@ -660,7 +638,7 @@ public: }; private: - /// Platform specific mapping state. + /// Platform-specific mapping state. mapmode Mode; uint64_t Size; void *Mapping; @@ -670,7 +648,7 @@ private: void *FileMappingHandle; #endif - error_code init(int FD, bool CloseFD, uint64_t Offset); + std::error_code init(int FD, bool CloseFD, uint64_t Offset); public: typedef char char_type; @@ -692,21 +670,14 @@ public: /// mapped_file_region::alignment(). /// \param ec This is set to errc::success if the map was constructed /// successfully. Otherwise it is set to a platform dependent error. - mapped_file_region(const Twine &path, - mapmode mode, - uint64_t length, - uint64_t offset, - error_code &ec); + mapped_file_region(const Twine &path, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec); /// \param fd An open file descriptor to map. mapped_file_region takes /// ownership if closefd is true. It must have been opended in the correct /// mode. - mapped_file_region(int fd, - bool closefd, - mapmode mode, - uint64_t length, - uint64_t offset, - error_code &ec); + mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec); ~mapped_file_region(); @@ -722,30 +693,6 @@ public: static int alignment(); }; -/// @brief Memory maps the contents of a file -/// -/// @param path Path to file to map. -/// @param file_offset Byte offset in file where mapping should begin. -/// @param size Byte length of range of the file to map. -/// @param map_writable If true, the file will be mapped in r/w such -/// that changes to the mapped buffer will be flushed back -/// to the file. If false, the file will be mapped read-only -/// and the buffer will be read-only. -/// @param result Set to the start address of the mapped buffer. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, - bool map_writable, void *&result); - - -/// @brief Memory unmaps the contents of a file -/// -/// @param base Pointer to the start of the buffer. -/// @param size Byte length of the range to unmmap. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code unmap_file_pages(void *base, size_t size); - /// Return the path to the main executable, given the value of argv[0] from /// program startup and the address of main itself. In extremis, this function /// may fail and return an empty path. @@ -777,7 +724,7 @@ public: void replace_filename(const Twine &filename, file_status st = file_status()); const std::string &path() const { return Path; } - error_code status(file_status &result) const; + std::error_code status(file_status &result) const; bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } @@ -790,9 +737,9 @@ public: namespace detail { struct DirIterState; - error_code directory_iterator_construct(DirIterState&, StringRef); - error_code directory_iterator_increment(DirIterState&); - error_code directory_iterator_destruct(DirIterState&); + std::error_code directory_iterator_construct(DirIterState &, StringRef); + std::error_code directory_iterator_increment(DirIterState &); + std::error_code directory_iterator_destruct(DirIterState &); /// DirIterState - Keeps state for the directory_iterator. It is reference /// counted in order to preserve InputIterator semantics on copy. @@ -816,14 +763,14 @@ class directory_iterator { IntrusiveRefCntPtr State; public: - explicit directory_iterator(const Twine &path, error_code &ec) { + explicit directory_iterator(const Twine &path, std::error_code &ec) { State = new detail::DirIterState; SmallString<128> path_storage; ec = detail::directory_iterator_construct(*State, path.toStringRef(path_storage)); } - explicit directory_iterator(const directory_entry &de, error_code &ec) { + explicit directory_iterator(const directory_entry &de, std::error_code &ec) { State = new detail::DirIterState; ec = detail::directory_iterator_construct(*State, de.path()); } @@ -832,7 +779,7 @@ public: directory_iterator() : State(nullptr) {} // No operator++ because we need error_code. - directory_iterator &increment(error_code &ec) { + directory_iterator &increment(std::error_code &ec) { ec = directory_iterator_increment(*State); return *this; } @@ -878,14 +825,14 @@ class recursive_directory_iterator { public: recursive_directory_iterator() {} - explicit recursive_directory_iterator(const Twine &path, error_code &ec) - : State(new detail::RecDirIterState) { + explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) + : State(new detail::RecDirIterState) { State->Stack.push(directory_iterator(path, ec)); if (State->Stack.top() == directory_iterator()) State.reset(); } // No operator++ because we need error_code. - recursive_directory_iterator &increment(error_code &ec) { + recursive_directory_iterator &increment(std::error_code &ec) { const directory_iterator end_itr; if (State->HasNoPushRequest) @@ -934,7 +881,7 @@ public: assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); const directory_iterator end_itr; - error_code ec; + std::error_code ec; do { if (ec) report_fatal_error("Error incrementing directory iterator."); diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index a62801f..b713cc7 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -36,23 +36,23 @@ namespace llvm { -/// format_object_base - This is a helper class used for handling formatted -/// output. It is the abstract base class of a templated derived class. +/// This is a helper class used for handling formatted output. It is the +/// abstract base class of a templated derived class. class format_object_base { protected: const char *Fmt; virtual void home(); // Out of line virtual method. - /// snprint - Call snprintf() for this object, on the given buffer and size. + /// Call snprintf() for this object, on the given buffer and size. virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; public: format_object_base(const char *fmt) : Fmt(fmt) {} virtual ~format_object_base() {} - /// print - Format the object into the specified buffer. On success, this - /// returns the length of the formatted string. If the buffer is too small, - /// this returns a length to retry with, which will be larger than BufferSize. + /// Format the object into the specified buffer. On success, this returns + /// the length of the formatted string. If the buffer is too small, this + /// returns a length to retry with, which will be larger than BufferSize. unsigned print(char *Buffer, unsigned BufferSize) const { assert(BufferSize && "Invalid buffer size!"); @@ -61,21 +61,23 @@ public: // VC++ and old GlibC return negative on overflow, just double the size. if (N < 0) - return BufferSize*2; + return BufferSize * 2; - // Other impls yield number of bytes needed, not including the final '\0'. + // Other implementations yield number of bytes needed, not including the + // final '\0'. if (unsigned(N) >= BufferSize) - return N+1; + return N + 1; // Otherwise N is the length of output (not including the final '\0'). return N; } }; -/// format_object1 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. +/// These are templated helper classes used by the format function that +/// capture the object to be formated and the format string. When actually +/// printed, this synthesizes the string into a temporary buffer provided and +/// returns whether or not it is big enough. + template class format_object1 : public format_object_base { T Val; @@ -89,10 +91,6 @@ public: } }; -/// format_object2 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template class format_object2 : public format_object_base { T1 Val1; @@ -107,10 +105,6 @@ public: } }; -/// format_object3 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template class format_object3 : public format_object_base { T1 Val1; @@ -126,10 +120,6 @@ public: } }; -/// format_object4 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template class format_object4 : public format_object_base { T1 Val1; @@ -147,10 +137,6 @@ public: } }; -/// format_object5 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template class format_object5 : public format_object_base { T1 Val1; @@ -170,47 +156,52 @@ public: } }; -/// This is a helper function that is used to produce formatted output. +template +class format_object6 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; + T5 Val5; + T6 Val6; +public: + format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, + const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) + : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), + Val5(Val5), Val6(Val6) { } + + int snprint(char *Buffer, unsigned BufferSize) const override { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); + } +}; + +/// These are helper functions used to produce formatted output. They use +/// template type deduction to construct the appropriate instance of the +/// format_object class to simplify their construction. /// /// This is typically used like: /// \code /// OS << format("%0.4f", myfloat) << '\n'; /// \endcode + template inline format_object1 format(const char *Fmt, const T &Val) { return format_object1(Fmt, Val); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template inline format_object2 format(const char *Fmt, const T1 &Val1, const T2 &Val2) { return format_object2(Fmt, Val1, Val2); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template inline format_object3 format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3) { return format_object3(Fmt, Val1, Val2, Val3); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template inline format_object4 format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -218,12 +209,6 @@ inline format_object4 format(const char *Fmt, const T1 &Val1, return format_object4(Fmt, Val1, Val2, Val3, Val4); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template inline format_object5 format(const char *Fmt,const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -231,6 +216,15 @@ inline format_object5 format(const char *Fmt,const T1 &Val1, return format_object5(Fmt, Val1, Val2, Val3, Val4, Val5); } +template +inline format_object6 +format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, + const T4 &Val4, const T5 &Val5, const T6 &Val6) { + return format_object6(Fmt, Val1, Val2, Val3, Val4, + Val5, Val6); +} + } // end namespace llvm #endif diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index e344220..876ab6e 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -330,6 +330,10 @@ public: return DomTreeNodes.lookup(BB); } + inline DomTreeNodeBase *operator[](NodeT *BB) const { + return getNode(BB); + } + /// getRootNode - This returns the entry node for the CFG of the function. If /// this tree represents the post-dominance relations for a function, however, /// this root may be a node with the block == NULL. This is the case when diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 539673a..2f02aa7 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -50,7 +50,7 @@ namespace GraphProgram { }; } -void DisplayGraph(StringRef Filename, bool wait = true, +bool DisplayGraph(StringRef Filename, bool wait = true, GraphProgram::Name program = GraphProgram::DOT); template diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 523a781..61c65da 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -12,11 +12,10 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/system_error.h" +#include #include // for std::pair namespace llvm { - /// \brief Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// @@ -56,7 +55,7 @@ private: SmallString<128> UniqueLockFileName; Optional > Owner; - Optional Error; + Optional Error; LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION; LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 2a0fc7b..bd4dc2f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -360,11 +360,28 @@ namespace llvm { enum { // Constant masks for the "n_desc" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 + // The low 3 bits are the for the REFERENCE_TYPE. + REFERENCE_TYPE = 0x7, + REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, + REFERENCE_FLAG_UNDEFINED_LAZY = 1, + REFERENCE_FLAG_DEFINED = 2, + REFERENCE_FLAG_PRIVATE_DEFINED = 3, + REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, + REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5, + // Flag bits (some overlap with the library ordinal bits). N_ARM_THUMB_DEF = 0x0008u, + REFERENCED_DYNAMICALLY = 0x0010u, N_NO_DEAD_STRIP = 0x0020u, N_WEAK_REF = 0x0040u, N_WEAK_DEF = 0x0080u, - N_SYMBOL_RESOLVER = 0x0100u + N_SYMBOL_RESOLVER = 0x0100u, + N_ALT_ENTRY = 0x0200u, + // For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL() + // as these are in the top 8 bits. + SELF_LIBRARY_ORDINAL = 0x0, + MAX_LIBRARY_ORDINAL = 0xfd, + DYNAMIC_LOOKUP_ORDINAL = 0xfe, + EXECUTABLE_ORDINAL = 0xff }; enum StabType { @@ -998,8 +1015,8 @@ namespace llvm { enum : uint32_t { // Capability bits used in the definition of cpusubtype. - CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits - CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries + CPU_SUBTYPE_MASK = 0xff000000, // Mask for architecture bits + CPU_SUBTYPE_LIB64 = 0x80000000, // 64 bit libraries // Special CPU subtype constants. CPU_SUBTYPE_MULTIPLE = ~0u diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index 1bb8cea..d8fbfeb 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -103,9 +103,6 @@ void llvm_shutdown(); /// llvm_shutdown() when it is destroyed. struct llvm_shutdown_obj { llvm_shutdown_obj() { } - explicit llvm_shutdown_obj(bool multithreaded) { - if (multithreaded) llvm_start_multithreaded(); - } ~llvm_shutdown_obj() { llvm_shutdown(); } }; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index f1f7b4f..0abba62 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -230,6 +230,9 @@ static const unsigned char BitReverseTable256[256] = { #define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) #define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) R6(0), R6(2), R6(1), R6(3) +#undef R2 +#undef R4 +#undef R6 }; /// \brief Reverse the bits in \p Val. @@ -258,6 +261,12 @@ inline uint32_t Lo_32(uint64_t Value) { return static_cast(Value); } +/// Make_64 - This functions makes a 64-bit integer from a high / low pair of +/// 32-bit integers. +inline uint64_t Make_64(uint32_t High, uint32_t Low) { + return ((uint64_t)High << 32) | (uint64_t)Low; +} + /// isInt - Checks if an integer fits into the given bit width. template inline bool isInt(int64_t x) { diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index 0996adb..b4305cb 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -15,8 +15,8 @@ #define LLVM_SUPPORT_MEMORY_H #include "llvm/Support/DataTypes.h" -#include "llvm/Support/system_error.h" #include +#include namespace llvm { namespace sys { @@ -77,7 +77,7 @@ namespace sys { static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, - error_code &EC); + std::error_code &EC); /// This method releases a block of memory that was allocated with the /// allocateMappedMemory method. It should not be used to release any @@ -88,7 +88,7 @@ namespace sys { /// describing the failure if an error occurred. /// /// @brief Release mapped memory. - static error_code releaseMappedMemory(MemoryBlock &Block); + static std::error_code releaseMappedMemory(MemoryBlock &Block); /// This method sets the protection flags for a block of memory to the /// state specified by /p Flags. The behavior is not specified if the @@ -105,8 +105,8 @@ namespace sys { /// describing the failure if an error occurred. /// /// @brief Set memory protection state. - static error_code protectMappedMemory(const MemoryBlock &Block, - unsigned Flags); + static std::error_code protectMappedMemory(const MemoryBlock &Block, + unsigned Flags); /// This method allocates a block of Read/Write/Execute memory that is /// suitable for executing dynamically generated code (e.g. JIT). An diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 5810c47..147be47 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -19,12 +19,11 @@ #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorOr.h" #include +#include namespace llvm { - -class error_code; - /// MemoryBuffer - This interface provides simple read-only access to a block /// of memory, and provides simple methods for reading files and standard input /// into a memory buffer. In addition to basic access to the characters in the @@ -62,19 +61,17 @@ public: return "Unknown buffer"; } - /// getFile - Open the specified file as a MemoryBuffer, returning a new - /// MemoryBuffer if successful, otherwise returning null. If FileSize is - /// specified, this means that the client knows that the file exists and that - /// it has the specified size. + /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer + /// if successful, otherwise returning null. If FileSize is specified, this + /// means that the client knows that the file exists and that it has the + /// specified size. /// /// \param IsVolatileSize Set to true to indicate that the file size may be /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. - static error_code getFile(Twine Filename, - std::unique_ptr &Result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true, - bool IsVolatileSize = false); + static ErrorOr> + getFile(Twine Filename, int64_t FileSize = -1, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// Given an already-open file descriptor, map some slice of it into a /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. @@ -83,10 +80,9 @@ public: /// \param IsVolatileSize Set to true to indicate that the file size may be /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. - static error_code getOpenFileSlice(int FD, const char *Filename, - std::unique_ptr &Result, - uint64_t MapSize, int64_t Offset, - bool IsVolatileSize = false); + static ErrorOr> + getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, + int64_t Offset, bool IsVolatileSize = false); /// Given an already-open file descriptor, read the file and return a /// MemoryBuffer. @@ -94,11 +90,9 @@ public: /// \param IsVolatileSize Set to true to indicate that the file size may be /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. - static error_code getOpenFile(int FD, const char *Filename, - std::unique_ptr &Result, - uint64_t FileSize, - bool RequiresNullTerminator = true, - bool IsVolatileSize = false); + static ErrorOr> + getOpenFile(int FD, const char *Filename, uint64_t FileSize, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that InputData must be null terminated if RequiresNullTerminator is true. @@ -125,17 +119,13 @@ public: static MemoryBuffer *getNewUninitMemBuffer(size_t Size, StringRef BufferName = ""); - /// getSTDIN - Read all of stdin into a file buffer, and return it. - /// If an error occurs, this returns null and sets ec. - static error_code getSTDIN(std::unique_ptr &Result); - + /// Read all of stdin into a file buffer, and return it. + static ErrorOr> getSTDIN(); - /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin - /// if the Filename is "-". If an error occurs, this returns null and sets - /// ec. - static error_code getFileOrSTDIN(StringRef Filename, - std::unique_ptr &Result, - int64_t FileSize = -1); + /// Open the specified file as a MemoryBuffer, or open stdin if the Filename + /// is "-". + static ErrorOr> + getFileOrSTDIN(StringRef Filename, int64_t FileSize = -1); //===--------------------------------------------------------------------===// // Provided for performance analysis. diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 7f6441e..30973de 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -31,7 +31,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" -#include "llvm/Support/system_error.h" +#include namespace llvm { class StringRef; @@ -171,10 +171,17 @@ public: // string. \arg Name is assumed to be in UTF-8 encoding too. static Optional GetEnv(StringRef name); + /// This function searches for an existing file in the list of directories + /// in a PATH like environment variable, and returns the first file found, + /// according to the order of the entries in the PATH like environment + /// variable. + static Optional FindInEnvPath(const std::string& EnvName, + const std::string& FileName); + /// This function returns a SmallVector containing the arguments passed from /// the operating system to the program. This function expects to be handed /// the vector passed in from main. - static error_code + static std::error_code GetArgumentVector(SmallVectorImpl &Args, ArrayRef ArgsFromMain, SpecificBumpPtrAllocator &ArgAllocator); diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 9160b7d..51279a9 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -16,10 +16,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Path.h" -#include "llvm/Support/system_error.h" +#include namespace llvm { -class error_code; namespace sys { /// This is the OS-specific separator for PATH like environment variables: @@ -67,8 +66,8 @@ struct ProcessInfo { // These functions change the specified standard stream (stdin or stdout) to // binary mode. They return errc::success if the specified stream // was changed. Otherwise a platform dependent error is returned. - error_code ChangeStdinToBinary(); - error_code ChangeStdoutToBinary(); + std::error_code ChangeStdinToBinary(); + std::error_code ChangeStdoutToBinary(); /// This function executes the program using the arguments provided. The /// invoked program will inherit the stdin, stdout, and stderr file diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h new file mode 100644 index 0000000..cadc713 --- /dev/null +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -0,0 +1,57 @@ +//==- llvm/Support/RandomNumberGenerator.h - RNG for diversity ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an abstraction for random number generation (RNG). +// Note that the current implementation is not cryptographically secure +// as it uses the C++11 facilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_ +#define LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" // Needed for uint64_t on Windows. +#include + +namespace llvm { + +/// A random number generator. +/// Instances of this class should not be shared across threads. +class RandomNumberGenerator { +public: + /// Seeds and salts the underlying RNG engine. The salt of type StringRef + /// is passed into the constructor. The seed can be set on the command + /// line via -rng-seed=. + /// The reason for the salt is to ensure different random streams even if + /// the same seed is used for multiple invocations of the compiler. + /// A good salt value should add additional entropy and be constant across + /// different machines (i.e., no paths) to allow for reproducible builds. + /// An instance of this class can be retrieved from the current Module. + /// \see Module::getRNG + RandomNumberGenerator(StringRef Salt); + + /// Returns a random number in the range [0, Max). + uint64_t next(uint64_t Max); + +private: + // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000 + // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine + std::mt19937_64 Generator; + + // Noncopyable. + RandomNumberGenerator(const RandomNumberGenerator &other) + LLVM_DELETED_FUNCTION; + RandomNumberGenerator & + operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION; +}; +} + +#endif diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h new file mode 100644 index 0000000..2bd7e74 --- /dev/null +++ b/include/llvm/Support/ScaledNumber.h @@ -0,0 +1,897 @@ +//===- llvm/Support/ScaledNumber.h - Support for scaled numbers -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions (and a class) useful for working with scaled +// numbers -- in particular, pairs of integers where one represents digits and +// another represents a scale. The functions are helpers and live in the +// namespace ScaledNumbers. The class ScaledNumber is useful for modelling +// certain cost metrics that need simple, integer-like semantics that are easy +// to reason about. +// +// These might remind you of soft-floats. If you want one of those, you're in +// the wrong place. Look at include/llvm/ADT/APFloat.h instead. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SCALEDNUMBER_H +#define LLVM_SUPPORT_SCALEDNUMBER_H + +#include "llvm/Support/MathExtras.h" + +#include +#include +#include +#include +#include +#include + +namespace llvm { +namespace ScaledNumbers { + +/// \brief Maximum scale; same as APFloat for easy debug printing. +const int32_t MaxScale = 16383; + +/// \brief Maximum scale; same as APFloat for easy debug printing. +const int32_t MinScale = -16382; + +/// \brief Get the width of a number. +template inline int getWidth() { return sizeof(DigitsT) * 8; } + +/// \brief Conditionally round up a scaled number. +/// +/// Given \c Digits and \c Scale, round up iff \c ShouldRound is \c true. +/// Always returns \c Scale unless there's an overflow, in which case it +/// returns \c 1+Scale. +/// +/// \pre adding 1 to \c Scale will not overflow INT16_MAX. +template +inline std::pair getRounded(DigitsT Digits, int16_t Scale, + bool ShouldRound) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + if (ShouldRound) + if (!++Digits) + // Overflow. + return std::make_pair(DigitsT(1) << (getWidth() - 1), Scale + 1); + return std::make_pair(Digits, Scale); +} + +/// \brief Convenience helper for 32-bit rounding. +inline std::pair getRounded32(uint32_t Digits, int16_t Scale, + bool ShouldRound) { + return getRounded(Digits, Scale, ShouldRound); +} + +/// \brief Convenience helper for 64-bit rounding. +inline std::pair getRounded64(uint64_t Digits, int16_t Scale, + bool ShouldRound) { + return getRounded(Digits, Scale, ShouldRound); +} + +/// \brief Adjust a 64-bit scaled number down to the appropriate width. +/// +/// \pre Adding 64 to \c Scale will not overflow INT16_MAX. +template +inline std::pair getAdjusted(uint64_t Digits, + int16_t Scale = 0) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + const int Width = getWidth(); + if (Width == 64 || Digits <= std::numeric_limits::max()) + return std::make_pair(Digits, Scale); + + // Shift right and round. + int Shift = 64 - Width - countLeadingZeros(Digits); + return getRounded(Digits >> Shift, Scale + Shift, + Digits & (UINT64_C(1) << (Shift - 1))); +} + +/// \brief Convenience helper for adjusting to 32 bits. +inline std::pair getAdjusted32(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted(Digits, Scale); +} + +/// \brief Convenience helper for adjusting to 64 bits. +inline std::pair getAdjusted64(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted(Digits, Scale); +} + +/// \brief Multiply two 64-bit integers to create a 64-bit scaled number. +/// +/// Implemented with four 64-bit integer multiplies. +std::pair multiply64(uint64_t LHS, uint64_t RHS); + +/// \brief Multiply two 32-bit integers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer multiply. +template +inline std::pair getProduct(DigitsT LHS, DigitsT RHS) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + if (getWidth() <= 32 || (LHS <= UINT32_MAX && RHS <= UINT32_MAX)) + return getAdjusted(uint64_t(LHS) * RHS); + + return multiply64(LHS, RHS); +} + +/// \brief Convenience helper for 32-bit product. +inline std::pair getProduct32(uint32_t LHS, uint32_t RHS) { + return getProduct(LHS, RHS); +} + +/// \brief Convenience helper for 64-bit product. +inline std::pair getProduct64(uint64_t LHS, uint64_t RHS) { + return getProduct(LHS, RHS); +} + +/// \brief Divide two 64-bit integers to create a 64-bit scaled number. +/// +/// Implemented with long division. +/// +/// \pre \c Dividend and \c Divisor are non-zero. +std::pair divide64(uint64_t Dividend, uint64_t Divisor); + +/// \brief Divide two 32-bit integers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer divide/remainder pair. +/// +/// \pre \c Dividend and \c Divisor are non-zero. +std::pair divide32(uint32_t Dividend, uint32_t Divisor); + +/// \brief Divide two 32-bit numbers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer divide/remainder pair. +/// +/// Returns \c (DigitsT_MAX, MaxScale) for divide-by-zero (0 for 0/0). +template +std::pair getQuotient(DigitsT Dividend, DigitsT Divisor) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + static_assert(sizeof(DigitsT) == 4 || sizeof(DigitsT) == 8, + "expected 32-bit or 64-bit digits"); + + // Check for zero. + if (!Dividend) + return std::make_pair(0, 0); + if (!Divisor) + return std::make_pair(std::numeric_limits::max(), MaxScale); + + if (getWidth() == 64) + return divide64(Dividend, Divisor); + return divide32(Dividend, Divisor); +} + +/// \brief Convenience helper for 32-bit quotient. +inline std::pair getQuotient32(uint32_t Dividend, + uint32_t Divisor) { + return getQuotient(Dividend, Divisor); +} + +/// \brief Convenience helper for 64-bit quotient. +inline std::pair getQuotient64(uint64_t Dividend, + uint64_t Divisor) { + return getQuotient(Dividend, Divisor); +} + +/// \brief Implementation of getLg() and friends. +/// +/// Returns the rounded lg of \c Digits*2^Scale and an int specifying whether +/// this was rounded up (1), down (-1), or exact (0). +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template +inline std::pair getLgImpl(DigitsT Digits, int16_t Scale) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + if (!Digits) + return std::make_pair(INT32_MIN, 0); + + // Get the floor of the lg of Digits. + int32_t LocalFloor = sizeof(Digits) * 8 - countLeadingZeros(Digits) - 1; + + // Get the actual floor. + int32_t Floor = Scale + LocalFloor; + if (Digits == UINT64_C(1) << LocalFloor) + return std::make_pair(Floor, 0); + + // Round based on the next digit. + assert(LocalFloor >= 1); + bool Round = Digits & UINT64_C(1) << (LocalFloor - 1); + return std::make_pair(Floor + Round, Round ? 1 : -1); +} + +/// \brief Get the lg (rounded) of a scaled number. +/// +/// Get the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template int32_t getLg(DigitsT Digits, int16_t Scale) { + return getLgImpl(Digits, Scale).first; +} + +/// \brief Get the lg floor of a scaled number. +/// +/// Get the floor of the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template int32_t getLgFloor(DigitsT Digits, int16_t Scale) { + auto Lg = getLgImpl(Digits, Scale); + return Lg.first - (Lg.second > 0); +} + +/// \brief Get the lg ceiling of a scaled number. +/// +/// Get the ceiling of the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template int32_t getLgCeiling(DigitsT Digits, int16_t Scale) { + auto Lg = getLgImpl(Digits, Scale); + return Lg.first + (Lg.second < 0); +} + +/// \brief Implementation for comparing scaled numbers. +/// +/// Compare two 64-bit numbers with different scales. Given that the scale of +/// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1, +/// 1, and 0 for less than, greater than, and equal, respectively. +/// +/// \pre 0 <= ScaleDiff < 64. +int compareImpl(uint64_t L, uint64_t R, int ScaleDiff); + +/// \brief Compare two scaled numbers. +/// +/// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1 +/// for greater than. +template +int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + // Check for zero. + if (!LDigits) + return RDigits ? -1 : 0; + if (!RDigits) + return 1; + + // Check for the scale. Use getLgFloor to be sure that the scale difference + // is always lower than 64. + int32_t lgL = getLgFloor(LDigits, LScale), lgR = getLgFloor(RDigits, RScale); + if (lgL != lgR) + return lgL < lgR ? -1 : 1; + + // Compare digits. + if (LScale < RScale) + return compareImpl(LDigits, RDigits, RScale - LScale); + + return -compareImpl(RDigits, LDigits, LScale - RScale); +} + +/// \brief Match scales of two numbers. +/// +/// Given two scaled numbers, match up their scales. Change the digits and +/// scales in place. Shift the digits as necessary to form equivalent numbers, +/// losing precision only when necessary. +/// +/// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of +/// \c LScale (\c RScale) is unspecified. +/// +/// As a convenience, returns the matching scale. If the output value of one +/// number is zero, returns the scale of the other. If both are zero, which +/// scale is returned is unspecifed. +template +int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, + int16_t &RScale) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + if (LScale < RScale) + // Swap arguments. + return matchScales(RDigits, RScale, LDigits, LScale); + if (!LDigits) + return RScale; + if (!RDigits || LScale == RScale) + return LScale; + + // Now LScale > RScale. Get the difference. + int32_t ScaleDiff = int32_t(LScale) - RScale; + if (ScaleDiff >= 2 * getWidth()) { + // Don't bother shifting. RDigits will get zero-ed out anyway. + RDigits = 0; + return LScale; + } + + // Shift LDigits left as much as possible, then shift RDigits right. + int32_t ShiftL = std::min(countLeadingZeros(LDigits), ScaleDiff); + assert(ShiftL < getWidth() && "can't shift more than width"); + + int32_t ShiftR = ScaleDiff - ShiftL; + if (ShiftR >= getWidth()) { + // Don't bother shifting. RDigits will get zero-ed out anyway. + RDigits = 0; + return LScale; + } + + LDigits <<= ShiftL; + RDigits >>= ShiftR; + + LScale -= ShiftL; + RScale += ShiftR; + assert(LScale == RScale && "scales should match"); + return LScale; +} + +/// \brief Get the sum of two scaled numbers. +/// +/// Get the sum of two scaled numbers with as much precision as possible. +/// +/// \pre Adding 1 to \c LScale (or \c RScale) will not overflow INT16_MAX. +template +std::pair getSum(DigitsT LDigits, int16_t LScale, + DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + // Check inputs up front. This is only relevent if addition overflows, but + // testing here should catch more bugs. + assert(LScale < INT16_MAX && "scale too large"); + assert(RScale < INT16_MAX && "scale too large"); + + // Normalize digits to match scales. + int16_t Scale = matchScales(LDigits, LScale, RDigits, RScale); + + // Compute sum. + DigitsT Sum = LDigits + RDigits; + if (Sum >= RDigits) + return std::make_pair(Sum, Scale); + + // Adjust sum after arithmetic overflow. + DigitsT HighBit = DigitsT(1) << (getWidth() - 1); + return std::make_pair(HighBit | Sum >> 1, Scale + 1); +} + +/// \brief Convenience helper for 32-bit sum. +inline std::pair getSum32(uint32_t LDigits, int16_t LScale, + uint32_t RDigits, int16_t RScale) { + return getSum(LDigits, LScale, RDigits, RScale); +} + +/// \brief Convenience helper for 64-bit sum. +inline std::pair getSum64(uint64_t LDigits, int16_t LScale, + uint64_t RDigits, int16_t RScale) { + return getSum(LDigits, LScale, RDigits, RScale); +} + +/// \brief Get the difference of two scaled numbers. +/// +/// Get LHS minus RHS with as much precision as possible. +/// +/// Returns \c (0, 0) if the RHS is larger than the LHS. +template +std::pair getDifference(DigitsT LDigits, int16_t LScale, + DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits::is_signed, "expected unsigned"); + + // Normalize digits to match scales. + const DigitsT SavedRDigits = RDigits; + const int16_t SavedRScale = RScale; + matchScales(LDigits, LScale, RDigits, RScale); + + // Compute difference. + if (LDigits <= RDigits) + return std::make_pair(0, 0); + if (RDigits || !SavedRDigits) + return std::make_pair(LDigits - RDigits, LScale); + + // Check if RDigits just barely lost its last bit. E.g., for 32-bit: + // + // 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32 + const auto RLgFloor = getLgFloor(SavedRDigits, SavedRScale); + if (!compare(LDigits, LScale, DigitsT(1), RLgFloor + getWidth())) + return std::make_pair(std::numeric_limits::max(), RLgFloor); + + return std::make_pair(LDigits, LScale); +} + +/// \brief Convenience helper for 32-bit difference. +inline std::pair getDifference32(uint32_t LDigits, + int16_t LScale, + uint32_t RDigits, + int16_t RScale) { + return getDifference(LDigits, LScale, RDigits, RScale); +} + +/// \brief Convenience helper for 64-bit difference. +inline std::pair getDifference64(uint64_t LDigits, + int16_t LScale, + uint64_t RDigits, + int16_t RScale) { + return getDifference(LDigits, LScale, RDigits, RScale); +} + +} // end namespace ScaledNumbers +} // end namespace llvm + +namespace llvm { + +class raw_ostream; +class ScaledNumberBase { +public: + static const int DefaultPrecision = 10; + + static void dump(uint64_t D, int16_t E, int Width); + static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width, + unsigned Precision); + static std::string toString(uint64_t D, int16_t E, int Width, + unsigned Precision); + static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); } + static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); } + static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); } + + static std::pair splitSigned(int64_t N) { + if (N >= 0) + return std::make_pair(N, false); + uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N); + return std::make_pair(Unsigned, true); + } + static int64_t joinSigned(uint64_t U, bool IsNeg) { + if (U > uint64_t(INT64_MAX)) + return IsNeg ? INT64_MIN : INT64_MAX; + return IsNeg ? -int64_t(U) : int64_t(U); + } +}; + +/// \brief Simple representation of a scaled number. +/// +/// ScaledNumber is a number represented by digits and a scale. It uses simple +/// saturation arithmetic and every operation is well-defined for every value. +/// It's somewhat similar in behaviour to a soft-float, but is *not* a +/// replacement for one. If you're doing numerics, look at \a APFloat instead. +/// Nevertheless, we've found these semantics useful for modelling certain cost +/// metrics. +/// +/// The number is split into a signed scale and unsigned digits. The number +/// represented is \c getDigits()*2^getScale(). In this way, the digits are +/// much like the mantissa in the x87 long double, but there is no canonical +/// form so the same number can be represented by many bit representations. +/// +/// ScaledNumber is templated on the underlying integer type for digits, which +/// is expected to be unsigned. +/// +/// Unlike APFloat, ScaledNumber does not model architecture floating point +/// behaviour -- while this might make it a little faster and easier to reason +/// about, it certainly makes it more dangerous for general numerics. +/// +/// ScaledNumber is totally ordered. However, there is no canonical form, so +/// there are multiple representations of most scalars. E.g.: +/// +/// ScaledNumber(8u, 0) == ScaledNumber(4u, 1) +/// ScaledNumber(4u, 1) == ScaledNumber(2u, 2) +/// ScaledNumber(2u, 2) == ScaledNumber(1u, 3) +/// +/// ScaledNumber implements most arithmetic operations. Precision is kept +/// where possible. Uses simple saturation arithmetic, so that operations +/// saturate to 0.0 or getLargest() rather than under or overflowing. It has +/// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0. +/// Any other division by 0.0 is defined to be getLargest(). +/// +/// As a convenience for modifying the exponent, left and right shifting are +/// both implemented, and both interpret negative shifts as positive shifts in +/// the opposite direction. +/// +/// Scales are limited to the range accepted by x87 long double. This makes +/// it trivial to add functionality to convert to APFloat (this is already +/// relied on for the implementation of printing). +/// +/// Possible (and conflicting) future directions: +/// +/// 1. Turn this into a wrapper around \a APFloat. +/// 2. Share the algorithm implementations with \a APFloat. +/// 3. Allow \a ScaledNumber to represent a signed number. +template class ScaledNumber : ScaledNumberBase { +public: + static_assert(!std::numeric_limits::is_signed, + "only unsigned floats supported"); + + typedef DigitsT DigitsType; + +private: + typedef std::numeric_limits DigitsLimits; + + static const int Width = sizeof(DigitsType) * 8; + static_assert(Width <= 64, "invalid integer width for digits"); + +private: + DigitsType Digits; + int16_t Scale; + +public: + ScaledNumber() : Digits(0), Scale(0) {} + + ScaledNumber(DigitsType Digits, int16_t Scale) + : Digits(Digits), Scale(Scale) {} + +private: + ScaledNumber(const std::pair &X) + : Digits(X.first), Scale(X.second) {} + +public: + static ScaledNumber getZero() { return ScaledNumber(0, 0); } + static ScaledNumber getOne() { return ScaledNumber(1, 0); } + static ScaledNumber getLargest() { + return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale); + } + static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); } + static ScaledNumber getInverse(uint64_t N) { + return get(N).invert(); + } + static ScaledNumber getFraction(DigitsType N, DigitsType D) { + return getQuotient(N, D); + } + + int16_t getScale() const { return Scale; } + DigitsType getDigits() const { return Digits; } + + /// \brief Convert to the given integer type. + /// + /// Convert to \c IntT using simple saturating arithmetic, truncating if + /// necessary. + template IntT toInt() const; + + bool isZero() const { return !Digits; } + bool isLargest() const { return *this == getLargest(); } + bool isOne() const { + if (Scale > 0 || Scale <= -Width) + return false; + return Digits == DigitsType(1) << -Scale; + } + + /// \brief The log base 2, rounded. + /// + /// Get the lg of the scalar. lg 0 is defined to be INT32_MIN. + int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); } + + /// \brief The log base 2, rounded towards INT32_MIN. + /// + /// Get the lg floor. lg 0 is defined to be INT32_MIN. + int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); } + + /// \brief The log base 2, rounded towards INT32_MAX. + /// + /// Get the lg ceiling. lg 0 is defined to be INT32_MIN. + int32_t lgCeiling() const { + return ScaledNumbers::getLgCeiling(Digits, Scale); + } + + bool operator==(const ScaledNumber &X) const { return compare(X) == 0; } + bool operator<(const ScaledNumber &X) const { return compare(X) < 0; } + bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; } + bool operator>(const ScaledNumber &X) const { return compare(X) > 0; } + bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; } + bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; } + + bool operator!() const { return isZero(); } + + /// \brief Convert to a decimal representation in a string. + /// + /// Convert to a string. Uses scientific notation for very large/small + /// numbers. Scientific notation is used roughly for numbers outside of the + /// range 2^-64 through 2^64. + /// + /// \c Precision indicates the number of decimal digits of precision to use; + /// 0 requests the maximum available. + /// + /// As a special case to make debugging easier, if the number is small enough + /// to convert without scientific notation and has more than \c Precision + /// digits before the decimal place, it's printed accurately to the first + /// digit past zero. E.g., assuming 10 digits of precision: + /// + /// 98765432198.7654... => 98765432198.8 + /// 8765432198.7654... => 8765432198.8 + /// 765432198.7654... => 765432198.8 + /// 65432198.7654... => 65432198.77 + /// 5432198.7654... => 5432198.765 + std::string toString(unsigned Precision = DefaultPrecision) { + return ScaledNumberBase::toString(Digits, Scale, Width, Precision); + } + + /// \brief Print a decimal representation. + /// + /// Print a string. See toString for documentation. + raw_ostream &print(raw_ostream &OS, + unsigned Precision = DefaultPrecision) const { + return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision); + } + void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); } + + ScaledNumber &operator+=(const ScaledNumber &X) { + std::tie(Digits, Scale) = + ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale); + // Check for exponent past MaxScale. + if (Scale > ScaledNumbers::MaxScale) + *this = getLargest(); + return *this; + } + ScaledNumber &operator-=(const ScaledNumber &X) { + std::tie(Digits, Scale) = + ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale); + return *this; + } + ScaledNumber &operator*=(const ScaledNumber &X); + ScaledNumber &operator/=(const ScaledNumber &X); + ScaledNumber &operator<<=(int16_t Shift) { + shiftLeft(Shift); + return *this; + } + ScaledNumber &operator>>=(int16_t Shift) { + shiftRight(Shift); + return *this; + } + +private: + void shiftLeft(int32_t Shift); + void shiftRight(int32_t Shift); + + /// \brief Adjust two floats to have matching exponents. + /// + /// Adjust \c this and \c X to have matching exponents. Returns the new \c X + /// by value. Does nothing if \a isZero() for either. + /// + /// The value that compares smaller will lose precision, and possibly become + /// \a isZero(). + ScaledNumber matchScales(ScaledNumber X) { + ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale); + return X; + } + +public: + /// \brief Scale a large number accurately. + /// + /// Scale N (multiply it by this). Uses full precision multiplication, even + /// if Width is smaller than 64, so information is not lost. + uint64_t scale(uint64_t N) const; + uint64_t scaleByInverse(uint64_t N) const { + // TODO: implement directly, rather than relying on inverse. Inverse is + // expensive. + return inverse().scale(N); + } + int64_t scale(int64_t N) const { + std::pair Unsigned = splitSigned(N); + return joinSigned(scale(Unsigned.first), Unsigned.second); + } + int64_t scaleByInverse(int64_t N) const { + std::pair Unsigned = splitSigned(N); + return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second); + } + + int compare(const ScaledNumber &X) const { + return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale); + } + int compareTo(uint64_t N) const { + ScaledNumber Scaled = get(N); + int Compare = compare(Scaled); + if (Width == 64 || Compare != 0) + return Compare; + + // Check for precision loss. We know *this == RoundTrip. + uint64_t RoundTrip = Scaled.template toInt(); + return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1; + } + int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } + + ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; } + ScaledNumber inverse() const { return ScaledNumber(*this).invert(); } + +private: + static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) { + return ScaledNumbers::getProduct(LHS, RHS); + } + static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) { + return ScaledNumbers::getQuotient(Dividend, Divisor); + } + + static int countLeadingZerosWidth(DigitsType Digits) { + if (Width == 64) + return countLeadingZeros64(Digits); + if (Width == 32) + return countLeadingZeros32(Digits); + return countLeadingZeros32(Digits) + Width - 32; + } + + /// \brief Adjust a number to width, rounding up if necessary. + /// + /// Should only be called for \c Shift close to zero. + /// + /// \pre Shift >= MinScale && Shift + 64 <= MaxScale. + static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) { + assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0"); + assert(Shift <= ScaledNumbers::MaxScale - 64 && + "Shift should be close to 0"); + auto Adjusted = ScaledNumbers::getAdjusted(N, Shift); + return Adjusted; + } + + static ScaledNumber getRounded(ScaledNumber P, bool Round) { + // Saturate. + if (P.isLargest()) + return P; + + return ScaledNumbers::getRounded(P.Digits, P.Scale, Round); + } +}; + +#define SCALED_NUMBER_BOP(op, base) \ + template \ + ScaledNumber operator op(const ScaledNumber &L, \ + const ScaledNumber &R) { \ + return ScaledNumber(L) base R; \ + } +SCALED_NUMBER_BOP(+, += ) +SCALED_NUMBER_BOP(-, -= ) +SCALED_NUMBER_BOP(*, *= ) +SCALED_NUMBER_BOP(/, /= ) +SCALED_NUMBER_BOP(<<, <<= ) +SCALED_NUMBER_BOP(>>, >>= ) +#undef SCALED_NUMBER_BOP + +template +raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber &X) { + return X.print(OS, 10); +} + +#define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \ + template \ + bool operator op(const ScaledNumber &L, T1 R) { \ + return L.compareTo(T2(R)) op 0; \ + } \ + template \ + bool operator op(T1 L, const ScaledNumber &R) { \ + return 0 op R.compareTo(T2(L)); \ + } +#define SCALED_NUMBER_COMPARE_TO(op) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t) +SCALED_NUMBER_COMPARE_TO(< ) +SCALED_NUMBER_COMPARE_TO(> ) +SCALED_NUMBER_COMPARE_TO(== ) +SCALED_NUMBER_COMPARE_TO(!= ) +SCALED_NUMBER_COMPARE_TO(<= ) +SCALED_NUMBER_COMPARE_TO(>= ) +#undef SCALED_NUMBER_COMPARE_TO +#undef SCALED_NUMBER_COMPARE_TO_TYPE + +template +uint64_t ScaledNumber::scale(uint64_t N) const { + if (Width == 64 || N <= DigitsLimits::max()) + return (get(N) * *this).template toInt(); + + // Defer to the 64-bit version. + return ScaledNumber(Digits, Scale).scale(N); +} + +template +template +IntT ScaledNumber::toInt() const { + typedef std::numeric_limits Limits; + if (*this < 1) + return 0; + if (*this >= Limits::max()) + return Limits::max(); + + IntT N = Digits; + if (Scale > 0) { + assert(size_t(Scale) < sizeof(IntT) * 8); + return N << Scale; + } + if (Scale < 0) { + assert(size_t(-Scale) < sizeof(IntT) * 8); + return N >> -Scale; + } + return N; +} + +template +ScaledNumber &ScaledNumber:: +operator*=(const ScaledNumber &X) { + if (isZero()) + return *this; + if (X.isZero()) + return *this = X; + + // Save the exponents. + int32_t Scales = int32_t(Scale) + int32_t(X.Scale); + + // Get the raw product. + *this = getProduct(Digits, X.Digits); + + // Combine with exponents. + return *this <<= Scales; +} +template +ScaledNumber &ScaledNumber:: +operator/=(const ScaledNumber &X) { + if (isZero()) + return *this; + if (X.isZero()) + return *this = getLargest(); + + // Save the exponents. + int32_t Scales = int32_t(Scale) - int32_t(X.Scale); + + // Get the raw quotient. + *this = getQuotient(Digits, X.Digits); + + // Combine with exponents. + return *this <<= Scales; +} +template void ScaledNumber::shiftLeft(int32_t Shift) { + if (!Shift || isZero()) + return; + assert(Shift != INT32_MIN); + if (Shift < 0) { + shiftRight(-Shift); + return; + } + + // Shift as much as we can in the exponent. + int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale); + Scale += ScaleShift; + if (ScaleShift == Shift) + return; + + // Check this late, since it's rare. + if (isLargest()) + return; + + // Shift the digits themselves. + Shift -= ScaleShift; + if (Shift > countLeadingZerosWidth(Digits)) { + // Saturate. + *this = getLargest(); + return; + } + + Digits <<= Shift; + return; +} + +template void ScaledNumber::shiftRight(int32_t Shift) { + if (!Shift || isZero()) + return; + assert(Shift != INT32_MIN); + if (Shift < 0) { + shiftLeft(-Shift); + return; + } + + // Shift as much as we can in the exponent. + int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale); + Scale -= ScaleShift; + if (ScaleShift == Shift) + return; + + // Shift the digits themselves. + Shift -= ScaleShift; + if (Shift >= Width) { + // Saturate. + *this = getZero(); + return; + } + + Digits >>= Shift; + return; +} + +template struct isPodLike; +template struct isPodLike> { + static const bool value = true; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 39f896d..4717553 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -30,7 +30,7 @@ namespace llvm { class Twine; class raw_ostream; -/// SourceMgr - This owns the files read by a parser, handles include stacks, +/// This owns the files read by a parser, handles include stacks, /// and handles diagnostic wrangling. class SourceMgr { public: @@ -40,34 +40,34 @@ public: DK_Note }; - /// DiagHandlerTy - Clients that want to handle their own diagnostics in a - /// custom way can register a function pointer+context as a diagnostic - /// handler. It gets called each time PrintMessage is invoked. + /// Clients that want to handle their own diagnostics in a custom way can + /// register a function pointer+context as a diagnostic handler. + /// It gets called each time PrintMessage is invoked. typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context); private: struct SrcBuffer { - /// Buffer - The memory buffer for the file. + /// The memory buffer for the file. MemoryBuffer *Buffer; - /// IncludeLoc - This is the location of the parent include, or null if at - /// the top level. + /// This is the location of the parent include, or null if at the top level. SMLoc IncludeLoc; }; - /// Buffers - This is all of the buffers that we are reading from. + /// This is all of the buffers that we are reading from. std::vector Buffers; - // IncludeDirectories - This is the list of directories we should search for - // include files in. + // This is the list of directories we should search for include files in. std::vector IncludeDirectories; - /// LineNoCache - This is a cache for line number queries, its implementation - /// is really private to SourceMgr.cpp. + /// This is a cache for line number queries, its implementation is really + /// private to SourceMgr.cpp. mutable void *LineNoCache; DiagHandlerTy DiagHandler; void *DiagContext; + bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } + SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; public: @@ -79,8 +79,8 @@ public: IncludeDirectories = Dirs; } - /// setDiagHandler - Specify a diagnostic handler to be invoked every time - /// PrintMessage is called. Ctx is passed into the handler when it is invoked. + /// Specify a diagnostic handler to be invoked every time PrintMessage is + /// called. \p Ctx is passed into the handler when it is invoked. void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) { DiagHandler = DH; DiagContext = Ctx; @@ -90,60 +90,67 @@ public: void *getDiagContext() const { return DiagContext; } const SrcBuffer &getBufferInfo(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i]; + assert(isValidBufferID(i)); + return Buffers[i - 1]; } const MemoryBuffer *getMemoryBuffer(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i].Buffer; + assert(isValidBufferID(i)); + return Buffers[i - 1].Buffer; } - size_t getNumBuffers() const { + unsigned getNumBuffers() const { return Buffers.size(); } + unsigned getMainFileID() const { + assert(getNumBuffers()); + return 1; + } + SMLoc getParentIncludeLoc(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i].IncludeLoc; + assert(isValidBufferID(i)); + return Buffers[i - 1].IncludeLoc; } - /// AddNewSourceBuffer - Add a new source buffer to this source manager. This - /// takes ownership of the memory buffer. - size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + /// Add a new source buffer to this source manager. This takes ownership of + /// the memory buffer. + unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { SrcBuffer NB; NB.Buffer = F; NB.IncludeLoc = IncludeLoc; Buffers.push_back(NB); - return Buffers.size() - 1; + return Buffers.size(); } - /// AddIncludeFile - Search for a file with the specified name in the current - /// directory or in one of the IncludeDirs. If no file is found, this returns - /// ~0, otherwise it returns the buffer ID of the stacked file. - /// The full path to the included file can be found in IncludedFile. - size_t AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, - std::string &IncludedFile); + /// Search for a file with the specified name in the current directory or in + /// one of the IncludeDirs. + /// + /// If no file is found, this returns 0, otherwise it returns the buffer ID + /// of the stacked file. The full path to the included file can be found in + /// \p IncludedFile. + unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, + std::string &IncludedFile); - /// FindBufferContainingLoc - Return the ID of the buffer containing the - /// specified location, returning -1 if not found. - int FindBufferContainingLoc(SMLoc Loc) const; + /// Return the ID of the buffer containing the specified location. + /// + /// 0 is returned if the buffer is not found. + unsigned FindBufferContainingLoc(SMLoc Loc) const; - /// FindLineNumber - Find the line number for the specified location in the - /// specified file. This is not a fast method. - unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const { + /// Find the line number for the specified location in the specified file. + /// This is not a fast method. + unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { return getLineAndColumn(Loc, BufferID).first; } - /// getLineAndColumn - Find the line and column number for the specified - /// location in the specified file. This is not a fast method. - std::pair - getLineAndColumn(SMLoc Loc, int BufferID = -1) const; + /// Find the line and column number for the specified location in the + /// specified file. This is not a fast method. + std::pair getLineAndColumn(SMLoc Loc, + unsigned BufferID = 0) const; - /// PrintMessage - Emit a message about the specified location with the - /// specified string. + /// Emit a message about the specified location with the specified string. /// - /// @param ShowColors - Display colored messages if output is a terminal and + /// \param ShowColors Display colored messages if output is a terminal and /// the default error handler is used. void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, @@ -157,21 +164,28 @@ public: ArrayRef FixIts = None, bool ShowColors = true) const; - /// GetMessage - Return an SMDiagnostic at the specified location with the - /// specified string. + /// Emits a manually-constructed diagnostic to the given output stream. + /// + /// \param ShowColors Display colored messages if output is a terminal and + /// the default error handler is used. + void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, + bool ShowColors = true) const; + + /// Return an SMDiagnostic at the specified location with the specified + /// string. /// - /// @param Msg If non-null, the kind of message (e.g., "error") which is + /// \param Msg If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef Ranges = None, ArrayRef FixIts = None) const; - /// PrintIncludeStack - Prints the names of included files and the line of the - /// file they were included from. A diagnostic handler can use this before - /// printing its custom formatted message. + /// Prints the names of included files and the line of the file they were + /// included from. A diagnostic handler can use this before printing its + /// custom formatted message. /// - /// @param IncludeLoc - The line of the include. - /// @param OS the raw_ostream to print on. + /// \param IncludeLoc The location of the include. + /// \param OS the raw_ostream to print on. void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; }; @@ -208,8 +222,8 @@ public: }; -/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, -/// allowing printing to a raw_ostream as a caret diagnostic. +/// Instances of this class encapsulate one diagnostic report, allowing +/// printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { const SourceMgr *SM; SMLoc Loc; diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h new file mode 100644 index 0000000..098b9c7 --- /dev/null +++ b/include/llvm/Support/SpecialCaseList.h @@ -0,0 +1,96 @@ +//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// This is a utility class used to parse user-provided text files with +// "special case lists" for code sanitizers. Such files are used to +// define "ABI list" for DataFlowSanitizer and blacklists for another sanitizers +// like AddressSanitizer or UndefinedBehaviorSanitizer. +// +// Empty lines and lines starting with "#" are ignored. All the rest lines +// should have the form: +// section:wildcard_expression[=category] +// If category is not specified, it is assumed to be empty string. +// Definitions of "section" and "category" are sanitizer-specific. For example, +// sanitizer blacklists support sections "src", "fun" and "global". +// Wildcard expressions define, respectively, source files, functions or +// globals which shouldn't be instrumented. +// Examples of categories: +// "functional": used in DFSan to list functions with pure functional +// semantics. +// "init": used in ASan blacklist to disable initialization-order bugs +// detection for certain globals or source files. +// Full special case list file example: +// --- +// # Blacklisted items: +// fun:*_ZN4base6subtle* +// global:*global_with_bad_access_or_initialization* +// global:*global_with_initialization_issues*=init +// type:*Namespace::ClassName*=init +// src:file_with_tricky_code.cc +// src:ignore-global-initializers-issues.cc=init +// +// # Functions with pure functional semantics: +// fun:cos=functional +// fun:sin=functional +// --- +// Note that the wild card is in fact an llvm::Regex, but * is automatically +// replaced with .* +// This is similar to the "ignore" feature of ThreadSanitizer. +// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SPECIALCASELIST_H +#define LLVM_SUPPORT_SPECIALCASELIST_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { +class MemoryBuffer; +class Regex; +class StringRef; + +class SpecialCaseList { + public: + /// Parses the special case list from a file. If Path is empty, returns + /// an empty special case list. On failure, returns 0 and writes an error + /// message to string. + static SpecialCaseList *create(const StringRef Path, std::string &Error); + /// Parses the special case list from a memory buffer. On failure, returns + /// 0 and writes an error message to string. + static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); + /// Parses the special case list from a file. On failure, reports a fatal + /// error. + static SpecialCaseList *createOrDie(const StringRef Path); + + ~SpecialCaseList(); + + /// Returns true, if special case list contains a line + /// \code + /// @Section:=@Category + /// \endcode + /// and @Query satisfies a wildcard expression . + bool inSection(const StringRef Section, const StringRef Query, + const StringRef Category = StringRef()) const; + + private: + SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + + struct Entry; + StringMap > Entries; + + SpecialCaseList(); + /// Parses just-constructed SpecialCaseList entries from a memory buffer. + bool parse(const MemoryBuffer *MB, std::string &Error); +}; + +} // namespace llvm + +#endif // LLVM_SUPPORT_SPECIALCASELIST_H + diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index 9c9e55c..6e71ad4 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -13,6 +13,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" #include #include @@ -115,7 +116,7 @@ public: // requiring that the bitcode size be known, or otherwise ensuring that // the memory doesn't go away/get reallocated, but it's // not currently necessary. Users that need the pointer don't stream. - assert(0 && "getPointer in streaming memory objects not allowed"); + llvm_unreachable("getPointer in streaming memory objects not allowed"); return nullptr; } bool isValidAddress(uint64_t address) const override; @@ -154,8 +155,8 @@ private: kChunkSize); BytesRead += bytes; if (bytes < kChunkSize) { - if (ObjectSize && BytesRead < Pos) - assert(0 && "Unexpected short read fetching bitcode"); + assert((!ObjectSize || BytesRead >= Pos) && + "Unexpected short read fetching bitcode"); if (BytesRead <= Pos) { // reached EOF/ran out of bytes ObjectSize = BytesRead; EOFReached = true; diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index 7e1394c..3e04653 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -29,6 +29,7 @@ #ifndef LLVM_SUPPORT_STRINGPOOL_H #define LLVM_SUPPORT_STRINGPOOL_H +#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringMap.h" #include #include @@ -128,10 +129,10 @@ namespace llvm { } inline const char *operator*() const { return begin(); } - inline operator bool() const { return S != nullptr; } + inline LLVM_EXPLICIT operator bool() const { return S != nullptr; } - inline bool operator==(const PooledStringPtr &That) { return S == That.S; } - inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } + inline bool operator==(const PooledStringPtr &That) const { return S == That.S; } + inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; } }; } // End llvm namespace diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index e65f9cc..340954f 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -68,33 +68,38 @@ inline uint64_t SwapByteOrder_64(uint64_t value) { #endif } -inline unsigned char SwapByteOrder(unsigned char C) { return C; } -inline signed char SwapByteOrder(signed char C) { return C; } -inline char SwapByteOrder(char C) { return C; } +inline unsigned char getSwappedBytes(unsigned char C) { return C; } +inline signed char getSwappedBytes(signed char C) { return C; } +inline char getSwappedBytes(char C) { return C; } -inline unsigned short SwapByteOrder(unsigned short C) { return SwapByteOrder_16(C); } -inline signed short SwapByteOrder( signed short C) { return SwapByteOrder_16(C); } +inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } -inline unsigned int SwapByteOrder(unsigned int C) { return SwapByteOrder_32(C); } -inline signed int SwapByteOrder( signed int C) { return SwapByteOrder_32(C); } +inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } #if __LONG_MAX__ == __INT_MAX__ -inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_32(C); } -inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_32(C); } +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } #elif __LONG_MAX__ == __LONG_LONG_MAX__ -inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_64(C); } -inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_64(C); } +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } #else #error "Unknown long size!" #endif -inline unsigned long long SwapByteOrder(unsigned long long C) { +inline unsigned long long getSwappedBytes(unsigned long long C) { return SwapByteOrder_64(C); } -inline signed long long SwapByteOrder(signed long long C) { +inline signed long long getSwappedBytes(signed long long C) { return SwapByteOrder_64(C); } +template +inline void swapByteOrder(T &Value) { + Value = getSwappedBytes(Value); +} + } // end namespace sys } // end namespace llvm diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index fcdc604..5d5b86a 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -51,6 +51,7 @@ namespace llvm { class raw_ostream; class formatted_raw_ostream; + MCStreamer *createNullStreamer(MCContext &Ctx); MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, @@ -139,6 +140,7 @@ namespace llvm { MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); + typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx); typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, MCContext &Ctx); typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT, @@ -225,6 +227,10 @@ namespace llvm { /// AsmStreamer, if registered (default = llvm::createAsmStreamer). AsmStreamerCtorTy AsmStreamerCtorFn; + /// Construction function for this target's NullStreamer, if registered + /// (default = llvm::createNullStreamer). + NullStreamerCtorTy NullStreamerCtorFn; + /// MCRelocationInfoCtorFn - Construction function for this target's /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) MCRelocationInfoCtorTy MCRelocationInfoCtorFn; @@ -235,8 +241,8 @@ namespace llvm { public: Target() - : AsmStreamerCtorFn(nullptr), MCRelocationInfoCtorFn(nullptr), - MCSymbolizerCtorFn(nullptr) {} + : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr), + MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} /// @name Target Information /// @{ @@ -447,6 +453,12 @@ namespace llvm { InstPrint, CE, TAB, ShowInst); } + MCStreamer *createNullStreamer(MCContext &Ctx) const { + if (NullStreamerCtorFn) + return NullStreamerCtorFn(Ctx); + return llvm::createNullStreamer(Ctx); + } + /// createMCRelocationInfo - Create a target specific MCRelocationInfo. /// /// \param TT The target triple. @@ -553,13 +565,6 @@ namespace llvm { Triple &TheTriple, std::string &Error); - /// getClosestTargetForJIT - Pick the best target that is compatible with - /// the current host. If no close target can be found, this returns null - /// and sets the Error string to a reason. - /// - /// Maintained for compatibility through 2.6. - static const Target *getClosestTargetForJIT(std::string &Error); - /// @} /// @name Target Registration /// @{ @@ -780,6 +785,10 @@ namespace llvm { T.AsmStreamerCtorFn = Fn; } + static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) { + T.NullStreamerCtorFn = Fn; + } + /// RegisterMCRelocationInfo - Register an MCRelocationInfo /// implementation for the given target. /// diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index a7e8774..7e87584 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// TThis file defines llvm_start_multithreaded() and friends. +// This file declares helper functions for running LLVM in a multi-threaded +// environment. // //===----------------------------------------------------------------------===// @@ -15,32 +16,10 @@ #define LLVM_SUPPORT_THREADING_H namespace llvm { - /// llvm_start_multithreaded - Allocate and initialize structures needed to - /// make LLVM safe for multithreading. The return value indicates whether - /// multithreaded initialization succeeded. LLVM will still be operational - /// on "failed" return, and will still be safe for hosting threading - /// applications in the JIT, but will not be safe for concurrent calls to the - /// LLVM APIs. - /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. - bool llvm_start_multithreaded(); - - /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM - /// safe for multithreading. - /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. - void llvm_stop_multithreaded(); - - /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe - /// mode or not. + /// Returns true if LLVM is compiled with support for multi-threading, and + /// false otherwise. bool llvm_is_multithreaded(); - /// acquire_global_lock - Acquire the global lock. This is a no-op if called - /// before llvm_start_multithreaded(). - void llvm_acquire_global_lock(); - - /// release_global_lock - Release the global lock. This is a no-op if called - /// before llvm_start_multithreaded(). - void llvm_release_global_lock(); - /// llvm_execute_on_thread - Execute the given \p UserFn on a separate /// thread, passing it the provided \p UserData. /// diff --git a/include/llvm/Support/WindowsError.h b/include/llvm/Support/WindowsError.h new file mode 100644 index 0000000..0e909a0 --- /dev/null +++ b/include/llvm/Support/WindowsError.h @@ -0,0 +1,19 @@ +//===-- WindowsError.h - Support for mapping windows errors to posix-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINDOWS_ERROR_H +#define LLVM_SUPPORT_WINDOWS_ERROR_H + +#include + +namespace llvm { +std::error_code mapWindowsError(unsigned EV); +} + +#endif diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 4ee05ed..a23faf6 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -24,7 +24,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" +#include namespace llvm { namespace yaml { @@ -880,7 +880,7 @@ public: ~Input(); // Check if there was an syntax or semantic error during parsing. - llvm::error_code error(); + std::error_code error(); private: bool outputting() override; @@ -982,13 +982,13 @@ public: // These are only used by operator>>. They could be private // if those templated things could be made friends. bool setCurrentDocument(); - void nextDocument(); + bool nextDocument(); private: llvm::SourceMgr SrcMgr; // must be before Strm std::unique_ptr Strm; std::unique_ptr TopNode; - llvm::error_code EC; + std::error_code EC; llvm::BumpPtrAllocator StringAllocator; llvm::yaml::document_iterator DocIterator; std::vector BitValuesUsed; diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h deleted file mode 100644 index aa5e9f7..0000000 --- a/include/llvm/Support/system_error.h +++ /dev/null @@ -1,901 +0,0 @@ -//===---------------------------- system_error ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This was lifted from libc++ and modified for C++03. This is called -// system_error even though it does not define that class because that's what -// it's called in C++0x. We don't define system_error because it is only used -// for exception handling, which we don't use in LLVM. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_SYSTEM_ERROR_H -#define LLVM_SUPPORT_SYSTEM_ERROR_H - -#include "llvm/Support/Compiler.h" - -/* - system_error synopsis - -namespace std -{ - -class error_category -{ -public: - virtual ~error_category(); - - error_category(const error_category&) = delete; - error_category& operator=(const error_category&) = delete; - - virtual const char* name() const = 0; - virtual error_condition default_error_condition(int ev) const; - virtual bool equivalent(int code, const error_condition& condition) const; - virtual bool equivalent(const error_code& code, int condition) const; - virtual std::string message(int ev) const = 0; - - bool operator==(const error_category& rhs) const; - bool operator!=(const error_category& rhs) const; - bool operator<(const error_category& rhs) const; -}; - -const error_category& generic_category(); -const error_category& system_category(); - -template struct is_error_code_enum - : public std::false_type {}; - -template struct is_error_condition_enum - : public std::false_type {}; - -class error_code -{ -public: - // constructors: - error_code(); - error_code(int val, const error_category& cat); - template - error_code(ErrorCodeEnum e); - - // modifiers: - void assign(int val, const error_category& cat); - template - error_code& operator=(ErrorCodeEnum e); - void clear(); - - // observers: - int value() const; - const error_category& category() const; - error_condition default_error_condition() const; - std::string message() const; - explicit operator bool() const; -}; - -// non-member functions: -bool operator<(const error_code& lhs, const error_code& rhs); -template - basic_ostream& - operator<<(basic_ostream& os, const error_code& ec); - -class error_condition -{ -public: - // constructors: - error_condition(); - error_condition(int val, const error_category& cat); - template - error_condition(ErrorConditionEnum e); - - // modifiers: - void assign(int val, const error_category& cat); - template - error_condition& operator=(ErrorConditionEnum e); - void clear(); - - // observers: - int value() const; - const error_category& category() const; - std::string message() const; - explicit operator bool() const; -}; - -bool operator<(const error_condition& lhs, const error_condition& rhs); - -class system_error - : public runtime_error -{ -public: - system_error(error_code ec, const std::string& what_arg); - system_error(error_code ec, const char* what_arg); - system_error(error_code ec); - system_error(int ev, const error_category& ecat, const std::string& what_arg); - system_error(int ev, const error_category& ecat, const char* what_arg); - system_error(int ev, const error_category& ecat); - - const error_code& code() const throw(); - const char* what() const throw(); -}; - -enum class errc -{ - address_family_not_supported, // EAFNOSUPPORT - address_in_use, // EADDRINUSE - address_not_available, // EADDRNOTAVAIL - already_connected, // EISCONN - argument_list_too_long, // E2BIG - argument_out_of_domain, // EDOM - bad_address, // EFAULT - bad_file_descriptor, // EBADF - bad_message, // EBADMSG - broken_pipe, // EPIPE - connection_aborted, // ECONNABORTED - connection_already_in_progress, // EALREADY - connection_refused, // ECONNREFUSED - connection_reset, // ECONNRESET - cross_device_link, // EXDEV - destination_address_required, // EDESTADDRREQ - device_or_resource_busy, // EBUSY - directory_not_empty, // ENOTEMPTY - executable_format_error, // ENOEXEC - file_exists, // EEXIST - file_too_large, // EFBIG - filename_too_long, // ENAMETOOLONG - function_not_supported, // ENOSYS - host_unreachable, // EHOSTUNREACH - identifier_removed, // EIDRM - illegal_byte_sequence, // EILSEQ - inappropriate_io_control_operation, // ENOTTY - interrupted, // EINTR - invalid_argument, // EINVAL - invalid_seek, // ESPIPE - io_error, // EIO - is_a_directory, // EISDIR - message_size, // EMSGSIZE - network_down, // ENETDOWN - network_reset, // ENETRESET - network_unreachable, // ENETUNREACH - no_buffer_space, // ENOBUFS - no_child_process, // ECHILD - no_link, // ENOLINK - no_lock_available, // ENOLCK - no_message_available, // ENODATA - no_message, // ENOMSG - no_protocol_option, // ENOPROTOOPT - no_space_on_device, // ENOSPC - no_stream_resources, // ENOSR - no_such_device_or_address, // ENXIO - no_such_device, // ENODEV - no_such_file_or_directory, // ENOENT - no_such_process, // ESRCH - not_a_directory, // ENOTDIR - not_a_socket, // ENOTSOCK - not_a_stream, // ENOSTR - not_connected, // ENOTCONN - not_enough_memory, // ENOMEM - not_supported, // ENOTSUP - operation_canceled, // ECANCELED - operation_in_progress, // EINPROGRESS - operation_not_permitted, // EPERM - operation_not_supported, // EOPNOTSUPP - operation_would_block, // EWOULDBLOCK - owner_dead, // EOWNERDEAD - permission_denied, // EACCES - protocol_error, // EPROTO - protocol_not_supported, // EPROTONOSUPPORT - read_only_file_system, // EROFS - resource_deadlock_would_occur, // EDEADLK - resource_unavailable_try_again, // EAGAIN - result_out_of_range, // ERANGE - state_not_recoverable, // ENOTRECOVERABLE - stream_timeout, // ETIME - text_file_busy, // ETXTBSY - timed_out, // ETIMEDOUT - too_many_files_open_in_system, // ENFILE - too_many_files_open, // EMFILE - too_many_links, // EMLINK - too_many_symbolic_link_levels, // ELOOP - value_too_large, // EOVERFLOW - wrong_protocol_type // EPROTOTYPE -}; - -template <> struct is_error_condition_enum : std::true_type { } - -error_code make_error_code(errc e); -error_condition make_error_condition(errc e); - -// Comparison operators: -bool operator==(const error_code& lhs, const error_code& rhs); -bool operator==(const error_code& lhs, const error_condition& rhs); -bool operator==(const error_condition& lhs, const error_code& rhs); -bool operator==(const error_condition& lhs, const error_condition& rhs); -bool operator!=(const error_code& lhs, const error_code& rhs); -bool operator!=(const error_code& lhs, const error_condition& rhs); -bool operator!=(const error_condition& lhs, const error_code& rhs); -bool operator!=(const error_condition& lhs, const error_condition& rhs); - -template <> struct hash; - -} // std - -*/ - -#include "llvm/Config/llvm-config.h" -#include -#include - -// This must be here instead of a .inc file because it is used in the definition -// of the enum values below. -#ifdef LLVM_ON_WIN32 - - // The following numbers were taken from VS2010. -# ifndef EAFNOSUPPORT -# define EAFNOSUPPORT 102 -# endif -# ifndef EADDRINUSE -# define EADDRINUSE 100 -# endif -# ifndef EADDRNOTAVAIL -# define EADDRNOTAVAIL 101 -# endif -# ifndef EISCONN -# define EISCONN 113 -# endif -# ifndef E2BIG -# define E2BIG 7 -# endif -# ifndef EDOM -# define EDOM 33 -# endif -# ifndef EFAULT -# define EFAULT 14 -# endif -# ifndef EBADF -# define EBADF 9 -# endif -# ifndef EBADMSG -# define EBADMSG 104 -# endif -# ifndef EPIPE -# define EPIPE 32 -# endif -# ifndef ECONNABORTED -# define ECONNABORTED 106 -# endif -# ifndef EALREADY -# define EALREADY 103 -# endif -# ifndef ECONNREFUSED -# define ECONNREFUSED 107 -# endif -# ifndef ECONNRESET -# define ECONNRESET 108 -# endif -# ifndef EXDEV -# define EXDEV 18 -# endif -# ifndef EDESTADDRREQ -# define EDESTADDRREQ 109 -# endif -# ifndef EBUSY -# define EBUSY 16 -# endif -# ifndef ENOTEMPTY -# define ENOTEMPTY 41 -# endif -# ifndef ENOEXEC -# define ENOEXEC 8 -# endif -# ifndef EEXIST -# define EEXIST 17 -# endif -# ifndef EFBIG -# define EFBIG 27 -# endif -# ifndef ENAMETOOLONG -# define ENAMETOOLONG 38 -# endif -# ifndef ENOSYS -# define ENOSYS 40 -# endif -# ifndef EHOSTUNREACH -# define EHOSTUNREACH 110 -# endif -# ifndef EIDRM -# define EIDRM 111 -# endif -# ifndef EILSEQ -# define EILSEQ 42 -# endif -# ifndef ENOTTY -# define ENOTTY 25 -# endif -# ifndef EINTR -# define EINTR 4 -# endif -# ifndef EINVAL -# define EINVAL 22 -# endif -# ifndef ESPIPE -# define ESPIPE 29 -# endif -# ifndef EIO -# define EIO 5 -# endif -# ifndef EISDIR -# define EISDIR 21 -# endif -# ifndef EMSGSIZE -# define EMSGSIZE 115 -# endif -# ifndef ENETDOWN -# define ENETDOWN 116 -# endif -# ifndef ENETRESET -# define ENETRESET 117 -# endif -# ifndef ENETUNREACH -# define ENETUNREACH 118 -# endif -# ifndef ENOBUFS -# define ENOBUFS 119 -# endif -# ifndef ECHILD -# define ECHILD 10 -# endif -# ifndef ENOLINK -# define ENOLINK 121 -# endif -# ifndef ENOLCK -# define ENOLCK 39 -# endif -# ifndef ENODATA -# define ENODATA 120 -# endif -# ifndef ENOMSG -# define ENOMSG 122 -# endif -# ifndef ENOPROTOOPT -# define ENOPROTOOPT 123 -# endif -# ifndef ENOSPC -# define ENOSPC 28 -# endif -# ifndef ENOSR -# define ENOSR 124 -# endif -# ifndef ENXIO -# define ENXIO 6 -# endif -# ifndef ENODEV -# define ENODEV 19 -# endif -# ifndef ENOENT -# define ENOENT 2 -# endif -# ifndef ESRCH -# define ESRCH 3 -# endif -# ifndef ENOTDIR -# define ENOTDIR 20 -# endif -# ifndef ENOTSOCK -# define ENOTSOCK 128 -# endif -# ifndef ENOSTR -# define ENOSTR 125 -# endif -# ifndef ENOTCONN -# define ENOTCONN 126 -# endif -# ifndef ENOMEM -# define ENOMEM 12 -# endif -# ifndef ENOTSUP -# define ENOTSUP 129 -# endif -# ifndef ECANCELED -# define ECANCELED 105 -# endif -# ifndef EINPROGRESS -# define EINPROGRESS 112 -# endif -# ifndef EPERM -# define EPERM 1 -# endif -# ifndef EOPNOTSUPP -# define EOPNOTSUPP 130 -# endif -# ifndef EWOULDBLOCK -# define EWOULDBLOCK 140 -# endif -# ifndef EOWNERDEAD -# define EOWNERDEAD 133 -# endif -# ifndef EACCES -# define EACCES 13 -# endif -# ifndef EPROTO -# define EPROTO 134 -# endif -# ifndef EPROTONOSUPPORT -# define EPROTONOSUPPORT 135 -# endif -# ifndef EROFS -# define EROFS 30 -# endif -# ifndef EDEADLK -# define EDEADLK 36 -# endif -# ifndef EAGAIN -# define EAGAIN 11 -# endif -# ifndef ERANGE -# define ERANGE 34 -# endif -# ifndef ENOTRECOVERABLE -# define ENOTRECOVERABLE 127 -# endif -# ifndef ETIME -# define ETIME 137 -# endif -# ifndef ETXTBSY -# define ETXTBSY 139 -# endif -# ifndef ETIMEDOUT -# define ETIMEDOUT 138 -# endif -# ifndef ENFILE -# define ENFILE 23 -# endif -# ifndef EMFILE -# define EMFILE 24 -# endif -# ifndef EMLINK -# define EMLINK 31 -# endif -# ifndef ELOOP -# define ELOOP 114 -# endif -# ifndef EOVERFLOW -# define EOVERFLOW 132 -# endif -# ifndef EPROTOTYPE -# define EPROTOTYPE 136 -# endif -#endif - -namespace llvm { - -// is_error_code_enum - -template struct is_error_code_enum : public std::false_type {}; - -// is_error_condition_enum - -template struct is_error_condition_enum : public std::false_type {}; - -// Some error codes are not present on all platforms, so we provide equivalents -// for them: - -//enum class errc -struct errc { -enum _ { - success = 0, - address_family_not_supported = EAFNOSUPPORT, - address_in_use = EADDRINUSE, - address_not_available = EADDRNOTAVAIL, - already_connected = EISCONN, - argument_list_too_long = E2BIG, - argument_out_of_domain = EDOM, - bad_address = EFAULT, - bad_file_descriptor = EBADF, -#ifdef EBADMSG - bad_message = EBADMSG, -#else - bad_message = EINVAL, -#endif - broken_pipe = EPIPE, - connection_aborted = ECONNABORTED, - connection_already_in_progress = EALREADY, - connection_refused = ECONNREFUSED, - connection_reset = ECONNRESET, - cross_device_link = EXDEV, - destination_address_required = EDESTADDRREQ, - device_or_resource_busy = EBUSY, - directory_not_empty = ENOTEMPTY, - executable_format_error = ENOEXEC, - file_exists = EEXIST, - file_too_large = EFBIG, - filename_too_long = ENAMETOOLONG, - function_not_supported = ENOSYS, - host_unreachable = EHOSTUNREACH, - identifier_removed = EIDRM, - illegal_byte_sequence = EILSEQ, - inappropriate_io_control_operation = ENOTTY, - interrupted = EINTR, - invalid_argument = EINVAL, - invalid_seek = ESPIPE, - io_error = EIO, - is_a_directory = EISDIR, - message_size = EMSGSIZE, - network_down = ENETDOWN, - network_reset = ENETRESET, - network_unreachable = ENETUNREACH, - no_buffer_space = ENOBUFS, - no_child_process = ECHILD, -#ifdef ENOLINK - no_link = ENOLINK, -#else - no_link = EINVAL, -#endif - no_lock_available = ENOLCK, -#ifdef ENODATA - no_message_available = ENODATA, -#else - no_message_available = ENOMSG, -#endif - no_message = ENOMSG, - no_protocol_option = ENOPROTOOPT, - no_space_on_device = ENOSPC, -#ifdef ENOSR - no_stream_resources = ENOSR, -#else - no_stream_resources = ENOMEM, -#endif - no_such_device_or_address = ENXIO, - no_such_device = ENODEV, - no_such_file_or_directory = ENOENT, - no_such_process = ESRCH, - not_a_directory = ENOTDIR, - not_a_socket = ENOTSOCK, -#ifdef ENOSTR - not_a_stream = ENOSTR, -#else - not_a_stream = EINVAL, -#endif - not_connected = ENOTCONN, - not_enough_memory = ENOMEM, - not_supported = ENOTSUP, -#ifdef ECANCELED - operation_canceled = ECANCELED, -#else - operation_canceled = EINVAL, -#endif - operation_in_progress = EINPROGRESS, - operation_not_permitted = EPERM, - operation_not_supported = EOPNOTSUPP, - operation_would_block = EWOULDBLOCK, -#ifdef EOWNERDEAD - owner_dead = EOWNERDEAD, -#else - owner_dead = EINVAL, -#endif - permission_denied = EACCES, -#ifdef EPROTO - protocol_error = EPROTO, -#else - protocol_error = EINVAL, -#endif - protocol_not_supported = EPROTONOSUPPORT, - read_only_file_system = EROFS, - resource_deadlock_would_occur = EDEADLK, - resource_unavailable_try_again = EAGAIN, - result_out_of_range = ERANGE, -#ifdef ENOTRECOVERABLE - state_not_recoverable = ENOTRECOVERABLE, -#else - state_not_recoverable = EINVAL, -#endif -#ifdef ETIME - stream_timeout = ETIME, -#else - stream_timeout = ETIMEDOUT, -#endif - text_file_busy = ETXTBSY, - timed_out = ETIMEDOUT, - too_many_files_open_in_system = ENFILE, - too_many_files_open = EMFILE, - too_many_links = EMLINK, - too_many_symbolic_link_levels = ELOOP, - value_too_large = EOVERFLOW, - wrong_protocol_type = EPROTOTYPE -}; - - _ v_; - - errc(_ v) : v_(v) {} - operator int() const {return v_;} -}; - -template <> struct is_error_condition_enum : std::true_type { }; - -template <> struct is_error_condition_enum : std::true_type { }; - -class error_condition; -class error_code; - -// class error_category - -class _do_message; - -class error_category -{ -public: - virtual ~error_category(); - - error_category(); -private: - error_category(const error_category&) LLVM_DELETED_FUNCTION; - error_category& operator=(const error_category&) LLVM_DELETED_FUNCTION; - -public: - virtual const char* name() const = 0; - virtual error_condition default_error_condition(int _ev) const; - virtual bool equivalent(int _code, const error_condition& _condition) const; - virtual bool equivalent(const error_code& _code, int _condition) const; - virtual std::string message(int _ev) const = 0; - - bool operator==(const error_category& _rhs) const {return this == &_rhs;} - - bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);} - - bool operator< (const error_category& _rhs) const {return this < &_rhs;} - - friend class _do_message; -}; - -class _do_message : public error_category -{ -public: - std::string message(int ev) const override; -}; - -const error_category& generic_category(); -const error_category& system_category(); - -/// Get the error_category used for errno values from POSIX functions. This is -/// the same as the system_category on POSIX systems, but is the same as the -/// generic_category on Windows. -const error_category& posix_category(); - -class error_condition -{ - int _val_; - const error_category* _cat_; -public: - error_condition() : _val_(0), _cat_(&generic_category()) {} - - error_condition(int _val, const error_category& _cat) - : _val_(_val), _cat_(&_cat) {} - - template - error_condition(E _e, typename std::enable_if< - is_error_condition_enum::value - >::type* = 0) - {*this = make_error_condition(_e);} - - void assign(int _val, const error_category& _cat) { - _val_ = _val; - _cat_ = &_cat; - } - - template - typename std::enable_if::value, - error_condition &>::type - operator=(E _e) { - *this = make_error_condition(_e); - return *this; - } - - void clear() { - _val_ = 0; - _cat_ = &generic_category(); - } - - int value() const {return _val_;} - - const error_category& category() const {return *_cat_;} - std::string message() const; - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - operator unspecified_bool_type() const { // true if error - return _val_ == 0 ? nullptr : unspecified_bool_true; - } -}; - -inline error_condition make_error_condition(errc _e) { - return error_condition(static_cast(_e), generic_category()); -} - -inline bool operator<(const error_condition& _x, const error_condition& _y) { - return _x.category() < _y.category() - || (_x.category() == _y.category() && _x.value() < _y.value()); -} - -// error_code - -class error_code { - int _val_; - const error_category* _cat_; -public: - error_code() : _val_(0), _cat_(&system_category()) {} - - static error_code success() { - return error_code(); - } - - error_code(int _val, const error_category& _cat) - : _val_(_val), _cat_(&_cat) {} - - template - error_code(E _e, typename std::enable_if< - is_error_code_enum::value - >::type* = 0) { - *this = make_error_code(_e); - } - - void assign(int _val, const error_category& _cat) { - _val_ = _val; - _cat_ = &_cat; - } - - template - typename std::enable_if::value, error_code &>::type - operator=(E _e) { - *this = make_error_code(_e); - return *this; - } - - void clear() { - _val_ = 0; - _cat_ = &system_category(); - } - - int value() const {return _val_;} - - const error_category& category() const {return *_cat_;} - - error_condition default_error_condition() const - {return _cat_->default_error_condition(_val_);} - - std::string message() const; - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - operator unspecified_bool_type() const { // true if error - return _val_ == 0 ? nullptr : unspecified_bool_true; - } -}; - -inline error_code make_error_code(errc _e) { - return error_code(static_cast(_e), generic_category()); -} - -inline bool operator<(const error_code& _x, const error_code& _y) { - return _x.category() < _y.category() - || (_x.category() == _y.category() && _x.value() < _y.value()); -} - -inline bool operator==(const error_code& _x, const error_code& _y) { - return _x.category() == _y.category() && _x.value() == _y.value(); -} - -inline bool operator==(const error_code& _x, const error_condition& _y) { - return _x.category().equivalent(_x.value(), _y) - || _y.category().equivalent(_x, _y.value()); -} - -inline bool operator==(const error_condition& _x, const error_code& _y) { - return _y == _x; -} - -inline bool operator==(const error_condition& _x, const error_condition& _y) { - return _x.category() == _y.category() && _x.value() == _y.value(); -} - -inline bool operator!=(const error_code& _x, const error_code& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_code& _x, const error_condition& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_condition& _x, const error_code& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_condition& _x, const error_condition& _y) { - return !(_x == _y); -} - -// Windows errors. - -// To construct an error_code after an API error: -// -// error_code( ::GetLastError(), system_category() ) -struct windows_error { -enum _ { - success = 0, - // These names and values are based on Windows WinError.h - // This is not a complete list. Add to this list if you need to explicitly - // check for it. - invalid_function = 1, // ERROR_INVALID_FUNCTION, - file_not_found = 2, // ERROR_FILE_NOT_FOUND, - path_not_found = 3, // ERROR_PATH_NOT_FOUND, - too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, - access_denied = 5, // ERROR_ACCESS_DENIED, - invalid_handle = 6, // ERROR_INVALID_HANDLE, - arena_trashed = 7, // ERROR_ARENA_TRASHED, - not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, - invalid_block = 9, // ERROR_INVALID_BLOCK, - bad_environment = 10, // ERROR_BAD_ENVIRONMENT, - bad_format = 11, // ERROR_BAD_FORMAT, - invalid_access = 12, // ERROR_INVALID_ACCESS, - outofmemory = 14, // ERROR_OUTOFMEMORY, - invalid_drive = 15, // ERROR_INVALID_DRIVE, - current_directory = 16, // ERROR_CURRENT_DIRECTORY, - not_same_device = 17, // ERROR_NOT_SAME_DEVICE, - no_more_files = 18, // ERROR_NO_MORE_FILES, - write_protect = 19, // ERROR_WRITE_PROTECT, - bad_unit = 20, // ERROR_BAD_UNIT, - not_ready = 21, // ERROR_NOT_READY, - bad_command = 22, // ERROR_BAD_COMMAND, - crc = 23, // ERROR_CRC, - bad_length = 24, // ERROR_BAD_LENGTH, - seek = 25, // ERROR_SEEK, - not_dos_disk = 26, // ERROR_NOT_DOS_DISK, - sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, - out_of_paper = 28, // ERROR_OUT_OF_PAPER, - write_fault = 29, // ERROR_WRITE_FAULT, - read_fault = 30, // ERROR_READ_FAULT, - gen_failure = 31, // ERROR_GEN_FAILURE, - sharing_violation = 32, // ERROR_SHARING_VIOLATION, - lock_violation = 33, // ERROR_LOCK_VIOLATION, - wrong_disk = 34, // ERROR_WRONG_DISK, - sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, - handle_eof = 38, // ERROR_HANDLE_EOF, - handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, - rem_not_list = 51, // ERROR_REM_NOT_LIST, - dup_name = 52, // ERROR_DUP_NAME, - bad_net_path = 53, // ERROR_BAD_NETPATH, - network_busy = 54, // ERROR_NETWORK_BUSY, - file_exists = 80, // ERROR_FILE_EXISTS, - cannot_make = 82, // ERROR_CANNOT_MAKE, - broken_pipe = 109, // ERROR_BROKEN_PIPE, - open_failed = 110, // ERROR_OPEN_FAILED, - buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, - disk_full = 112, // ERROR_DISK_FULL, - insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, - lock_failed = 167, // ERROR_LOCK_FAILED, - busy = 170, // ERROR_BUSY, - cancel_violation = 173, // ERROR_CANCEL_VIOLATION, - already_exists = 183 // ERROR_ALREADY_EXISTS -}; - _ v_; - - windows_error(_ v) : v_(v) {} - explicit windows_error(int v) : v_(_(v)) {} - operator int() const {return v_;} -}; - - -template <> struct is_error_code_enum : std::true_type { }; - -template <> struct is_error_code_enum : std::true_type { }; - -inline error_code make_error_code(windows_error e) { - return error_code(static_cast(e), system_category()); -} - -} // end namespace llvm - -#endif diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h new file mode 100644 index 0000000..5baed79 --- /dev/null +++ b/include/llvm/TableGen/SetTheory.h @@ -0,0 +1,142 @@ +//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. Operators for standard set operations are +// predefined, and it is possible to add special purpose set operators as well. +// +// The user may define named sets as Records of predefined classes. Set +// expanders can be added to a SetTheory instance to teach it how to find the +// elements of such a named set. +// +// These are the predefined operators. The argument lists can be individual +// elements (defs), other sets (defs of expandable classes), lists, or DAG +// expressions that are evaluated recursively. +// +// - (add S1, S2 ...) Union sets. This is also how sets are created from element +// lists. +// +// - (sub S1, S2, ...) Set difference. Every element in S1 except for the +// elements in S2, ... +// +// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. +// +// - (shl S, N) Shift left. Remove the first N elements from S. +// +// - (trunc S, N) Truncate. The first N elements of S. +// +// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). +// +// - (rotr S, N) Rotate right. +// +// - (decimate S, N) Decimate S by picking every N'th element, starting with +// the first one. For instance, (decimate S, 2) returns the even elements of +// S. +// +// - (sequence "Format", From, To) Generate a sequence of defs with printf. +// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] +// +//===----------------------------------------------------------------------===// + +#ifndef SETTHEORY_H +#define SETTHEORY_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/SourceMgr.h" +#include +#include + +namespace llvm { + +class DagInit; +class Init; +class Record; +class RecordKeeper; + +class SetTheory { +public: + typedef std::vector RecVec; + typedef SmallSetVector RecSet; + + /// Operator - A callback representing a DAG operator. + class Operator { + virtual void anchor(); + public: + virtual ~Operator() {} + + /// apply - Apply this operator to Expr's arguments and insert the result + /// in Elts. + virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) =0; + }; + + /// Expander - A callback function that can transform a Record representing a + /// set into a fully expanded list of elements. Expanders provide a way for + /// users to define named sets that can be used in DAG expressions. + class Expander { + virtual void anchor(); + public: + virtual ~Expander() {} + + virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; + }; + +private: + // Map set defs to their fully expanded contents. This serves as a memoization + // cache and it makes it possible to return const references on queries. + typedef std::map ExpandMap; + ExpandMap Expansions; + + // Known DAG operators by name. + StringMap Operators; + + // Typed expanders by class name. + StringMap Expanders; + +public: + /// Create a SetTheory instance with only the standard operators. + SetTheory(); + + /// addExpander - Add an expander for Records with the named super class. + void addExpander(StringRef ClassName, Expander*); + + /// addFieldExpander - Add an expander for ClassName that simply evaluates + /// FieldName in the Record to get the set elements. That is all that is + /// needed for a class like: + /// + /// class Set { + /// dag Elts = d; + /// } + /// + void addFieldExpander(StringRef ClassName, StringRef FieldName); + + /// addOperator - Add a DAG operator. + void addOperator(StringRef Name, Operator*); + + /// evaluate - Evaluate Expr and append the resulting set to Elts. + void evaluate(Init *Expr, RecSet &Elts, ArrayRef Loc); + + /// evaluate - Evaluate a sequence of Inits and append to Elts. + template + void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef Loc) { + while (begin != end) + evaluate(*begin++, Elts, Loc); + } + + /// expand - Expand a record into a set of elements if possible. Return a + /// pointer to the expanded elements, or NULL if Set cannot be expanded + /// further. + const RecVec *expand(Record *Set); +}; + +} // end namespace llvm + +#endif + diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 7d1f19c..f77cc7a 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -587,6 +587,11 @@ class Operand : DAGOperand { string OperandType = "OPERAND_UNKNOWN"; dag MIOperandInfo = (ops); + // MCOperandPredicate - Optionally, a code fragment operating on + // const MCOperand &MCOp, and returning a bool, to indicate if + // the value of MCOp is valid for the specific subclass of Operand + code MCOperandPredicate; + // ParserMatchClass - The "match class" that operands of this type fit // in. Match classes are used to define the order in which instructions are // match, to ensure that which instructions gets matched is deterministic. diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index 7c42e23..bfddd06 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -93,6 +93,19 @@ public: /// stack pointer. virtual bool isFPCloseToIncomingSP() const { return true; } + /// assignCalleeSavedSpillSlots - Allows target to override spill slot + /// assignment logic. If implemented, assignCalleeSavedSpillSlots() should + /// assign frame slots to all CSI entries and return true. If this method + /// returns false, spill slots will be assigned using generic implementation. + /// assignCalleeSavedSpillSlots() may add, delete or rearrange elements of + /// CSI. + virtual bool + assignCalleeSavedSpillSlots(MachineFunction &MF, + const TargetRegisterInfo *TRI, + std::vector &CSI) const { + return false; + } + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of /// pairs, that contains an entry for each callee saved register that must be /// spilled to a particular stack location if it is spilled. diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 165b35f..87e7c14 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -29,6 +29,7 @@ class MachineRegisterInfo; class MDNode; class MCInst; class MCSchedModel; +class MCSymbolRefExpr; class SDNode; class ScheduleHazardRecognizer; class SelectionDAG; @@ -36,6 +37,7 @@ class ScheduleDAG; class TargetRegisterClass; class TargetRegisterInfo; class BranchProbability; +class TargetSubtargetInfo; template class SmallVectorImpl; @@ -321,6 +323,20 @@ public: virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const; + /// getUnconditionalBranch - Get an instruction that performs an unconditional + /// branch to the given symbol. + virtual void + getUnconditionalBranch(MCInst &MI, + const MCSymbolRefExpr *BranchTarget) const { + llvm_unreachable("Target didn't implement " + "TargetInstrInfo::getUnconditionalBranch!"); + } + + /// getTrap - Get a machine trap instruction + virtual void getTrap(MCInst &MI) const { + llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!"); + } + /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic /// block at the specified instruction (i.e. instruction would be the start /// of a new basic block). @@ -728,7 +744,7 @@ public: /// use for this target when scheduling the machine instructions before /// register allocation. virtual ScheduleHazardRecognizer* - CreateTargetHazardRecognizer(const TargetMachine *TM, + CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const; /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 60a4079..5e9978d 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -185,10 +185,15 @@ public: /// Return true if the target has BitExtract instructions. bool hasExtractBitsInsn() const { return HasExtractBitsInsn; } - /// Return true if a vector of the given type should be split - /// (TypeSplitVector) instead of promoted (TypePromoteInteger) during type - /// legalization. - virtual bool shouldSplitVectorType(EVT /*VT*/) const { return false; } + /// Return the preferred vector type legalization action. + virtual TargetLoweringBase::LegalizeTypeAction + getPreferredVectorAction(EVT VT) const { + // The default action for one element vectors is to scalarize + if (VT.getVectorNumElements() == 1) + return TypeScalarizeVector; + // The default action for other vectors is to promote + return TypePromoteInteger; + } // There are two general methods for expanding a BUILD_VECTOR node: // 1. Use SCALAR_TO_VECTOR on the defined scalar values and then shuffle @@ -279,8 +284,17 @@ public: /// selects between the two kinds. For example on X86 a scalar boolean should /// be zero extended from i1, while the elements of a vector of booleans /// should be sign extended from i1. - BooleanContent getBooleanContents(bool isVec) const { - return isVec ? BooleanVectorContents : BooleanContents; + /// + /// Some cpus also treat floating point types the same way as they treat + /// vectors instead of the way they treat scalars. + BooleanContent getBooleanContents(bool isVec, bool isFloat) const { + if (isVec) + return BooleanVectorContents; + return isFloat ? BooleanFloatContents : BooleanContents; + } + + BooleanContent getBooleanContents(EVT Type) const { + return getBooleanContents(Type.isVector(), Type.isFloatingPoint()); } /// Return target scheduling preference. @@ -711,6 +725,13 @@ public: /// reduce runtime. virtual bool ShouldShrinkFPConstant(EVT) const { return true; } + /// When splitting a value of the specified type into parts, does the Lo + /// or Hi part come first? This usually follows the endianness, except + /// for ppcf128, where the Hi part always comes first. + bool hasBigEndianPartOrdering(EVT VT) const { + return isBigEndian() || VT == MVT::ppcf128; + } + /// If true, the target has custom DAG combine transformations that it can /// perform for the specified node. bool hasTargetDAGCombine(ISD::NodeType NT) const { @@ -938,9 +959,19 @@ public: virtual void resetOperationActions() {} protected: - /// Specify how the target extends the result of a boolean value from i1 to a - /// wider type. See getBooleanContents. - void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } + /// Specify how the target extends the result of integer and floating point + /// boolean values from i1 to a wider type. See getBooleanContents. + void setBooleanContents(BooleanContent Ty) { + BooleanContents = Ty; + BooleanFloatContents = Ty; + } + + /// Specify how the target extends the result of integer and floating point + /// boolean values from i1 to a wider type. See getBooleanContents. + void setBooleanContents(BooleanContent IntTy, BooleanContent FloatTy) { + BooleanContents = IntTy; + BooleanFloatContents = FloatTy; + } /// Specify how the target extends the result of a vector boolean value from a /// vector of i1 to a wider type. See getBooleanContents. @@ -1484,6 +1515,10 @@ private: /// a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; + /// Information about the contents of the high-bits in boolean values held in + /// a type wider than i1. See getBooleanContents. + BooleanContent BooleanFloatContents; + /// Information about the contents of the high-bits in boolean vector values /// when the element type is wider than i1. See getBooleanContents. BooleanContent BooleanVectorContents; @@ -2111,7 +2146,7 @@ public: unsigned NumFixedArgs; CallingConv::ID CallConv; SDValue Callee; - ArgListTy *Args; + ArgListTy Args; SelectionDAG &DAG; SDLoc DL; ImmutableCallSite *CS; @@ -2123,7 +2158,7 @@ public: : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), - Args(nullptr), DAG(DAG), CS(nullptr) {} + DAG(DAG), CS(nullptr) {} CallLoweringInfo &setDebugLoc(SDLoc dl) { DL = dl; @@ -2136,19 +2171,19 @@ public: } CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType, - SDValue Target, ArgListTy *ArgsList, + SDValue Target, ArgListTy &&ArgsList, unsigned FixedArgs = -1) { RetTy = ResultType; Callee = Target; CallConv = CC; NumFixedArgs = - (FixedArgs == static_cast(-1) ? Args->size() : FixedArgs); - Args = ArgsList; + (FixedArgs == static_cast(-1) ? Args.size() : FixedArgs); + Args = std::move(ArgsList); return *this; } CallLoweringInfo &setCallee(Type *ResultType, FunctionType *FTy, - SDValue Target, ArgListTy *ArgsList, + SDValue Target, ArgListTy &&ArgsList, ImmutableCallSite &Call) { RetTy = ResultType; @@ -2163,7 +2198,7 @@ public: CallConv = Call.getCallingConv(); NumFixedArgs = FTy->getNumParams(); - Args = ArgsList; + Args = std::move(ArgsList); CS = &Call; @@ -2206,8 +2241,7 @@ public: } ArgListTy &getArgs() { - assert(Args && "Arguments must be set before accessing them"); - return *Args; + return Args; } }; diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 374a163..419eced 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -131,14 +131,12 @@ public: MCStreamer &Streamer) const; virtual const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym, - const MCSection *KeySec) const { + const MCSymbol *KeySym) const { return StaticCtorSection; } virtual const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym, - const MCSection *KeySec) const { + const MCSymbol *KeySym) const { return StaticDtorSection; } diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 636eaf5..922fae5 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -39,6 +39,17 @@ namespace llvm { }; } + namespace JumpTable { + enum JumpTableType { + Single, // Use a single table for all indirect jumptable calls. + Arity, // Use one table per number of function parameters. + Simplified, // Use one table per function type, with types projected + // into 4 types: pointer to non-function, struct, + // primitive, and function pointer. + Full // Use one table per unique function type + }; + } + class TargetOptions { public: TargetOptions() @@ -54,7 +65,7 @@ namespace llvm { CompressDebugSections(false), FunctionSections(false), DataSections(false), TrapUnreachable(false), TrapFuncName(""), FloatABIType(FloatABI::Default), - AllowFPOpFusion(FPOpFusion::Standard) {} + AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -205,6 +216,10 @@ namespace llvm { /// the value of this option. FPOpFusion::FPOpFusionMode AllowFPOpFusion; + /// JTType - This flag specifies the type of jump-instruction table to + /// create for functions that have the jumptable attribute. + JumpTable::JumpTableType JTType; + /// Machine level options. MCTargetOptions MCOptions; }; diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index a162297..c6f3fbf 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -813,12 +813,6 @@ public: /// getFrameRegister - This method should return the register used as a base /// for values allocated in the current stack frame. virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; - - /// getCompactUnwindRegNum - This function maps the register to the number for - /// compact unwind encoding. Return -1 if the register isn't valid. - virtual int getCompactUnwindRegNum(unsigned, bool) const { - return -1; - } }; diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index 98a5149..78a2db1 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -37,7 +37,7 @@ protected: const DataLayout *getDataLayout() const { return DL; } public: - explicit TargetSelectionDAGInfo(const TargetMachine &TM); + explicit TargetSelectionDAGInfo(const DataLayout *DL); virtual ~TargetSelectionDAGInfo(); /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index c0c342b..bbb83ef 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -66,6 +66,16 @@ public: /// scheduler. It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; + /// \brief True if the subtarget should run PostMachineScheduler. + /// + /// This only takes effect if the target has configured the + /// PostMachineScheduler pass to run, or if the global cl::opt flag, + /// MISchedPostRA, is set. + virtual bool enablePostMachineScheduler() const; + + /// \brief True if the subtarget should run the atomic expansion pass. + virtual bool enableAtomicExpandLoadLinked() const; + /// \brief Override generic scheduling policy within a region. /// /// This is a convenient way for targets that don't provide any custom @@ -90,6 +100,12 @@ public: AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const; + /// \brief True if the subtarget should run the local reassignment + /// heuristic of the register allocator. + /// This heuristic may be compile time intensive, \p OptLevel provides + /// a finer grain to tune the register allocator. + virtual bool enableRALocalReassignment(CodeGenOpt::Level OptLevel) const; + /// \brief Enable use of alias analysis during code generation (during MI /// scheduling, DAGCombine, etc.). virtual bool useAA() const; diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 023de08..50877d0 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -117,6 +117,7 @@ public: bool SLPVectorize; bool LoopVectorize; bool RerollLoops; + bool LoadCombine; private: /// ExtensionList - This is list of all of the extensions that are registered. diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 61d5c26..c6a339b 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -64,18 +64,14 @@ ModulePass *createGCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()); // Insert AddressSanitizer (address sanity checking) instrumentation -FunctionPass *createAddressSanitizerFunctionPass( - bool CheckInitOrder = true, bool CheckUseAfterReturn = false, - bool CheckLifetime = false, StringRef BlacklistFile = StringRef()); -ModulePass *createAddressSanitizerModulePass( - bool CheckInitOrder = true, StringRef BlacklistFile = StringRef()); +FunctionPass *createAddressSanitizerFunctionPass(); +ModulePass *createAddressSanitizerModulePass(); // Insert MemorySanitizer instrumentation (detection of uninitialized reads) -FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0, - StringRef BlacklistFile = StringRef()); +FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0); // Insert ThreadSanitizer (race detection) instrumentation -FunctionPass *createThreadSanitizerPass(StringRef BlacklistFile = StringRef()); +FunctionPass *createThreadSanitizerPass(); // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(), diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index cf1d655..8ecfd80 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -19,6 +19,7 @@ namespace llvm { +class BasicBlockPass; class FunctionPass; class Pass; class GetElementPtrInst; @@ -381,6 +382,12 @@ FunctionPass *createAddDiscriminatorsPass(); // FunctionPass *createSeparateConstOffsetFromGEPPass(); +//===----------------------------------------------------------------------===// +// +// LoadCombine - Combine loads into bigger loads. +// +BasicBlockPass *createLoadCombinePass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 6f64269..c0c6906 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -148,7 +148,7 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr); /// and if a predecessor branches to us and one of our successors, fold the /// setcc into the predecessor and use logical operations to pick the right /// destination. -bool FoldBranchToCommonDest(BranchInst *BI); +bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr); /// DemoteRegToStack - This function takes a virtual register computed by an /// Instruction and replaces it with a slot in the stack frame, allocated via diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index ee26d83..7e3a74a 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -17,6 +17,7 @@ namespace llvm { class AliasAnalysis; class BasicBlock; +class DataLayout; class DominatorTree; class Loop; class LoopInfo; @@ -32,7 +33,8 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); /// will optionally update \c AliasAnalysis and \c ScalarEvolution analyses if /// passed into it. bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, - AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr); + AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr, + const DataLayout *DL = nullptr); /// \brief Put loop into LCSSA form. /// diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h deleted file mode 100644 index 508a6df..0000000 --- a/include/llvm/Transforms/Utils/SpecialCaseList.h +++ /dev/null @@ -1,114 +0,0 @@ -//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===// -// -// This is a utility class for instrumentation passes (like AddressSanitizer -// or ThreadSanitizer) to avoid instrumenting some functions or global -// variables based on a user-supplied list. -// -// The list can also specify categories for specific globals, which can be used -// to instruct an instrumentation pass to treat certain functions or global -// variables in a specific way, such as by omitting certain aspects of -// instrumentation while keeping others, or informing the instrumentation pass -// that a specific uninstrumentable function has certain semantics, thus -// allowing the pass to instrument callers according to those semantics. -// -// For example, AddressSanitizer uses the "init" category for globals whose -// initializers should not be instrumented, but which in all other respects -// should be instrumented. -// -// Each line contains a prefix, followed by a colon and a wild card expression, -// followed optionally by an equals sign and an instrumentation-specific -// category. Empty lines and lines starting with "#" are ignored. -// --- -// # Blacklisted items: -// fun:*_ZN4base6subtle* -// global:*global_with_bad_access_or_initialization* -// global:*global_with_initialization_issues*=init -// type:*Namespace::ClassName*=init -// src:file_with_tricky_code.cc -// src:ignore-global-initializers-issues.cc=init -// -// # Functions with pure functional semantics: -// fun:cos=functional -// fun:sin=functional -// --- -// Note that the wild card is in fact an llvm::Regex, but * is automatically -// replaced with .* -// This is similar to the "ignore" feature of ThreadSanitizer. -// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_UTILS_SPECIALCASELIST_H -#define LLVM_TRANSFORMS_UTILS_SPECIALCASELIST_H - -#include "llvm/ADT/StringMap.h" - -namespace llvm { -class Function; -class GlobalAlias; -class GlobalVariable; -class MemoryBuffer; -class Module; -class Regex; -class StringRef; - -class SpecialCaseList { - public: - /// Parses the special case list from a file. If Path is empty, returns - /// an empty special case list. On failure, returns 0 and writes an error - /// message to string. - static SpecialCaseList *create(const StringRef Path, std::string &Error); - /// Parses the special case list from a memory buffer. On failure, returns - /// 0 and writes an error message to string. - static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); - /// Parses the special case list from a file. On failure, reports a fatal - /// error. - static SpecialCaseList *createOrDie(const StringRef Path); - - ~SpecialCaseList(); - - /// Returns whether either this function or its source file are listed in the - /// given category, which may be omitted to search the empty category. - bool isIn(const Function &F, const StringRef Category = StringRef()) const; - - /// Returns whether this global, its type or its source file are listed in the - /// given category, which may be omitted to search the empty category. - bool isIn(const GlobalVariable &G, - const StringRef Category = StringRef()) const; - - /// Returns whether this global alias is listed in the given category, which - /// may be omitted to search the empty category. - /// - /// If GA aliases a function, the alias's name is matched as a function name - /// would be. Similarly, aliases of globals are matched like globals. - bool isIn(const GlobalAlias &GA, - const StringRef Category = StringRef()) const; - - /// Returns whether this module is listed in the given category, which may be - /// omitted to search the empty category. - bool isIn(const Module &M, const StringRef Category = StringRef()) const; - - private: - SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; - SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; - - struct Entry; - StringMap > Entries; - - SpecialCaseList(); - /// Parses just-constructed SpecialCaseList entries from a memory buffer. - bool parse(const MemoryBuffer *MB, std::string &Error); - - bool inSectionCategory(const StringRef Section, const StringRef Query, - const StringRef Category) const; -}; - -} // namespace llvm - -#endif // LLVM_TRANSFORMS_UTILS_SPECIALCASELIST_H diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h index e1d6c56..44a7149 100644 --- a/include/llvm/Transforms/Utils/VectorUtils.h +++ b/include/llvm/Transforms/Utils/VectorUtils.h @@ -48,12 +48,27 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) { case Intrinsic::pow: case Intrinsic::fma: case Intrinsic::fmuladd: + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::powi: return true; default: return false; } } +static bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, + unsigned ScalarOpdIdx) { + switch (ID) { + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::powi: + return (ScalarOpdIdx == 1); + default: + return false; + } +} + static Intrinsic::ID checkUnaryFloatSignature(const CallInst &I, Intrinsic::ID ValidIntrinsicID) { if (I.getNumArgOperands() != 1 || -- cgit v1.1