diff options
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r-- | llvm/lib/Support/AArch64AttributeParser.cpp | 27 | ||||
-rw-r--r-- | llvm/lib/Support/CommandLine.cpp | 27 | ||||
-rw-r--r-- | llvm/lib/Support/Debug.cpp | 69 |
3 files changed, 106 insertions, 17 deletions
diff --git a/llvm/lib/Support/AArch64AttributeParser.cpp b/llvm/lib/Support/AArch64AttributeParser.cpp index c675ef2..eed8dba 100644 --- a/llvm/lib/Support/AArch64AttributeParser.cpp +++ b/llvm/lib/Support/AArch64AttributeParser.cpp @@ -8,6 +8,7 @@ //===---------------------------------------------------------------------===// #include "llvm/Support/AArch64AttributeParser.h" +#include "llvm/Support/AArch64BuildAttributes.h" std::vector<llvm::SubsectionAndTagToTagName> & llvm::AArch64AttributeParser::returnTagsNamesMap() { @@ -19,3 +20,29 @@ llvm::AArch64AttributeParser::returnTagsNamesMap() { {"aeabi_feature_and_bits", 2, "Tag_Feature_GCS"}}; return TagsNamesMap; } + +llvm::AArch64BuildAttrSubsections llvm::extractBuildAttributesSubsections( + const llvm::AArch64AttributeParser &Attributes) { + + llvm::AArch64BuildAttrSubsections SubSections; + auto GetPauthValue = [&Attributes](unsigned Tag) { + return Attributes.getAttributeValue("aeabi_pauthabi", Tag).value_or(0); + }; + SubSections.Pauth.TagPlatform = + GetPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_PLATFORM); + SubSections.Pauth.TagSchema = + GetPauthValue(llvm::AArch64BuildAttributes::TAG_PAUTH_SCHEMA); + + auto GetFeatureValue = [&Attributes](unsigned Tag) { + return Attributes.getAttributeValue("aeabi_feature_and_bits", Tag) + .value_or(0); + }; + SubSections.AndFeatures |= + GetFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_BTI); + SubSections.AndFeatures |= + GetFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_PAC) << 1; + SubSections.AndFeatures |= + GetFeatureValue(llvm::AArch64BuildAttributes::TAG_FEATURE_GCS) << 2; + + return SubSections; +} diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp index d5c3cba..8491633 100644 --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -68,11 +68,19 @@ template class LLVM_EXPORT_TEMPLATE basic_parser<float>; template class LLVM_EXPORT_TEMPLATE basic_parser<std::string>; template class LLVM_EXPORT_TEMPLATE basic_parser<char>; -template class opt<unsigned>; -template class opt<int>; -template class opt<std::string>; -template class opt<char>; -template class opt<bool>; +#if !(defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) && defined(_MSC_VER)) +// Only instantiate opt<std::string> when not building a Windows DLL. When +// exporting opt<std::string>, MSVC implicitly exports symbols for +// std::basic_string through transitive inheritance via std::string. These +// symbols may appear in clients, leading to duplicate symbol conflicts. +template class LLVM_EXPORT_TEMPLATE opt<std::string>; +#endif + +template class LLVM_EXPORT_TEMPLATE opt<bool>; +template class LLVM_EXPORT_TEMPLATE opt<char>; +template class LLVM_EXPORT_TEMPLATE opt<int>; +template class LLVM_EXPORT_TEMPLATE opt<unsigned>; + } // namespace cl } // namespace llvm @@ -95,6 +103,15 @@ void parser<float>::anchor() {} void parser<std::string>::anchor() {} void parser<char>::anchor() {} +// These anchor functions instantiate opt<T> and reference its virtual +// destructor to ensure MSVC exports the corresponding vtable and typeinfo when +// building a Windows DLL. Without an explicit reference, MSVC may omit the +// instantiation at link time even if it is marked DLL-export. +void opt_bool_anchor() { opt<bool> anchor{""}; } +void opt_char_anchor() { opt<char> anchor{""}; } +void opt_int_anchor() { opt<int> anchor{""}; } +void opt_unsigned_anchor() { opt<unsigned> anchor{""}; } + //===----------------------------------------------------------------------===// const static size_t DefaultPad = 2; diff --git a/llvm/lib/Support/Debug.cpp b/llvm/lib/Support/Debug.cpp index 5bb04d0..b6f338f 100644 --- a/llvm/lib/Support/Debug.cpp +++ b/llvm/lib/Support/Debug.cpp @@ -24,11 +24,13 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Debug.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Signals.h" #include "llvm/Support/circular_raw_ostream.h" #include "llvm/Support/raw_ostream.h" +#include <utility> #include "DebugOptions.h" @@ -38,27 +40,62 @@ using namespace llvm; +/// Parse a debug type string into a pair of the debug type and the debug level. +/// The expected format is "type[:level]", where the level is an optional +/// integer. +static std::pair<std::string, std::optional<int>> +parseDebugType(StringRef DbgType) { + std::optional<int> Level; + size_t ColonPos = DbgType.find(':'); + if (ColonPos != StringRef::npos) { + StringRef LevelStr = DbgType.substr(ColonPos + 1); + DbgType = DbgType.take_front(ColonPos); + if (LevelStr.empty()) + Level = 0; + else { + int parsedLevel; + if (to_integer(LevelStr, parsedLevel, 10)) + Level = parsedLevel; + } + } + return std::make_pair(DbgType.str(), Level); +} + // Even though LLVM might be built with NDEBUG, define symbols that the code // built without NDEBUG can depend on via the llvm/Support/Debug.h header. namespace llvm { /// Exported boolean set by the -debug option. bool DebugFlag = false; -static ManagedStatic<std::vector<std::string>> CurrentDebugType; +/// The current debug type and an optional debug level. +/// The debug level is the verbosity of the debug output. +/// 0 is a special level that acts as an opt-out for this specific debug type. +/// If provided, the debug output is enabled only if the user specified a level +/// at least as high as the provided level. +static ManagedStatic<std::vector<std::pair<std::string, std::optional<int>>>> + CurrentDebugType; /// Return true if the specified string is the debug type /// specified on the command line, or if none was specified on the command line /// with the -debug-only=X option. -bool isCurrentDebugType(const char *DebugType) { +bool isCurrentDebugType(const char *DebugType, int Level) { if (CurrentDebugType->empty()) return true; + // Track if there is at least one debug type with a level, this is used + // to allow to opt-out of some DebugType and leaving all the others enabled. + bool HasEnabledDebugType = false; // See if DebugType is in list. Note: do not use find() as that forces us to // unnecessarily create an std::string instance. - for (auto &d : *CurrentDebugType) { - if (d == DebugType) + for (auto &D : *CurrentDebugType) { + HasEnabledDebugType = + HasEnabledDebugType || (!D.second.has_value() || D.second.value() > 0); + if (D.first != DebugType) + continue; + if (!D.second.has_value()) return true; + return D.second >= Level; } - return false; + return !HasEnabledDebugType; } /// Set the current debug type, as if the -debug-only=X @@ -73,8 +110,11 @@ void setCurrentDebugType(const char *Type) { void setCurrentDebugTypes(const char **Types, unsigned Count) { CurrentDebugType->clear(); - llvm::append_range(*CurrentDebugType, ArrayRef(Types, Count)); + CurrentDebugType->reserve(Count); + for (const char *Type : ArrayRef(Types, Count)) + CurrentDebugType->push_back(parseDebugType(Type)); } + } // namespace llvm // All Debug.h functionality is a no-op in NDEBUG mode. @@ -114,10 +154,10 @@ struct DebugOnlyOpt { if (Val.empty()) return; DebugFlag = true; - SmallVector<StringRef,8> dbgTypes; - StringRef(Val).split(dbgTypes, ',', -1, false); - for (auto dbgType : dbgTypes) - CurrentDebugType->push_back(std::string(dbgType)); + SmallVector<StringRef, 8> DbgTypes; + StringRef(Val).split(DbgTypes, ',', -1, false); + for (auto DbgType : DbgTypes) + CurrentDebugType->push_back(parseDebugType(DbgType)); } }; } // namespace @@ -129,8 +169,13 @@ struct CreateDebugOnly { static void *call() { return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>( "debug-only", - cl::desc("Enable a specific type of debug output (comma separated list " - "of types)"), + cl::desc( + "Enable a specific type of debug output (comma separated list " + "of types using the format \"type[:level]\", where the level " + "is an optional integer. The level can be set to 1, 2, 3, etc. to " + "control the verbosity of the output. Setting a debug-type level " + "to zero acts as an opt-out for this specific debug-type without " + "affecting the others."), cl::Hidden, cl::value_desc("debug string"), cl::location(DebugOnlyOptLoc), cl::ValueRequired); } |