diff options
Diffstat (limited to 'llvm/include')
-rw-r--r-- | llvm/include/llvm/ADT/STLExtras.h | 22 | ||||
-rw-r--r-- | llvm/include/llvm/BinaryFormat/DXContainer.h | 70 | ||||
-rw-r--r-- | llvm/include/llvm/CAS/OnDiskDataAllocator.h | 95 | ||||
-rw-r--r-- | llvm/include/llvm/CAS/OnDiskTrieRawHashMap.h | 32 | ||||
-rw-r--r-- | llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h | 8 | ||||
-rw-r--r-- | llvm/include/llvm/Frontend/OpenMP/OMPConstants.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/IR/DebugInfoMetadata.h | 19 | ||||
-rw-r--r-- | llvm/include/llvm/IR/IRBuilder.h | 11 | ||||
-rw-r--r-- | llvm/include/llvm/MC/TargetRegistry.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/Object/OffloadBundle.h | 74 | ||||
-rw-r--r-- | llvm/include/llvm/Option/ArgList.h | 17 | ||||
-rw-r--r-- | llvm/include/llvm/Option/OptParser.td | 46 | ||||
-rw-r--r-- | llvm/include/llvm/Option/OptTable.h | 93 | ||||
-rw-r--r-- | llvm/include/llvm/Option/Option.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/Support/GlobPattern.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/Transforms/IPO/FunctionAttrs.h | 13 |
16 files changed, 375 insertions, 143 deletions
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 4a91b06..5b20d6bd 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1692,6 +1692,28 @@ template <typename R, typename E> auto accumulate(R &&Range, E &&Init) { std::forward<E>(Init)); } +/// Wrapper for std::accumulate with a binary operator. +template <typename R, typename E, typename BinaryOp> +auto accumulate(R &&Range, E &&Init, BinaryOp &&Op) { + return std::accumulate(adl_begin(Range), adl_end(Range), + std::forward<E>(Init), std::forward<BinaryOp>(Op)); +} + +/// Returns the sum of all values in `Range` with `Init` initial value. +/// The default initial value is 0. +template <typename R, typename E = detail::ValueOfRange<R>> +auto sum_of(R &&Range, E Init = E{0}) { + return accumulate(std::forward<R>(Range), std::move(Init)); +} + +/// Returns the product of all values in `Range` with `Init` initial value. +/// The default initial value is 1. +template <typename R, typename E = detail::ValueOfRange<R>> +auto product_of(R &&Range, E Init = E{1}) { + return accumulate(std::forward<R>(Range), std::move(Init), + std::multiplies<>{}); +} + /// Provide wrappers to std::for_each which take ranges instead of having to /// pass begin/end explicitly. template <typename R, typename UnaryFunction> diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index 8944e736..b9a08ce 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -201,19 +201,9 @@ enum class RootParameterType : uint32_t { LLVM_ABI ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes(); -#define ROOT_PARAMETER(Val, Enum) \ - case Val: \ - return true; -inline bool isValidParameterType(uint32_t V) { - switch (V) { -#include "DXContainerConstants.def" - } - return false; -} +bool isValidParameterType(uint32_t V); -inline bool isValidRangeType(uint32_t V) { - return V <= llvm::to_underlying(dxil::ResourceClass::LastEntry); -} +bool isValidRangeType(uint32_t V); #define SHADER_VISIBILITY(Val, Enum) Enum = Val, enum class ShaderVisibility : uint32_t { @@ -222,30 +212,14 @@ enum class ShaderVisibility : uint32_t { LLVM_ABI ArrayRef<EnumEntry<ShaderVisibility>> getShaderVisibility(); -#define SHADER_VISIBILITY(Val, Enum) \ - case Val: \ - return true; -inline bool isValidShaderVisibility(uint32_t V) { - switch (V) { -#include "DXContainerConstants.def" - } - return false; -} +bool isValidShaderVisibility(uint32_t V); #define FILTER(Val, Enum) Enum = Val, enum class SamplerFilter : uint32_t { #include "DXContainerConstants.def" }; -#define FILTER(Val, Enum) \ - case Val: \ - return true; -inline bool isValidSamplerFilter(uint32_t V) { - switch (V) { -#include "DXContainerConstants.def" - } - return false; -} +bool isValidSamplerFilter(uint32_t V); LLVM_ABI ArrayRef<EnumEntry<SamplerFilter>> getSamplerFilters(); @@ -256,15 +230,7 @@ enum class TextureAddressMode : uint32_t { LLVM_ABI ArrayRef<EnumEntry<TextureAddressMode>> getTextureAddressModes(); -#define TEXTURE_ADDRESS_MODE(Val, Enum) \ - case Val: \ - return true; -inline bool isValidAddress(uint32_t V) { - switch (V) { -#include "DXContainerConstants.def" - } - return false; -} +bool isValidAddress(uint32_t V); #define COMPARISON_FUNC(Val, Enum) Enum = Val, enum class ComparisonFunc : uint32_t { @@ -273,30 +239,20 @@ enum class ComparisonFunc : uint32_t { LLVM_ABI ArrayRef<EnumEntry<ComparisonFunc>> getComparisonFuncs(); -#define COMPARISON_FUNC(Val, Enum) \ - case Val: \ - return true; -inline bool isValidComparisonFunc(uint32_t V) { - switch (V) { -#include "DXContainerConstants.def" - } - return false; -} +bool isValidComparisonFunc(uint32_t V); #define STATIC_BORDER_COLOR(Val, Enum) Enum = Val, enum class StaticBorderColor : uint32_t { #include "DXContainerConstants.def" }; -#define STATIC_BORDER_COLOR(Val, Enum) \ - case Val: \ - return true; -inline bool isValidBorderColor(uint32_t V) { - switch (V) { -#include "DXContainerConstants.def" - } - return false; -} +bool isValidBorderColor(uint32_t V); + +bool isValidRootDesciptorFlags(uint32_t V); + +bool isValidDescriptorRangeFlags(uint32_t V); + +bool isValidStaticSamplerFlags(uint32_t V); LLVM_ABI ArrayRef<EnumEntry<StaticBorderColor>> getStaticBorderColors(); diff --git a/llvm/include/llvm/CAS/OnDiskDataAllocator.h b/llvm/include/llvm/CAS/OnDiskDataAllocator.h new file mode 100644 index 0000000..2809df8 --- /dev/null +++ b/llvm/include/llvm/CAS/OnDiskDataAllocator.h @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file declares interface for OnDiskDataAllocator, a file backed data +/// pool can be used to allocate space to store data packed in a single file. It +/// is based on MappedFileRegionArena and includes a header in the beginning to +/// provide metadata. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CAS_ONDISKDATAALLOCATOR_H +#define LLVM_CAS_ONDISKDATAALLOCATOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/CAS/FileOffset.h" +#include "llvm/Support/Error.h" + +namespace llvm::cas { + +/// Sink for data. Stores variable length data with 8-byte alignment. Does not +/// track size of data, which is assumed to known from context, or embedded. +/// Uses 0-padding but does not guarantee 0-termination. +class OnDiskDataAllocator { +public: + using ValueProxy = MutableArrayRef<char>; + + /// A pointer to data stored on disk. + class OnDiskPtr { + public: + FileOffset getOffset() const { return Offset; } + explicit operator bool() const { return bool(getOffset()); } + const ValueProxy &operator*() const { + assert(Offset && "Null dereference"); + return Value; + } + const ValueProxy *operator->() const { + assert(Offset && "Null dereference"); + return &Value; + } + + OnDiskPtr() = default; + + private: + friend class OnDiskDataAllocator; + OnDiskPtr(FileOffset Offset, ValueProxy Value) + : Offset(Offset), Value(Value) {} + FileOffset Offset; + ValueProxy Value; + }; + + /// Get the data of \p Size stored at the given \p Offset. Note the allocator + /// doesn't keep track of the allocation size, thus \p Size doesn't need to + /// match the size of allocation but needs to be smaller. + Expected<ArrayRef<char>> get(FileOffset Offset, size_t Size) const; + + /// Allocate at least \p Size with 8-byte alignment. + Expected<OnDiskPtr> allocate(size_t Size); + + /// \returns the buffer that was allocated at \p create time, with size + /// \p UserHeaderSize. + MutableArrayRef<uint8_t> getUserHeader(); + + size_t size() const; + size_t capacity() const; + + static Expected<OnDiskDataAllocator> + create(const Twine &Path, const Twine &TableName, uint64_t MaxFileSize, + std::optional<uint64_t> NewFileInitialSize, + uint32_t UserHeaderSize = 0, + function_ref<void(void *)> UserHeaderInit = nullptr); + + OnDiskDataAllocator(OnDiskDataAllocator &&RHS); + OnDiskDataAllocator &operator=(OnDiskDataAllocator &&RHS); + + // No copy. Just call \a create() again. + OnDiskDataAllocator(const OnDiskDataAllocator &) = delete; + OnDiskDataAllocator &operator=(const OnDiskDataAllocator &) = delete; + + ~OnDiskDataAllocator(); + +private: + struct ImplType; + explicit OnDiskDataAllocator(std::unique_ptr<ImplType> Impl); + std::unique_ptr<ImplType> Impl; +}; + +} // namespace llvm::cas + +#endif // LLVM_CAS_ONDISKDATAALLOCATOR_H diff --git a/llvm/include/llvm/CAS/OnDiskTrieRawHashMap.h b/llvm/include/llvm/CAS/OnDiskTrieRawHashMap.h index 5e41bf6..fbd68d0 100644 --- a/llvm/include/llvm/CAS/OnDiskTrieRawHashMap.h +++ b/llvm/include/llvm/CAS/OnDiskTrieRawHashMap.h @@ -133,38 +133,38 @@ public: bool IsValue = false; }; - class pointer; - class const_pointer : public PointerImpl<ConstValueProxy> { + class OnDiskPtr; + class ConstOnDiskPtr : public PointerImpl<ConstValueProxy> { public: - const_pointer() = default; + ConstOnDiskPtr() = default; private: - friend class pointer; + friend class OnDiskPtr; friend class OnDiskTrieRawHashMap; - using const_pointer::PointerImpl::PointerImpl; + using ConstOnDiskPtr::PointerImpl::PointerImpl; }; - class pointer : public PointerImpl<ValueProxy> { + class OnDiskPtr : public PointerImpl<ValueProxy> { public: - operator const_pointer() const { - return const_pointer(Value, getOffset(), IsValue); + operator ConstOnDiskPtr() const { + return ConstOnDiskPtr(Value, getOffset(), IsValue); } - pointer() = default; + OnDiskPtr() = default; private: friend class OnDiskTrieRawHashMap; - using pointer::PointerImpl::PointerImpl; + using OnDiskPtr::PointerImpl::PointerImpl; }; /// Find the value from hash. /// /// \returns pointer to the value if exists, otherwise returns a non-value /// pointer that evaluates to `false` when convert to boolean. - const_pointer find(ArrayRef<uint8_t> Hash) const; + ConstOnDiskPtr find(ArrayRef<uint8_t> Hash) const; /// Helper function to recover a pointer into the trie from file offset. - Expected<const_pointer> recoverFromFileOffset(FileOffset Offset) const; + Expected<ConstOnDiskPtr> recoverFromFileOffset(FileOffset Offset) const; using LazyInsertOnConstructCB = function_ref<void(FileOffset TentativeOffset, ValueProxy TentativeValue)>; @@ -186,11 +186,11 @@ public: /// The in-memory \a TrieRawHashMap uses LazyAtomicPointer to synchronize /// simultaneous writes, but that seems dangerous to use in a memory-mapped /// file in case a process crashes in the busy state. - Expected<pointer> insertLazy(ArrayRef<uint8_t> Hash, - LazyInsertOnConstructCB OnConstruct = nullptr, - LazyInsertOnLeakCB OnLeak = nullptr); + Expected<OnDiskPtr> insertLazy(ArrayRef<uint8_t> Hash, + LazyInsertOnConstructCB OnConstruct = nullptr, + LazyInsertOnLeakCB OnLeak = nullptr); - Expected<pointer> insert(const ConstValueProxy &Value) { + Expected<OnDiskPtr> insert(const ConstValueProxy &Value) { return insertLazy(Value.Hash, [&](FileOffset, ValueProxy Allocated) { assert(Allocated.Hash == Value.Hash); assert(Allocated.Data.size() == Value.Data.size()); diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h index 4dd1811..7131980 100644 --- a/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h +++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h @@ -28,12 +28,14 @@ LLVM_ABI bool verifyRootFlag(uint32_t Flags); LLVM_ABI bool verifyVersion(uint32_t Version); LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue); LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace); -LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); +LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, + dxbc::RootDescriptorFlags Flags); LLVM_ABI bool verifyRangeType(uint32_t Type); LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, dxil::ResourceClass Type, - dxbc::DescriptorRangeFlags FlagsVal); -LLVM_ABI bool verifyStaticSamplerFlags(uint32_t Version, uint32_t FlagsNumber); + dxbc::DescriptorRangeFlags Flags); +LLVM_ABI bool verifyStaticSamplerFlags(uint32_t Version, + dxbc::StaticSamplerFlags Flags); LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors); LLVM_ABI bool verifyMipLODBias(float MipLODBias); LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h index 6e1bce1..7bec7e0 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h @@ -239,6 +239,9 @@ enum class OpenMPOffloadMappingFlags : uint64_t { // dynamic. // This is an OpenMP extension for the sake of OpenACC support. OMP_MAP_OMPX_HOLD = 0x2000, + // Attach pointer and pointee, after processing all other maps. + // Applicable to map-entering directives. Does not change ref-count. + OMP_MAP_ATTACH = 0x4000, /// Signal that the runtime library should use args as an array of /// descriptor_dim pointers and use args_size as dims. Used when we have /// non-contiguous list items in target update directive diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 6652e30..7c6e709 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2600,14 +2600,19 @@ public: StringRef getDirectory() const { return getScope()->getDirectory(); } std::optional<StringRef> getSource() const { return getScope()->getSource(); } - /// Get the scope where this is inlined. - /// - /// Walk through \a getInlinedAt() and return \a getScope() from the deepest - /// location. + /// Walk through \a getInlinedAt() and return the \a DILocation of the + /// outermost call site in the inlining chain. + const DILocation *getInlinedAtLocation() const { + const DILocation *Current = this; + while (const DILocation *Next = Current->getInlinedAt()) + Current = Next; + return Current; + } + + // Return the \a DILocalScope of the outermost call site in the inlining + // chain. DILocalScope *getInlinedAtScope() const { - if (auto *IA = getInlinedAt()) - return IA->getInlinedAtScope(); - return getScope(); + return getInlinedAtLocation()->getScope(); } /// Get the DWARF discriminator. diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 783f8f6..041a4ce 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -1722,16 +1722,19 @@ public: return Insert(BinOp, Name); } - Value *CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name = "") { + Value *CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name = "", + Instruction *MDFrom = nullptr) { assert(Cond2->getType()->isIntOrIntVectorTy(1)); return CreateSelect(Cond1, Cond2, - ConstantInt::getNullValue(Cond2->getType()), Name); + ConstantInt::getNullValue(Cond2->getType()), Name, + MDFrom); } - Value *CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name = "") { + Value *CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name = "", + Instruction *MDFrom = nullptr) { assert(Cond2->getType()->isIntOrIntVectorTy(1)); return CreateSelect(Cond1, ConstantInt::getAllOnesValue(Cond2->getType()), - Cond2, Name); + Cond2, Name, MDFrom); } Value *CreateLogicalOp(Instruction::BinaryOps Opc, Value *Cond1, Value *Cond2, diff --git a/llvm/include/llvm/MC/TargetRegistry.h b/llvm/include/llvm/MC/TargetRegistry.h index 570d4c0..234c587 100644 --- a/llvm/include/llvm/MC/TargetRegistry.h +++ b/llvm/include/llvm/MC/TargetRegistry.h @@ -737,7 +737,8 @@ struct TargetRegistry { /// \param TripleStr - The triple to use for finding a target. /// \param Error - On failure, an error string describing why no target was /// found. - // TODO: Drop this in favor of the method accepting Triple. + // TODO(boomanaiden154): Remove this function after LLVM 22 branches. + [[deprecated("Use overload accepting Triple instead")]] static const Target *lookupTarget(StringRef TripleStr, std::string &Error) { return lookupTarget(Triple(TripleStr), Error); } diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h index 18be62b..bbb313c0 100644 --- a/llvm/include/llvm/Object/OffloadBundle.h +++ b/llvm/include/llvm/Object/OffloadBundle.h @@ -32,29 +32,41 @@ namespace llvm { namespace object { +// CompressedOffloadBundle represents the format for the compressed offload +// bundles. +// +// The format is as follows: +// - Magic Number (4 bytes) - A constant "CCOB". +// - Version (2 bytes) +// - Compression Method (2 bytes) - Uses the values from +// llvm::compression::Format. +// - Total file size (4 bytes in V2, 8 bytes in V3). +// - Uncompressed Size (4 bytes in V1/V2, 8 bytes in V3). +// - Truncated MD5 Hash (8 bytes). +// - Compressed Data (variable length). class CompressedOffloadBundle { private: - static inline const size_t MagicSize = 4; - static inline const size_t VersionFieldSize = sizeof(uint16_t); - static inline const size_t MethodFieldSize = sizeof(uint16_t); - static inline const size_t FileSizeFieldSize = sizeof(uint32_t); - static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t); - static inline const size_t HashFieldSize = sizeof(uint64_t); - static inline const size_t V1HeaderSize = - MagicSize + VersionFieldSize + MethodFieldSize + - UncompressedSizeFieldSize + HashFieldSize; - static inline const size_t V2HeaderSize = - MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize + - UncompressedSizeFieldSize + HashFieldSize; static inline const llvm::StringRef MagicNumber = "CCOB"; - static inline const uint16_t Version = 2; public: - LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + struct CompressedBundleHeader { + unsigned Version; + llvm::compression::Format CompressionFormat; + std::optional<size_t> FileSize; + size_t UncompressedFileSize; + uint64_t Hash; + + static llvm::Expected<CompressedBundleHeader> tryParse(llvm::StringRef); + }; + + static inline const uint16_t DefaultVersion = 3; + + static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input, - bool Verbose = false); - LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> - decompress(llvm::MemoryBufferRef &Input, bool Verbose = false); + uint16_t Version, raw_ostream *VerboseStream = nullptr); + static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + decompress(const llvm::MemoryBuffer &Input, + raw_ostream *VerboseStream = nullptr); }; /// Bundle entry in binary clang-offload-bundler format. @@ -62,12 +74,12 @@ struct OffloadBundleEntry { uint64_t Offset = 0u; uint64_t Size = 0u; uint64_t IDLength = 0u; - StringRef ID; + std::string ID; OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T) - : Offset(O), Size(S), IDLength(I), ID(T) {} + : Offset(O), Size(S), IDLength(I), ID(T.str()) {} void dumpInfo(raw_ostream &OS) { OS << "Offset = " << Offset << ", Size = " << Size - << ", ID Length = " << IDLength << ", ID = " << ID; + << ", ID Length = " << IDLength << ", ID = " << ID << "\n"; } void dumpURI(raw_ostream &OS, StringRef FilePath) { OS << ID.data() << "\tfile://" << FilePath << "#offset=" << Offset @@ -81,16 +93,21 @@ class OffloadBundleFatBin { uint64_t Size = 0u; StringRef FileName; uint64_t NumberOfEntries; + bool Decompressed; SmallVector<OffloadBundleEntry> Entries; public: + std::unique_ptr<MemoryBuffer> DecompressedBuffer; + SmallVector<OffloadBundleEntry> getEntries() { return Entries; } uint64_t getSize() const { return Size; } StringRef getFileName() const { return FileName; } uint64_t getNumEntries() const { return NumberOfEntries; } + bool isDecompressed() const { return Decompressed; } LLVM_ABI static Expected<std::unique_ptr<OffloadBundleFatBin>> - create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName); + create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName, + bool Decompress = false); LLVM_ABI Error extractBundle(const ObjectFile &Source); LLVM_ABI Error dumpEntryToCodeObject(); @@ -106,9 +123,14 @@ public: Entry.dumpURI(outs(), FileName); } - OffloadBundleFatBin(MemoryBufferRef Source, StringRef File) - : FileName(File), NumberOfEntries(0), - Entries(SmallVector<OffloadBundleEntry>()) {} + OffloadBundleFatBin(MemoryBufferRef Source, StringRef File, + bool Decompress = false) + : FileName(File), NumberOfEntries(0), Decompressed(Decompress), + Entries(SmallVector<OffloadBundleEntry>()) { + if (Decompress) + DecompressedBuffer = + MemoryBuffer::getMemBufferCopy(Source.getBuffer(), File); + } }; enum UriTypeT { FILE_URI, MEMORY_URI }; @@ -191,6 +213,10 @@ LLVM_ABI Error extractOffloadBundleFatBinary( LLVM_ABI Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size, StringRef OutputFileName); +/// Extract code object memory from the given \p Source object file at \p Offset +/// and of \p Size, and copy into \p OutputFileName. +LLVM_ABI Error extractCodeObject(MemoryBufferRef Buffer, int64_t Offset, + int64_t Size, StringRef OutputFileName); /// Extracts an Offload Bundle Entry given by URI LLVM_ABI Error extractOffloadBundleByURI(StringRef URIstr); diff --git a/llvm/include/llvm/Option/ArgList.h b/llvm/include/llvm/Option/ArgList.h index 3e80574..db36509 100644 --- a/llvm/include/llvm/Option/ArgList.h +++ b/llvm/include/llvm/Option/ArgList.h @@ -20,6 +20,7 @@ #include "llvm/Option/OptSpecifier.h" #include "llvm/Option/Option.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" #include <algorithm> #include <cstddef> #include <initializer_list> @@ -280,6 +281,22 @@ public: /// list. virtual unsigned getNumInputArgStrings() const = 0; + /// getSubCommand - Find subcommand from the arguments if the usage is valid. + /// + /// \param AllSubCommands - A list of all valid subcommands. + /// \param HandleMultipleSubcommands - A callback for the case where multiple + /// subcommands are present in the arguments. It gets a list of all found + /// subcommands. + /// \param HandleOtherPositionals - A callback for the case where positional + /// arguments that are not subcommands are present. + /// \return The name of the subcommand found. If no subcommand is found, + /// this returns an empty StringRef. If multiple subcommands are found, the + /// first one is returned. + StringRef getSubCommand( + ArrayRef<OptTable::SubCommand> AllSubCommands, + std::function<void(ArrayRef<StringRef>)> HandleMultipleSubcommands, + std::function<void(ArrayRef<StringRef>)> HandleOtherPositionals) const; + /// @} /// @name Argument Lookup Utilities /// @{ diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td index 9fd606b..8f32fb4 100644 --- a/llvm/include/llvm/Option/OptParser.td +++ b/llvm/include/llvm/Option/OptParser.td @@ -98,7 +98,15 @@ class HelpTextVariant<list<OptionVisibility> visibilities, string text> { string Text = text; } -class Option<list<string> prefixes, string name, OptionKind kind> { +// Class definition for positional subcommands. +class SubCommand<string name, string helpText, string usage = ""> { + string Name = name; + string HelpText = helpText; + string Usage = usage; +} + +class Option<list<string> prefixes, string name, OptionKind kind, + list<SubCommand> subcommands = []> { string EnumName = ?; // Uses the def name if undefined. list<string> Prefixes = prefixes; string Name = name; @@ -129,26 +137,34 @@ class Option<list<string> prefixes, string name, OptionKind kind> { code ValueMerger = "mergeForwardValue"; code ValueExtractor = "extractForwardValue"; list<code> NormalizedValues = ?; + list<SubCommand> SubCommands = subcommands; } // Helpers for defining options. -class Flag<list<string> prefixes, string name> - : Option<prefixes, name, KIND_FLAG>; -class Joined<list<string> prefixes, string name> - : Option<prefixes, name, KIND_JOINED>; -class Separate<list<string> prefixes, string name> - : Option<prefixes, name, KIND_SEPARATE>; -class CommaJoined<list<string> prefixes, string name> - : Option<prefixes, name, KIND_COMMAJOINED>; -class MultiArg<list<string> prefixes, string name, int numargs> - : Option<prefixes, name, KIND_MULTIARG> { +class Flag<list<string> prefixes, string name, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_FLAG, subcommands>; +class Joined<list<string> prefixes, string name, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_JOINED, subcommands>; +class Separate<list<string> prefixes, string name, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_SEPARATE, subcommands>; +class CommaJoined<list<string> prefixes, string name, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_COMMAJOINED, subcommands>; +class MultiArg<list<string> prefixes, string name, int numargs, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_MULTIARG, subcommands> { int NumArgs = numargs; } -class JoinedOrSeparate<list<string> prefixes, string name> - : Option<prefixes, name, KIND_JOINED_OR_SEPARATE>; -class JoinedAndSeparate<list<string> prefixes, string name> - : Option<prefixes, name, KIND_JOINED_AND_SEPARATE>; +class JoinedOrSeparate<list<string> prefixes, string name, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_JOINED_OR_SEPARATE, subcommands>; +class JoinedAndSeparate<list<string> prefixes, string name, + list<SubCommand> subcommands = []> + : Option<prefixes, name, KIND_JOINED_AND_SEPARATE, subcommands>; // Mix-ins for adding optional attributes. diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h index df42ee3..f641ca4 100644 --- a/llvm/include/llvm/Option/OptTable.h +++ b/llvm/include/llvm/Option/OptTable.h @@ -53,6 +53,13 @@ public: /// parts of the driver still use Option instances where convenient. class LLVM_ABI OptTable { public: + /// Represents a subcommand and its options in the option table. + struct SubCommand { + const char *Name; + const char *HelpText; + const char *Usage; + }; + /// Entry for a single option instance in the option data table. struct Info { unsigned PrefixesOffset; @@ -79,6 +86,8 @@ public: unsigned short AliasID; const char *AliasArgs; const char *Values; + // Offset into OptTable's SubCommandIDsTable. + unsigned SubCommandIDsOffset; bool hasNoPrefix() const { return PrefixesOffset == 0; } @@ -94,6 +103,21 @@ public: getNumPrefixes(PrefixesTable)); } + bool hasSubCommands() const { return SubCommandIDsOffset != 0; } + + unsigned getNumSubCommandIDs(ArrayRef<unsigned> SubCommandIDsTable) const { + // We embed the number of subcommand IDs in the value of the first offset. + return SubCommandIDsTable[SubCommandIDsOffset]; + } + + ArrayRef<unsigned> + getSubCommandIDs(ArrayRef<unsigned> SubCommandIDsTable) const { + return hasSubCommands() ? SubCommandIDsTable.slice( + SubCommandIDsOffset + 1, + getNumSubCommandIDs(SubCommandIDsTable)) + : ArrayRef<unsigned>(); + } + void appendPrefixes(const StringTable &StrTable, ArrayRef<StringTable::Offset> PrefixesTable, SmallVectorImpl<StringRef> &Prefixes) const { @@ -119,6 +143,22 @@ public: } }; +public: + bool isValidForSubCommand(const Info *CandidateInfo, + StringRef SubCommand) const { + assert(!SubCommand.empty() && + "This helper is only for valid registered subcommands."); + auto SCIT = + std::find_if(SubCommands.begin(), SubCommands.end(), + [&](const auto &C) { return SubCommand == C.Name; }); + assert(SCIT != SubCommands.end() && + "This helper is only for valid registered subcommands."); + auto SubCommandIDs = CandidateInfo->getSubCommandIDs(SubCommandIDsTable); + unsigned CurrentSubCommandID = SCIT - &SubCommands[0]; + return std::find(SubCommandIDs.begin(), SubCommandIDs.end(), + CurrentSubCommandID) != SubCommandIDs.end(); + } + private: // A unified string table for these options. Individual strings are stored as // null terminated C-strings at offsets within this table. @@ -134,6 +174,13 @@ private: ArrayRef<Info> OptionInfos; bool IgnoreCase; + + /// The subcommand information table. + ArrayRef<SubCommand> SubCommands; + + /// The subcommand IDs table. + ArrayRef<unsigned> SubCommandIDsTable; + bool GroupedShortOptions = false; bool DashDashParsing = false; const char *EnvVar = nullptr; @@ -168,7 +215,9 @@ protected: /// manually call \c buildPrefixChars once they are fully constructed. OptTable(const StringTable &StrTable, ArrayRef<StringTable::Offset> PrefixesTable, - ArrayRef<Info> OptionInfos, bool IgnoreCase = false); + ArrayRef<Info> OptionInfos, bool IgnoreCase = false, + ArrayRef<SubCommand> SubCommands = {}, + ArrayRef<unsigned> SubCommandIDsTable = {}); /// Build (or rebuild) the PrefixChars member. void buildPrefixChars(); @@ -179,6 +228,8 @@ public: /// Return the string table used for option names. const StringTable &getStrTable() const { return *StrTable; } + ArrayRef<SubCommand> getSubCommands() const { return SubCommands; } + /// Return the prefixes table used for option names. ArrayRef<StringTable::Offset> getPrefixesTable() const { return PrefixesTable; @@ -410,7 +461,8 @@ public: /// texts. void printHelp(raw_ostream &OS, const char *Usage, const char *Title, bool ShowHidden = false, bool ShowAllAliases = false, - Visibility VisibilityMask = Visibility()) const; + Visibility VisibilityMask = Visibility(), + StringRef SubCommand = {}) const; void printHelp(raw_ostream &OS, const char *Usage, const char *Title, unsigned FlagsToInclude, unsigned FlagsToExclude, @@ -418,7 +470,8 @@ public: private: void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title, - bool ShowHidden, bool ShowAllAliases, + StringRef SubCommand, bool ShowHidden, + bool ShowAllAliases, std::function<bool(const Info &)> ExcludeOption, Visibility VisibilityMask) const; }; @@ -428,7 +481,9 @@ class GenericOptTable : public OptTable { protected: LLVM_ABI GenericOptTable(const StringTable &StrTable, ArrayRef<StringTable::Offset> PrefixesTable, - ArrayRef<Info> OptionInfos, bool IgnoreCase = false); + ArrayRef<Info> OptionInfos, bool IgnoreCase = false, + ArrayRef<SubCommand> SubCommands = {}, + ArrayRef<unsigned> SubCommandIDsTable = {}); }; class PrecomputedOptTable : public OptTable { @@ -437,8 +492,11 @@ protected: ArrayRef<StringTable::Offset> PrefixesTable, ArrayRef<Info> OptionInfos, ArrayRef<StringTable::Offset> PrefixesUnionOffsets, - bool IgnoreCase = false) - : OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) { + bool IgnoreCase = false, + ArrayRef<SubCommand> SubCommands = {}, + ArrayRef<unsigned> SubCommandIDsTable = {}) + : OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase, SubCommands, + SubCommandIDsTable) { for (auto PrefixOffset : PrefixesUnionOffsets) PrefixesUnion.push_back(StrTable[PrefixOffset]); buildPrefixChars(); @@ -452,33 +510,36 @@ protected: #define LLVM_MAKE_OPT_ID_WITH_ID_PREFIX( \ ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ - METAVAR, VALUES) \ + METAVAR, VALUES, SUBCOMMANDIDS_OFFSET) \ ID_PREFIX##ID #define LLVM_MAKE_OPT_ID(PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, \ GROUP, ALIAS, ALIASARGS, FLAGS, VISIBILITY, PARAM, \ - HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ - LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, \ - ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - VISIBILITY, PARAM, HELPTEXT, \ - HELPTEXTSFORVARIANTS, METAVAR, VALUES) + HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ + SUBCOMMANDIDS_OFFSET) \ + LLVM_MAKE_OPT_ID_WITH_ID_PREFIX( \ + OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ + ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ + METAVAR, VALUES, SUBCOMMANDIDS_OFFSET) #define LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \ ID_PREFIX, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ - METAVAR, VALUES) \ + METAVAR, VALUES, SUBCOMMANDIDS_OFFSET) \ llvm::opt::OptTable::Info { \ PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, HELPTEXT, HELPTEXTSFORVARIANTS, \ METAVAR, ID_PREFIX##ID, llvm::opt::Option::KIND##Class, PARAM, FLAGS, \ - VISIBILITY, ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES \ + VISIBILITY, ID_PREFIX##GROUP, ID_PREFIX##ALIAS, ALIASARGS, VALUES, \ + SUBCOMMANDIDS_OFFSET \ } #define LLVM_CONSTRUCT_OPT_INFO( \ PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \ - FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES) \ + FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ + SUBCOMMANDIDS_OFFSET) \ LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX( \ OPT_, PREFIXES_OFFSET, PREFIXED_NAME_OFFSET, ID, KIND, GROUP, ALIAS, \ ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ - METAVAR, VALUES) + METAVAR, VALUES, SUBCOMMANDIDS_OFFSET) #endif // LLVM_OPTION_OPTTABLE_H diff --git a/llvm/include/llvm/Option/Option.h b/llvm/include/llvm/Option/Option.h index 51c330a..192cb3c9 100644 --- a/llvm/include/llvm/Option/Option.h +++ b/llvm/include/llvm/Option/Option.h @@ -216,6 +216,12 @@ public: /// always be false. LLVM_ABI bool matches(OptSpecifier ID) const; + LLVM_ABI bool isRegisteredSC(StringRef SubCommand) const { + assert(Info && "Must have a valid info!"); + assert(Owner && "Must have a valid owner!"); + return Owner->isValidForSubCommand(Info, SubCommand); + } + /// Potentially accept the current argument, returning a new Arg instance, /// or 0 if the option does not accept this argument (or the argument is /// missing values). diff --git a/llvm/include/llvm/Support/GlobPattern.h b/llvm/include/llvm/Support/GlobPattern.h index 62ed4a0..c1b4484 100644 --- a/llvm/include/llvm/Support/GlobPattern.h +++ b/llvm/include/llvm/Support/GlobPattern.h @@ -65,13 +65,19 @@ public: bool isTrivialMatchAll() const { if (!Prefix.empty()) return false; + if (!Suffix.empty()) + return false; if (SubGlobs.size() != 1) return false; return SubGlobs[0].getPat() == "*"; } + StringRef prefix() const { return Prefix; } + StringRef suffix() const { return Suffix; } + private: StringRef Prefix; + StringRef Suffix; struct SubGlobPattern { /// \param Pat the pattern to match against diff --git a/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h b/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h index 754714d..eaca0a8 100644 --- a/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h @@ -79,6 +79,19 @@ public: LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; +/// Additional 'norecurse' attribute deduction during postlink LTO phase. +/// +/// This is a module pass that infers 'norecurse' attribute on functions. +/// It runs during LTO and analyzes the module's call graph to find functions +/// that are guaranteed not to call themselves, either directly or indirectly. +/// The pass uses a module-wide flag which checks if any function's address is +/// taken or any function in the module has external linkage, to safely handle +/// indirect and library function calls from current function. +class NoRecurseLTOInferencePass + : public PassInfoMixin<NoRecurseLTOInferencePass> { +public: + LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +}; } // end namespace llvm #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H |