diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index f75a3a901ecd5..f6b8e44785b5f 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -39,14 +39,35 @@ void recordFixes(const VarDecl &Var, ASTContext &Context, } } +llvm::Optional firstLocAfterNewLine(SourceLocation Loc, + SourceManager &SM) { + bool Invalid; + const char *TextAfter = SM.getCharacterData(Loc, &Invalid); + if (Invalid) { + return llvm::None; + } + size_t Offset = std::strcspn(TextAfter, "\n"); + return Loc.getLocWithOffset(TextAfter[Offset] == '\0' ? Offset : Offset + 1); +} + void recordRemoval(const DeclStmt &Stmt, ASTContext &Context, DiagnosticBuilder &Diagnostic) { - // Attempt to remove the whole line until the next non-comment token. - auto Tok = utils::lexer::findNextTokenSkippingComments( - Stmt.getEndLoc(), Context.getSourceManager(), Context.getLangOpts()); - if (Tok) { - Diagnostic << FixItHint::CreateRemoval(SourceRange( - Stmt.getBeginLoc(), Tok->getLocation().getLocWithOffset(-1))); + auto &SM = Context.getSourceManager(); + // Attempt to remove trailing comments as well. + auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM, + Context.getLangOpts()); + llvm::Optional PastNewLine = + firstLocAfterNewLine(Stmt.getEndLoc(), SM); + if (Tok && PastNewLine) { + auto BeforeFirstTokenAfterComment = Tok->getLocation().getLocWithOffset(-1); + // Remove until the end of the line or the end of a trailing comment which + // ever comes first. + auto End = + SM.isBeforeInTranslationUnit(*PastNewLine, BeforeFirstTokenAfterComment) + ? *PastNewLine + : BeforeFirstTokenAfterComment; + Diagnostic << FixItHint::CreateRemoval( + SourceRange(Stmt.getBeginLoc(), End)); } else { Diagnostic << FixItHint::CreateRemoval(Stmt.getSourceRange()); } @@ -147,6 +168,7 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { return compoundStmt( forEachDescendant( declStmt( + unless(has(decompositionDecl())), has(varDecl(hasLocalStorage(), hasType(qualType( hasCanonicalType(allOf( diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 78a3851f66bef..0d35991d24799 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -40,6 +40,7 @@ add_clang_library(clangTidyReadabilityModule StaticAccessedThroughInstanceCheck.cpp StaticDefinitionInAnonymousNamespaceCheck.cpp StringCompareCheck.cpp + SuspiciousCallArgumentCheck.cpp UniqueptrDeleteReleaseCheck.cpp UppercaseLiteralSuffixCheck.cpp UseAnyOfAllOfCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 088b9f09082e0..a05b70826e669 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -43,6 +43,7 @@ #include "StaticAccessedThroughInstanceCheck.h" #include "StaticDefinitionInAnonymousNamespaceCheck.h" #include "StringCompareCheck.h" +#include "SuspiciousCallArgumentCheck.h" #include "UniqueptrDeleteReleaseCheck.h" #include "UppercaseLiteralSuffixCheck.h" #include "UseAnyOfAllOfCheck.h" @@ -122,6 +123,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-redundant-string-init"); CheckFactories.registerCheck( "readability-simplify-boolean-expr"); + CheckFactories.registerCheck( + "readability-suspicious-call-argument"); CheckFactories.registerCheck( "readability-uniqueptr-delete-release"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp new file mode 100644 index 0000000000000..557e95bc24073 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp @@ -0,0 +1,806 @@ +//===--- SuspiciousCallArgumentCheck.cpp - clang-tidy ---------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "SuspiciousCallArgumentCheck.h" +#include "../utils/OptionsUtils.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Type.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include + +using namespace clang::ast_matchers; +namespace optutils = clang::tidy::utils::options; + +namespace clang { +namespace tidy { +namespace readability { + +namespace { +struct DefaultHeuristicConfiguration { + /// Whether the heuristic is to be enabled by default. + const bool Enabled; + + /// The upper bound of % of similarity the two strings might have to be + /// considered dissimilar. + /// (For purposes of configuration, -1 if the heuristic is not configurable + /// with bounds.) + const int8_t DissimilarBelow; + + /// The lower bound of % of similarity the two string must have to be + /// considered similar. + /// (For purposes of configuration, -1 if the heuristic is not configurable + /// with bounds.) + const int8_t SimilarAbove; + + /// Can the heuristic be configured with bounds? + bool hasBounds() const { return DissimilarBelow > -1 && SimilarAbove > -1; } +}; +} // namespace + +static constexpr std::size_t DefaultMinimumIdentifierNameLength = 3; + +static constexpr StringRef HeuristicToString[] = { + "Equality", "Abbreviation", "Prefix", "Suffix", + "Substring", "Levenshtein", "JaroWinkler", "Dice"}; + +static constexpr DefaultHeuristicConfiguration Defaults[] = { + {true, -1, -1}, // Equality. + {true, -1, -1}, // Abbreviation. + {true, 25, 30}, // Prefix. + {true, 25, 30}, // Suffix. + {true, 40, 50}, // Substring. + {true, 50, 66}, // Levenshtein. + {true, 75, 85}, // Jaro-Winkler. + {true, 60, 70}, // Dice. +}; + +static_assert( + sizeof(HeuristicToString) / sizeof(HeuristicToString[0]) == + SuspiciousCallArgumentCheck::HeuristicCount, + "Ensure that every heuristic has a corresponding stringified name"); +static_assert(sizeof(Defaults) / sizeof(Defaults[0]) == + SuspiciousCallArgumentCheck::HeuristicCount, + "Ensure that every heuristic has a default configuration."); + +namespace { +template struct HasWellConfiguredBounds { + static constexpr bool Value = + !((Defaults[I].DissimilarBelow == -1) ^ (Defaults[I].SimilarAbove == -1)); + static_assert(Value, "A heuristic must either have a dissimilarity and " + "similarity bound, or neither!"); +}; + +template struct HasWellConfiguredBoundsFold { + static constexpr bool Value = HasWellConfiguredBounds::Value && + HasWellConfiguredBoundsFold::Value; +}; + +template <> struct HasWellConfiguredBoundsFold<0> { + static constexpr bool Value = HasWellConfiguredBounds<0>::Value; +}; + +struct AllHeuristicsBoundsWellConfigured { + static constexpr bool Value = + HasWellConfiguredBoundsFold::Value; +}; + +static_assert(AllHeuristicsBoundsWellConfigured::Value, ""); +} // namespace + +static const std::string DefaultAbbreviations = + optutils::serializeStringList({"addr=address", + "arr=array", + "attr=attribute", + "buf=buffer", + "cl=client", + "cnt=count", + "col=column", + "cpy=copy", + "dest=destination", + "dist=distance" + "dst=distance", + "elem=element", + "hght=height", + "i=index", + "idx=index", + "len=length", + "ln=line", + "lst=list", + "nr=number", + "num=number", + "pos=position", + "ptr=pointer", + "ref=reference", + "src=source", + "srv=server", + "stmt=statement", + "str=string", + "val=value", + "var=variable", + "vec=vector", + "wdth=width"}); + +static constexpr std::size_t SmallVectorSize = + SuspiciousCallArgumentCheck::SmallVectorSize; + +/// Returns how many % X is of Y. +static inline double percentage(double X, double Y) { return X / Y * 100.0; } + +static bool applyEqualityHeuristic(StringRef Arg, StringRef Param) { + return Arg.equals_insensitive(Param); +} + +static bool applyAbbreviationHeuristic( + const llvm::StringMap &AbbreviationDictionary, StringRef Arg, + StringRef Param) { + if (AbbreviationDictionary.find(Arg) != AbbreviationDictionary.end() && + Param.equals(AbbreviationDictionary.lookup(Arg))) + return true; + + if (AbbreviationDictionary.find(Param) != AbbreviationDictionary.end() && + Arg.equals(AbbreviationDictionary.lookup(Param))) + return true; + + return false; +} + +/// Check whether the shorter String is a prefix of the longer String. +static bool applyPrefixHeuristic(StringRef Arg, StringRef Param, + int8_t Threshold) { + StringRef Shorter = Arg.size() < Param.size() ? Arg : Param; + StringRef Longer = Arg.size() >= Param.size() ? Arg : Param; + + if (Longer.startswith_insensitive(Shorter)) + return percentage(Shorter.size(), Longer.size()) > Threshold; + + return false; +} + +/// Check whether the shorter String is a suffix of the longer String. +static bool applySuffixHeuristic(StringRef Arg, StringRef Param, + int8_t Threshold) { + StringRef Shorter = Arg.size() < Param.size() ? Arg : Param; + StringRef Longer = Arg.size() >= Param.size() ? Arg : Param; + + if (Longer.endswith_insensitive(Shorter)) + return percentage(Shorter.size(), Longer.size()) > Threshold; + + return false; +} + +static bool applySubstringHeuristic(StringRef Arg, StringRef Param, + int8_t Threshold) { + + std::size_t MaxLength = 0; + SmallVector Current(Param.size()); + SmallVector Previous(Param.size()); + std::string ArgLower = Arg.lower(); + std::string ParamLower = Param.lower(); + + for (std::size_t I = 0; I < Arg.size(); ++I) { + for (std::size_t J = 0; J < Param.size(); ++J) { + if (ArgLower[I] == ParamLower[J]) { + if (I == 0 || J == 0) + Current[J] = 1; + else + Current[J] = 1 + Previous[J - 1]; + + MaxLength = std::max(MaxLength, Current[J]); + } else + Current[J] = 0; + } + + Current.swap(Previous); + } + + size_t LongerLength = std::max(Arg.size(), Param.size()); + return percentage(MaxLength, LongerLength) > Threshold; +} + +static bool applyLevenshteinHeuristic(StringRef Arg, StringRef Param, + int8_t Threshold) { + std::size_t LongerLength = std::max(Arg.size(), Param.size()); + double Dist = Arg.edit_distance(Param); + Dist = (1.0 - Dist / LongerLength) * 100.0; + return Dist > Threshold; +} + +// Based on http://en.wikipedia.org/wiki/Jaro–Winkler_distance. +static bool applyJaroWinklerHeuristic(StringRef Arg, StringRef Param, + int8_t Threshold) { + std::size_t Match = 0, Transpos = 0; + std::ptrdiff_t ArgLen = Arg.size(); + std::ptrdiff_t ParamLen = Param.size(); + SmallVector ArgFlags(ArgLen); + SmallVector ParamFlags(ParamLen); + std::ptrdiff_t Range = + std::max(std::ptrdiff_t{0}, std::max(ArgLen, ParamLen) / 2 - 1); + + // Calculate matching characters. + for (std::ptrdiff_t I = 0; I < ParamLen; ++I) + for (std::ptrdiff_t J = std::max(I - Range, std::ptrdiff_t{0}), + L = std::min(I + Range + 1, ArgLen); + J < L; ++J) + if (tolower(Param[I]) == tolower(Arg[J]) && !ArgFlags[J]) { + ArgFlags[J] = 1; + ParamFlags[I] = 1; + ++Match; + break; + } + + if (!Match) + return false; + + // Calculate character transpositions. + std::ptrdiff_t L = 0; + for (std::ptrdiff_t I = 0; I < ParamLen; ++I) { + if (ParamFlags[I] == 1) { + std::ptrdiff_t J; + for (J = L; J < ArgLen; ++J) + if (ArgFlags[J] == 1) { + L = J + 1; + break; + } + + if (tolower(Param[I]) != tolower(Arg[J])) + ++Transpos; + } + } + Transpos /= 2; + + // Jaro distance. + double MatchD = Match; + double Dist = ((MatchD / ArgLen) + (MatchD / ParamLen) + + ((MatchD - Transpos) / Match)) / + 3.0; + + // Calculate common string prefix up to 4 chars. + L = 0; + for (std::ptrdiff_t I = 0; + I < std::min(std::min(ArgLen, ParamLen), std::ptrdiff_t{4}); ++I) + if (tolower(Arg[I]) == tolower(Param[I])) + ++L; + + // Jaro-Winkler distance. + Dist = (Dist + (L * 0.1 * (1.0 - Dist))) * 100.0; + return Dist > Threshold; +} + +// Based on http://en.wikipedia.org/wiki/Sørensen–Dice_coefficient +static bool applyDiceHeuristic(StringRef Arg, StringRef Param, + int8_t Threshold) { + llvm::StringSet<> ArgBigrams; + llvm::StringSet<> ParamBigrams; + + // Extract character bigrams from Arg. + for (std::ptrdiff_t I = 0; I < static_cast(Arg.size()) - 1; + ++I) + ArgBigrams.insert(Arg.substr(I, 2).lower()); + + // Extract character bigrams from Param. + for (std::ptrdiff_t I = 0; I < static_cast(Param.size()) - 1; + ++I) + ParamBigrams.insert(Param.substr(I, 2).lower()); + + std::size_t Intersection = 0; + + // Find the intersection between the two sets. + for (auto IT = ParamBigrams.begin(); IT != ParamBigrams.end(); ++IT) + Intersection += ArgBigrams.count((IT->getKey())); + + // Calculate Dice coefficient. + return percentage(Intersection * 2.0, + ArgBigrams.size() + ParamBigrams.size()) > Threshold; +} + +/// Checks if ArgType binds to ParamType regarding reference-ness and +/// cv-qualifiers. +static bool areRefAndQualCompatible(QualType ArgType, QualType ParamType) { + return !ParamType->isReferenceType() || + ParamType.getNonReferenceType().isAtLeastAsQualifiedAs( + ArgType.getNonReferenceType()); +} + +static bool isPointerOrArray(QualType TypeToCheck) { + return TypeToCheck->isPointerType() || TypeToCheck->isArrayType(); +} + +/// Checks whether ArgType is an array type identical to ParamType's array type. +/// Enforces array elements' qualifier compatibility as well. +static bool isCompatibleWithArrayReference(QualType ArgType, + QualType ParamType) { + if (!ArgType->isArrayType()) + return false; + // Here, qualifiers belong to the elements of the arrays. + if (!ParamType.isAtLeastAsQualifiedAs(ArgType)) + return false; + + return ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType(); +} + +static QualType convertToPointeeOrArrayElementQualType(QualType TypeToConvert) { + unsigned CVRqualifiers = 0; + // Save array element qualifiers, since getElementType() removes qualifiers + // from array elements. + if (TypeToConvert->isArrayType()) + CVRqualifiers = TypeToConvert.getLocalQualifiers().getCVRQualifiers(); + TypeToConvert = TypeToConvert->isPointerType() + ? TypeToConvert->getPointeeType() + : TypeToConvert->getAsArrayTypeUnsafe()->getElementType(); + TypeToConvert = TypeToConvert.withCVRQualifiers(CVRqualifiers); + return TypeToConvert; +} + +/// Checks if multilevel pointers' qualifiers compatibility continues on the +/// current pointer level. For multilevel pointers, C++ permits conversion, if +/// every cv-qualifier in ArgType also appears in the corresponding position in +/// ParamType, and if PramType has a cv-qualifier that's not in ArgType, then +/// every * in ParamType to the right of that cv-qualifier, except the last +/// one, must also be const-qualified. +static bool arePointersStillQualCompatible(QualType ArgType, QualType ParamType, + bool &IsParamContinuouslyConst) { + // The types are compatible, if the parameter is at least as qualified as the + // argument, and if it is more qualified, it has to be const on upper pointer + // levels. + bool AreTypesQualCompatible = + ParamType.isAtLeastAsQualifiedAs(ArgType) && + (!ParamType.hasQualifiers() || IsParamContinuouslyConst); + // Check whether the parameter's constness continues at the current pointer + // level. + IsParamContinuouslyConst &= ParamType.isConstQualified(); + + return AreTypesQualCompatible; +} + +/// Checks whether multilevel pointers are compatible in terms of levels, +/// qualifiers and pointee type. +static bool arePointerTypesCompatible(QualType ArgType, QualType ParamType, + bool IsParamContinuouslyConst) { + if (!arePointersStillQualCompatible(ArgType, ParamType, + IsParamContinuouslyConst)) + return false; + + do { + // Step down one pointer level. + ArgType = convertToPointeeOrArrayElementQualType(ArgType); + ParamType = convertToPointeeOrArrayElementQualType(ParamType); + + // Check whether cv-qualifiers permit compatibility on + // current level. + if (!arePointersStillQualCompatible(ArgType, ParamType, + IsParamContinuouslyConst)) + return false; + + if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType()) + return true; + + } while (ParamType->isPointerType() && ArgType->isPointerType()); + // The final type does not match, or pointer levels differ. + return false; +} + +/// Checks whether ArgType converts implicitly to ParamType. +static bool areTypesCompatible(QualType ArgType, QualType ParamType, + const ASTContext &Ctx) { + if (ArgType.isNull() || ParamType.isNull()) + return false; + + ArgType = ArgType.getCanonicalType(); + ParamType = ParamType.getCanonicalType(); + + if (ArgType == ParamType) + return true; + + // Check for constness and reference compatibility. + if (!areRefAndQualCompatible(ArgType, ParamType)) + return false; + + bool IsParamReference = ParamType->isReferenceType(); + + // Reference-ness has already been checked and should be removed + // before further checking. + ArgType = ArgType.getNonReferenceType(); + ParamType = ParamType.getNonReferenceType(); + + if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType()) + return true; + + // Arithmetic types are interconvertible, except scoped enums. + if (ParamType->isArithmeticType() && ArgType->isArithmeticType()) { + if ((ParamType->isEnumeralType() && + ParamType->getAs()->getDecl()->isScoped()) || + (ArgType->isEnumeralType() && + ArgType->getAs()->getDecl()->isScoped())) + return false; + + return true; + } + + // Check if the argument and the param are both function types (the parameter + // decayed to a function pointer). + if (ArgType->isFunctionType() && ParamType->isFunctionPointerType()) { + ParamType = ParamType->getPointeeType(); + return ArgType == ParamType; + } + + // Arrays or pointer arguments convert to array or pointer parameters. + if (!(isPointerOrArray(ArgType) && isPointerOrArray(ParamType))) + return false; + + // When ParamType is an array reference, ArgType has to be of the same-sized + // array-type with cv-compatible element type. + if (IsParamReference && ParamType->isArrayType()) + return isCompatibleWithArrayReference(ArgType, ParamType); + + bool IsParamContinuouslyConst = + !IsParamReference || ParamType.getNonReferenceType().isConstQualified(); + + // Remove the first level of indirection. + ArgType = convertToPointeeOrArrayElementQualType(ArgType); + ParamType = convertToPointeeOrArrayElementQualType(ParamType); + + // Check qualifier compatibility on the next level. + if (!ParamType.isAtLeastAsQualifiedAs(ArgType)) + return false; + + if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType()) + return true; + + // At this point, all possible C language implicit conversion were checked. + if (!Ctx.getLangOpts().CPlusPlus) + return false; + + // Check whether ParamType and ArgType were both pointers to a class or a + // struct, and check for inheritance. + if (ParamType->isStructureOrClassType() && + ArgType->isStructureOrClassType()) { + const auto *ArgDecl = ArgType->getAsCXXRecordDecl(); + const auto *ParamDecl = ParamType->getAsCXXRecordDecl(); + if (!ArgDecl || !ArgDecl->hasDefinition() || !ParamDecl || + !ParamDecl->hasDefinition()) + return false; + + return ArgDecl->isDerivedFrom(ParamDecl); + } + + // Unless argument and param are both multilevel pointers, the types are not + // convertible. + if (!(ParamType->isAnyPointerType() && ArgType->isAnyPointerType())) + return false; + + return arePointerTypesCompatible(ArgType, ParamType, + IsParamContinuouslyConst); +} + +static bool isOverloadedUnaryOrBinarySymbolOperator(const FunctionDecl *FD) { + switch (FD->getOverloadedOperator()) { + case OO_None: + case OO_Call: + case OO_Subscript: + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + case OO_Conditional: + case OO_Coawait: + return false; + + default: + return FD->getNumParams() <= 2; + } +} + +SuspiciousCallArgumentCheck::SuspiciousCallArgumentCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + MinimumIdentifierNameLength(Options.get( + "MinimumIdentifierNameLength", DefaultMinimumIdentifierNameLength)) { + auto GetToggleOpt = [this](Heuristic H) -> bool { + auto Idx = static_cast(H); + assert(Idx < HeuristicCount); + return Options.get(HeuristicToString[Idx], Defaults[Idx].Enabled); + }; + auto GetBoundOpt = [this](Heuristic H, BoundKind BK) -> int8_t { + auto Idx = static_cast(H); + assert(Idx < HeuristicCount); + + SmallString<32> Key = HeuristicToString[Idx]; + Key.append(BK == BoundKind::DissimilarBelow ? "DissimilarBelow" + : "SimilarAbove"); + int8_t Default = BK == BoundKind::DissimilarBelow + ? Defaults[Idx].DissimilarBelow + : Defaults[Idx].SimilarAbove; + return Options.get(Key, Default); + }; + for (std::size_t Idx = 0; Idx < HeuristicCount; ++Idx) { + auto H = static_cast(Idx); + if (GetToggleOpt(H)) + AppliedHeuristics.emplace_back(H); + ConfiguredBounds.emplace_back( + std::make_pair(GetBoundOpt(H, BoundKind::DissimilarBelow), + GetBoundOpt(H, BoundKind::SimilarAbove))); + } + + for (const std::string &Abbreviation : optutils::parseStringList( + Options.get("Abbreviations", DefaultAbbreviations))) { + auto KeyAndValue = StringRef{Abbreviation}.split("="); + assert(!KeyAndValue.first.empty() && !KeyAndValue.second.empty()); + AbbreviationDictionary.insert( + std::make_pair(KeyAndValue.first.str(), KeyAndValue.second.str())); + } +} + +void SuspiciousCallArgumentCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "MinimumIdentifierNameLength", + MinimumIdentifierNameLength); + const auto &SetToggleOpt = [this, &Opts](Heuristic H) -> void { + auto Idx = static_cast(H); + Options.store(Opts, HeuristicToString[Idx], isHeuristicEnabled(H)); + }; + const auto &SetBoundOpt = [this, &Opts](Heuristic H, BoundKind BK) -> void { + auto Idx = static_cast(H); + assert(Idx < HeuristicCount); + if (!Defaults[Idx].hasBounds()) + return; + + SmallString<32> Key = HeuristicToString[Idx]; + Key.append(BK == BoundKind::DissimilarBelow ? "DissimilarBelow" + : "SimilarAbove"); + Options.store(Opts, Key, getBound(H, BK).getValue()); + }; + + for (std::size_t Idx = 0; Idx < HeuristicCount; ++Idx) { + auto H = static_cast(Idx); + SetToggleOpt(H); + SetBoundOpt(H, BoundKind::DissimilarBelow); + SetBoundOpt(H, BoundKind::SimilarAbove); + } + + SmallVector Abbreviations; + for (const auto &Abbreviation : AbbreviationDictionary) { + SmallString<32> EqualSignJoined; + EqualSignJoined.append(Abbreviation.first()); + EqualSignJoined.append("="); + EqualSignJoined.append(Abbreviation.second); + + if (!Abbreviation.second.empty()) + Abbreviations.emplace_back(EqualSignJoined.str()); + } + Options.store(Opts, "Abbreviations", + optutils::serializeStringList(Abbreviations)); +} + +bool SuspiciousCallArgumentCheck::isHeuristicEnabled(Heuristic H) const { + return llvm::is_contained(AppliedHeuristics, H); +} + +Optional SuspiciousCallArgumentCheck::getBound(Heuristic H, + BoundKind BK) const { + auto Idx = static_cast(H); + assert(Idx < HeuristicCount); + + if (!Defaults[Idx].hasBounds()) + return None; + + switch (BK) { + case BoundKind::DissimilarBelow: + return ConfiguredBounds[Idx].first; + case BoundKind::SimilarAbove: + return ConfiguredBounds[Idx].second; + } + llvm_unreachable("Unhandled Bound kind."); +} + +void SuspiciousCallArgumentCheck::registerMatchers(MatchFinder *Finder) { + // Only match calls with at least 2 arguments. + Finder->addMatcher( + functionDecl(forEachDescendant(callExpr(unless(anyOf(argumentCountIs(0), + argumentCountIs(1)))) + .bind("functionCall"))) + .bind("callingFunc"), + this); +} + +void SuspiciousCallArgumentCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *MatchedCallExpr = + Result.Nodes.getNodeAs("functionCall"); + const auto *Caller = Result.Nodes.getNodeAs("callingFunc"); + assert(MatchedCallExpr && Caller); + + const Decl *CalleeDecl = MatchedCallExpr->getCalleeDecl(); + if (!CalleeDecl) + return; + + const FunctionDecl *CalleeFuncDecl = CalleeDecl->getAsFunction(); + if (!CalleeFuncDecl) + return; + if (CalleeFuncDecl == Caller) + // Ignore recursive calls. + return; + if (isOverloadedUnaryOrBinarySymbolOperator(CalleeFuncDecl)) + return; + + // Get param attributes. + setParamNamesAndTypes(CalleeFuncDecl); + + if (ParamNames.empty()) + return; + + // Get Arg attributes. + std::size_t InitialArgIndex = 0; + + if (const auto *MethodDecl = dyn_cast(CalleeFuncDecl)) { + if (MethodDecl->getParent()->isLambda()) + // Lambda functions' first Arg are the lambda object. + InitialArgIndex = 1; + else if (MethodDecl->getOverloadedOperator() == OO_Call) + // For custom operator()s, the first Arg is the called object. + InitialArgIndex = 1; + } + + setArgNamesAndTypes(MatchedCallExpr, InitialArgIndex); + + if (ArgNames.empty()) + return; + + std::size_t ParamCount = ParamNames.size(); + + // Check similarity. + for (std::size_t I = 0; I < ParamCount; ++I) { + for (std::size_t J = I + 1; J < ParamCount; ++J) { + // Do not check if param or arg names are short, or not convertible. + if (!areParamAndArgComparable(I, J, *Result.Context)) + continue; + if (!areArgsSwapped(I, J)) + continue; + + // Warning at the call itself. + diag(MatchedCallExpr->getExprLoc(), + "%ordinal0 argument '%1' (passed to '%2') looks like it might be " + "swapped with the %ordinal3, '%4' (passed to '%5')") + << static_cast(I + 1) << ArgNames[I] << ParamNames[I] + << static_cast(J + 1) << ArgNames[J] << ParamNames[J] + << MatchedCallExpr->getArg(I)->getSourceRange() + << MatchedCallExpr->getArg(J)->getSourceRange(); + + // Note at the functions declaration. + SourceLocation IParNameLoc = + CalleeFuncDecl->getParamDecl(I)->getLocation(); + SourceLocation JParNameLoc = + CalleeFuncDecl->getParamDecl(J)->getLocation(); + + diag(CalleeFuncDecl->getLocation(), "in the call to %0, declared here", + DiagnosticIDs::Note) + << CalleeFuncDecl + << CharSourceRange::getTokenRange(IParNameLoc, IParNameLoc) + << CharSourceRange::getTokenRange(JParNameLoc, JParNameLoc); + } + } +} + +void SuspiciousCallArgumentCheck::setParamNamesAndTypes( + const FunctionDecl *CalleeFuncDecl) { + // Reset vectors, and fill them with the currently checked function's + // parameters' data. + ParamNames.clear(); + ParamTypes.clear(); + + for (const ParmVarDecl *Param : CalleeFuncDecl->parameters()) { + ParamTypes.push_back(Param->getType()); + + if (IdentifierInfo *II = Param->getIdentifier()) + ParamNames.push_back(II->getName()); + else + ParamNames.push_back(StringRef()); + } +} + +void SuspiciousCallArgumentCheck::setArgNamesAndTypes( + const CallExpr *MatchedCallExpr, std::size_t InitialArgIndex) { + // Reset vectors, and fill them with the currently checked function's + // arguments' data. + ArgNames.clear(); + ArgTypes.clear(); + + for (std::size_t I = InitialArgIndex, J = MatchedCallExpr->getNumArgs(); + I < J; ++I) { + if (const auto *ArgExpr = dyn_cast( + MatchedCallExpr->getArg(I)->IgnoreUnlessSpelledInSource())) { + if (const auto *Var = dyn_cast(ArgExpr->getDecl())) { + ArgTypes.push_back(Var->getType()); + ArgNames.push_back(Var->getName()); + } else if (const auto *FCall = + dyn_cast(ArgExpr->getDecl())) { + ArgTypes.push_back(FCall->getType()); + ArgNames.push_back(FCall->getName()); + } else { + ArgTypes.push_back(QualType()); + ArgNames.push_back(StringRef()); + } + } else { + ArgTypes.push_back(QualType()); + ArgNames.push_back(StringRef()); + } + } +} + +bool SuspiciousCallArgumentCheck::areParamAndArgComparable( + std::size_t Position1, std::size_t Position2, const ASTContext &Ctx) const { + if (Position1 >= ArgNames.size() || Position2 >= ArgNames.size()) + return false; + + // Do not report for too short strings. + if (ArgNames[Position1].size() < MinimumIdentifierNameLength || + ArgNames[Position2].size() < MinimumIdentifierNameLength || + ParamNames[Position1].size() < MinimumIdentifierNameLength || + ParamNames[Position2].size() < MinimumIdentifierNameLength) + return false; + + if (!areTypesCompatible(ArgTypes[Position1], ParamTypes[Position2], Ctx) || + !areTypesCompatible(ArgTypes[Position2], ParamTypes[Position1], Ctx)) + return false; + + return true; +} + +bool SuspiciousCallArgumentCheck::areArgsSwapped(std::size_t Position1, + std::size_t Position2) const { + for (Heuristic H : AppliedHeuristics) { + bool A1ToP2Similar = areNamesSimilar( + ArgNames[Position2], ParamNames[Position1], H, BoundKind::SimilarAbove); + bool A2ToP1Similar = areNamesSimilar( + ArgNames[Position1], ParamNames[Position2], H, BoundKind::SimilarAbove); + + bool A1ToP1Dissimilar = + !areNamesSimilar(ArgNames[Position1], ParamNames[Position1], H, + BoundKind::DissimilarBelow); + bool A2ToP2Dissimilar = + !areNamesSimilar(ArgNames[Position2], ParamNames[Position2], H, + BoundKind::DissimilarBelow); + + if ((A1ToP2Similar || A2ToP1Similar) && A1ToP1Dissimilar && + A2ToP2Dissimilar) + return true; + } + return false; +} + +bool SuspiciousCallArgumentCheck::areNamesSimilar(StringRef Arg, + StringRef Param, Heuristic H, + BoundKind BK) const { + int8_t Threshold = -1; + if (Optional GotBound = getBound(H, BK)) + Threshold = GotBound.getValue(); + + switch (H) { + case Heuristic::Equality: + return applyEqualityHeuristic(Arg, Param); + case Heuristic::Abbreviation: + return applyAbbreviationHeuristic(AbbreviationDictionary, Arg, Param); + case Heuristic::Prefix: + return applyPrefixHeuristic(Arg, Param, Threshold); + case Heuristic::Suffix: + return applySuffixHeuristic(Arg, Param, Threshold); + case Heuristic::Substring: + return applySubstringHeuristic(Arg, Param, Threshold); + case Heuristic::Levenshtein: + return applyLevenshteinHeuristic(Arg, Param, Threshold); + case Heuristic::JaroWinkler: + return applyJaroWinklerHeuristic(Arg, Param, Threshold); + case Heuristic::Dice: + return applyDiceHeuristic(Arg, Param, Threshold); + } + llvm_unreachable("Unhandled heuristic kind"); +} + +} // namespace readability +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.h b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.h new file mode 100644 index 0000000000000..3f4e011132cb7 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.h @@ -0,0 +1,100 @@ +//===--- SuspiciousCallArgumentCheck.h - clang-tidy -------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SUSPICIOUSCALLARGUMENTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SUSPICIOUSCALLARGUMENTCHECK_H + +#include "../ClangTidyCheck.h" +#include "llvm/ADT/StringSet.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Finds function calls where the arguments passed are provided out of order, +/// based on the difference between the argument name and the parameter names +/// of the function. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-suspicious-call-argument.html +class SuspiciousCallArgumentCheck : public ClangTidyCheck { + enum class Heuristic { + Equality, + Abbreviation, + Prefix, + Suffix, + Substring, + Levenshtein, + JaroWinkler, + Dice + }; + + /// When applying a heuristic, the value of this enum decides which kind of + /// bound will be selected from the bounds configured for the heuristic. + /// This only applies to heuristics that can take bounds. + enum class BoundKind { + /// Check for dissimilarity of the names. Names are deemed dissimilar if + /// the similarity measurement is **below** the configured threshold. + DissimilarBelow, + + /// Check for similarity of the names. Names are deemed similar if the + /// similarity measurement (the result of heuristic) is **above** the + /// configured threshold. + SimilarAbove + }; + +public: + static constexpr std::size_t SmallVectorSize = 8; + static constexpr std::size_t HeuristicCount = + static_cast(Heuristic::Dice) + 1; + + SuspiciousCallArgumentCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + const std::size_t MinimumIdentifierNameLength; + + /// The configuration for which heuristics were enabled. + SmallVector AppliedHeuristics; + + /// The lower and upper bounds for each heuristic, as configured by the user. + SmallVector, HeuristicCount> ConfiguredBounds; + + /// The abbreviation-to-abbreviated map for the Abbreviation heuristic. + llvm::StringMap AbbreviationDictionary; + + bool isHeuristicEnabled(Heuristic H) const; + Optional getBound(Heuristic H, BoundKind BK) const; + + // Runtime information of the currently analyzed function call. + SmallVector ArgTypes; + SmallVector ArgNames; + SmallVector ParamTypes; + SmallVector ParamNames; + + void setParamNamesAndTypes(const FunctionDecl *CalleeFuncDecl); + + void setArgNamesAndTypes(const CallExpr *MatchedCallExpr, + std::size_t InitialArgIndex); + + bool areParamAndArgComparable(std::size_t Position1, std::size_t Position2, + const ASTContext &Ctx) const; + + bool areArgsSwapped(std::size_t Position1, std::size_t Position2) const; + + bool areNamesSimilar(StringRef Arg, StringRef Param, Heuristic H, + BoundKind BK) const; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SUSPICIOUSCALLARGUMENTCHECK_H diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py index de810230b2852..acd1ed6979c0d 100755 --- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py +++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py @@ -173,6 +173,9 @@ def run_tidy(args, tmpdir, build_path, queue, lock, failed_files): proc = subprocess.Popen(invocation, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = proc.communicate() if proc.returncode != 0: + if proc.returncode < 0: + msg = "%s: terminated by signal %d\n" % (name, -proc.returncode) + err += msg.encode('utf-8') failed_files.append(name) with lock: sys.stdout.write(' '.join(invocation) + '\n' + output.decode('utf-8')) diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index 3c2b097e89fd1..5aee128c9d6b5 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -19,12 +19,15 @@ if (NOT DEFINED CLANGD_BUILD_XPC) endif () option(CLANGD_MALLOC_TRIM "Call malloc_trim(3) periodically in Clangd. (only takes effect when using glibc)" ON) +# -DCLANG_TIDY_CHECKS=Off avoids a dependency on clang-tidy, reducing rebuilds. +option(CLANGD_TIDY_CHECKS "Link all clang-tidy checks into clangd" ON) llvm_canonicalize_cmake_booleans( CLANGD_BUILD_XPC CLANGD_ENABLE_REMOTE ENABLE_GRPC_REFLECTION CLANGD_MALLOC_TRIM + CLANGD_TIDY_CHECKS LLVM_ENABLE_ZLIB ) @@ -162,10 +165,12 @@ target_link_libraries(clangDaemon ${LLVM_PTHREAD_LIB} clangTidy - ${ALL_CLANG_TIDY_CHECKS} clangdSupport ) +if(CLANGD_TIDY_CHECKS) + target_link_libraries(clangDaemon PRIVATE ${ALL_CLANG_TIDY_CHECKS}) +endif() add_subdirectory(refactor/tweaks) if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") diff --git a/clang-tools-extra/clangd/Features.cpp b/clang-tools-extra/clangd/Features.cpp index 17f475fc4c22b..4ec03ea84bfb4 100644 --- a/clang-tools-extra/clangd/Features.cpp +++ b/clang-tools-extra/clangd/Features.cpp @@ -48,6 +48,10 @@ std::string featureString() { #if CLANGD_BUILD_XPC "+xpc" #endif + +#if !CLANGD_TIDY_CHECKS + "-tidy" +#endif ; } diff --git a/clang-tools-extra/clangd/Features.inc.in b/clang-tools-extra/clangd/Features.inc.in index 72464d89b830e..b6c3729b0bb8d 100644 --- a/clang-tools-extra/clangd/Features.inc.in +++ b/clang-tools-extra/clangd/Features.inc.in @@ -3,3 +3,4 @@ #define CLANGD_ENABLE_REMOTE @CLANGD_ENABLE_REMOTE@ #define ENABLE_GRPC_REFLECTION @ENABLE_GRPC_REFLECTION@ #define CLANGD_MALLOC_TRIM @CLANGD_MALLOC_TRIM@ +#define CLANGD_TIDY_CHECKS @CLANGD_TIDY_CHECKS@ diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index cb8ad5a8fa9ff..2520062eed9b5 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -15,6 +15,7 @@ #include "Config.h" #include "Diagnostics.h" #include "FeatureModule.h" +#include "Features.h" #include "Headers.h" #include "HeuristicResolver.h" #include "IncludeFixer.h" @@ -60,8 +61,10 @@ // Force the linker to link in Clang-tidy modules. // clangd doesn't support the static analyzer. +#if CLANGD_TIDY_CHECKS #define CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS #include "../clang-tidy/ClangTidyForceLinker.h" +#endif namespace clang { namespace clangd { diff --git a/clang-tools-extra/clangd/ParsedAST.h b/clang-tools-extra/clangd/ParsedAST.h index 703ae38254284..9bb4796645866 100644 --- a/clang-tools-extra/clangd/ParsedAST.h +++ b/clang-tools-extra/clangd/ParsedAST.h @@ -13,7 +13,7 @@ // we have several customizations: // - preamble handling // - capturing diagnostics for later access -// - running clang-tidy checks checks +// - running clang-tidy checks // //===----------------------------------------------------------------------===// diff --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp index 49f16e72be92a..581dae7557295 100644 --- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp +++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp @@ -91,7 +91,7 @@ class Command { // By resetting the parser options, we lost the standard -help flag. llvm::cl::opt> Help{ "help", llvm::cl::desc("Display available options"), - llvm::cl::ValueDisallowed, llvm::cl::cat(llvm::cl::GeneralCategory)}; + llvm::cl::ValueDisallowed, llvm::cl::cat(llvm::cl::getGeneralCategory())}; // FIXME: Allow commands to signal failure. virtual void run() = 0; diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp b/clang-tools-extra/clangd/indexer/IndexerMain.cpp index fd8404be677a2..533334fcc1f28 100644 --- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp +++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp @@ -124,7 +124,7 @@ int main(int argc, const char **argv) { )"; auto Executor = clang::tooling::createExecutorFromCommandLineArgs( - argc, argv, llvm::cl::GeneralCategory, Overview); + argc, argv, llvm::cl::getGeneralCategory(), Overview); if (!Executor) { llvm::errs() << llvm::toString(Executor.takeError()) << "\n"; diff --git a/clang-tools-extra/clangd/test/diagnostics.test b/clang-tools-extra/clangd/test/diagnostics-tidy.test similarity index 69% rename from clang-tools-extra/clangd/test/diagnostics.test rename to clang-tools-extra/clangd/test/diagnostics-tidy.test index 588fefdbf2e06..1d10541be8bf0 100644 --- a/clang-tools-extra/clangd/test/diagnostics.test +++ b/clang-tools-extra/clangd/test/diagnostics-tidy.test @@ -1,27 +1,12 @@ +# REQUIRES: clangd-tidy-checks # RUN: clangd -lit-test -clang-tidy-checks=bugprone-sizeof-expression < %s | FileCheck -strict-whitespace %s {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} --- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","text":"void main() {\n(void)sizeof(42);\n}"}}} +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.c","languageId":"c","text":"int main() {\n(void)sizeof(42);\n}"}}} # CHECK: "method": "textDocument/publishDiagnostics", # CHECK-NEXT: "params": { # CHECK-NEXT: "diagnostics": [ # CHECK-NEXT: { -# CHECK-NEXT: "code": "-Wmain-return-type", -# CHECK-NEXT: "message": "Return type of 'main' is not 'int' (fix available)", -# CHECK-NEXT: "range": { -# CHECK-NEXT: "end": { -# CHECK-NEXT: "character": 4, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: }, -# CHECK-NEXT: "start": { -# CHECK-NEXT: "character": 0, -# CHECK-NEXT: "line": 0 -# CHECK-NEXT: } -# CHECK-NEXT: }, -# CHECK-NEXT: "severity": 2, -# CHECK-NEXT: "source": "clang" -# CHECK-NEXT: }, -# CHECK-NEXT: { # CHECK-NEXT: "code": "bugprone-sizeof-expression", # CHECK-NEXT: "message": "Suspicious usage of 'sizeof(K)'; did you mean 'K'?", # CHECK-NEXT: "range": { @@ -54,3 +39,4 @@ {"jsonrpc":"2.0","id":5,"method":"shutdown"} --- {"jsonrpc":"2.0","method":"exit"} + diff --git a/clang-tools-extra/clangd/test/lit.cfg.py b/clang-tools-extra/clangd/test/lit.cfg.py index 2680eb441df98..0f3d8b310b290 100644 --- a/clang-tools-extra/clangd/test/lit.cfg.py +++ b/clang-tools-extra/clangd/test/lit.cfg.py @@ -31,5 +31,8 @@ def calculate_arch_features(arch_string): if config.clangd_enable_remote: config.available_features.add('clangd-remote-index') +if config.clangd_tidy_checks: + config.available_features.add('clangd-tidy-checks') + if config.have_zlib: config.available_features.add('zlib') diff --git a/clang-tools-extra/clangd/test/lit.site.cfg.py.in b/clang-tools-extra/clangd/test/lit.site.cfg.py.in index efcc770095b36..853a3bf24a072 100644 --- a/clang-tools-extra/clangd/test/lit.site.cfg.py.in +++ b/clang-tools-extra/clangd/test/lit.site.cfg.py.in @@ -25,6 +25,7 @@ config.clangd_source_dir = "@CMAKE_CURRENT_SOURCE_DIR@/.." config.clangd_binary_dir = "@CMAKE_CURRENT_BINARY_DIR@/.." config.clangd_build_xpc = @CLANGD_BUILD_XPC@ config.clangd_enable_remote = @CLANGD_ENABLE_REMOTE@ +config.clangd_tidy_checks = @CLANGD_TIDY_CHECKS@ config.have_zlib = @LLVM_ENABLE_ZLIB@ # Delegate logic to lit.cfg.py. diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index 93b85d8c0b5dc..eab28bb7fa0e5 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -288,16 +288,26 @@ TEST_F(ConfigCompileTests, Tidy) { Tidy.CheckOptions.emplace_back(std::make_pair( std::string("example-check.ExampleOption"), std::string("0"))); EXPECT_TRUE(compileAndApply()); - EXPECT_EQ( - Conf.Diagnostics.ClangTidy.Checks, - "bugprone-use-after-move,llvm-*,-llvm-include-order,-readability-*"); EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.size(), 2U); EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup("StrictMode"), "true"); EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup( "example-check.ExampleOption"), "0"); +#if CLANGD_TIDY_CHECKS + EXPECT_EQ( + Conf.Diagnostics.ClangTidy.Checks, + "bugprone-use-after-move,llvm-*,-llvm-include-order,-readability-*"); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); +#else // !CLANGD_TIDY_CHECKS + EXPECT_EQ(Conf.Diagnostics.ClangTidy.Checks, "llvm-*,-readability-*"); + EXPECT_THAT( + Diags.Diagnostics, + ElementsAre( + DiagMessage( + "clang-tidy check 'bugprone-use-after-move' was not found"), + DiagMessage("clang-tidy check 'llvm-include-order' was not found"))); +#endif } TEST_F(ConfigCompileTests, TidyBadChecks) { diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 87f3c8737d464..1b04257df0579 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -10,6 +10,7 @@ #include "Config.h" #include "Diagnostics.h" #include "FeatureModule.h" +#include "Features.h" #include "ParsedAST.h" #include "Protocol.h" #include "SourceCode.h" @@ -114,6 +115,18 @@ Position pos(int line, int character) { return Res; } +// Normally returns the provided diagnostics matcher. +// If clang-tidy checks are not linked in, returns a matcher for no diagnostics! +// This is intended for tests where the diagnostics come from clang-tidy checks. +// We don't #ifdef each individual test as it's intrusive and we want to ensure +// that as much of the test is still compiled an run as possible. +::testing::Matcher> +ifTidyChecks(::testing::Matcher> M) { + if (!CLANGD_TIDY_CHECKS) + return IsEmpty(); + return M; +} + TEST(DiagnosticsTest, DiagnosticRanges) { // Check we report correct ranges, including various edge-cases. Annotations Test(R"cpp( @@ -121,8 +134,11 @@ TEST(DiagnosticsTest, DiagnosticRanges) { #define ID(X) X namespace test{}; void $decl[[foo]](); - class T{$explicit[[]]$constructor[[T]](int a);}; int main() { + struct Container { int* begin(); int* end(); } *container; + for (auto i : $insertstar[[]]$range[[container]]) { + } + $typo[[go\ o]](); foo()$semicolon[[]]//with comments @@ -135,10 +151,14 @@ o]](); } )cpp"); auto TU = TestTU::withCode(Test.code()); - TU.ClangTidyProvider = addTidyChecks("google-explicit-constructor"); EXPECT_THAT( *TU.build().getDiagnostics(), ElementsAre( + // Make sure the whole token is highlighted. + AllOf(Diag(Test.range("range"), + "invalid range expression of type 'struct Container *'; " + "did you mean to dereference it with '*'?"), + WithFix(Fix(Test.range("insertstar"), "*", "insert '*'"))), // This range spans lines. AllOf(Diag(Test.range("typo"), "use of undeclared identifier 'goo'; did you mean 'foo'?"), @@ -163,13 +183,7 @@ o]](); AllOf(Diag(Test.range("macro"), "use of undeclared identifier 'fod'; did you mean 'foo'?"), WithFix(Fix(Test.range("macroarg"), "foo", - "change 'fod' to 'foo'"))), - // We make sure here that the entire token is highlighted - AllOf(Diag(Test.range("constructor"), - "single-argument constructors must be marked explicit to " - "avoid unintentional implicit conversions"), - WithFix(Fix(Test.range("explicit"), "explicit ", - "insert 'explicit '"))))); + "change 'fod' to 'foo'"))))); } TEST(DiagnosticsTest, FlagsMatter) { @@ -212,10 +226,10 @@ TEST(DiagnosticsTest, DeduplicatedClangTidyDiagnostics) { // Verify that we filter out the duplicated diagnostic message. EXPECT_THAT( *TU.build().getDiagnostics(), - UnorderedElementsAre(::testing::AllOf( + ifTidyChecks(UnorderedElementsAre(::testing::AllOf( Diag(Test.range(), "floating point literal has suffix 'f', which is not uppercase"), - DiagSource(Diag::ClangTidy)))); + DiagSource(Diag::ClangTidy))))); Test = Annotations(R"cpp( template @@ -232,10 +246,10 @@ TEST(DiagnosticsTest, DeduplicatedClangTidyDiagnostics) { // duplicated messages, verify that we deduplicate them. EXPECT_THAT( *TU.build().getDiagnostics(), - UnorderedElementsAre(::testing::AllOf( + ifTidyChecks(UnorderedElementsAre(::testing::AllOf( Diag(Test.range(), "floating point literal has suffix 'f', which is not uppercase"), - DiagSource(Diag::ClangTidy)))); + DiagSource(Diag::ClangTidy))))); } TEST(DiagnosticsTest, ClangTidy) { @@ -265,9 +279,10 @@ TEST(DiagnosticsTest, ClangTidy) { "modernize-deprecated-headers," "modernize-use-trailing-return-type," "misc-no-recursion"); + TU.ExtraArgs.push_back("-Wno-unsequenced"); EXPECT_THAT( *TU.build().getDiagnostics(), - UnorderedElementsAre( + ifTidyChecks(UnorderedElementsAre( AllOf(Diag(Test.range("deprecated"), "inclusion of deprecated C++ header 'assert.h'; consider " "using 'cassert' instead"), @@ -277,28 +292,25 @@ TEST(DiagnosticsTest, ClangTidy) { "change '\"assert.h\"' to ''"))), Diag(Test.range("doubled"), "suspicious usage of 'sizeof(sizeof(...))'"), - AllOf( - Diag(Test.range("macroarg"), - "side effects in the 1st macro argument 'X' are repeated in " - "macro expansion"), - DiagSource(Diag::ClangTidy), - DiagName("bugprone-macro-repeated-side-effects"), - WithNote( - Diag(Test.range("macrodef"), "macro 'SQUARE' defined here"))), - Diag(Test.range("macroarg"), - "multiple unsequenced modifications to 'y'"), - AllOf( - Diag(Test.range("main"), - "use a trailing return type for this function"), - DiagSource(Diag::ClangTidy), - DiagName("modernize-use-trailing-return-type"), - // Verify that we don't have "[check-name]" suffix in the message. - WithFix( - FixMessage("use a trailing return type for this function"))), + AllOf(Diag(Test.range("macroarg"), + "side effects in the 1st macro argument 'X' are " + "repeated in " + "macro expansion"), + DiagSource(Diag::ClangTidy), + DiagName("bugprone-macro-repeated-side-effects"), + WithNote(Diag(Test.range("macrodef"), + "macro 'SQUARE' defined here"))), + AllOf(Diag(Test.range("main"), + "use a trailing return type for this function"), + DiagSource(Diag::ClangTidy), + DiagName("modernize-use-trailing-return-type"), + // Verify there's no "[check-name]" suffix in the message. + WithFix(FixMessage( + "use a trailing return type for this function"))), Diag(Test.range("foo"), "function 'foo' is within a recursive call chain"), Diag(Test.range("bar"), - "function 'bar' is within a recursive call chain"))); + "function 'bar' is within a recursive call chain")))); } TEST(DiagnosticsTest, ClangTidyEOF) { @@ -313,9 +325,9 @@ TEST(DiagnosticsTest, ClangTidyEOF) { TU.ClangTidyProvider = addTidyChecks("llvm-include-order"); EXPECT_THAT( *TU.build().getDiagnostics(), - Contains(AllOf(Diag(Test.range(), "#includes are not sorted properly"), - DiagSource(Diag::ClangTidy), - DiagName("llvm-include-order")))); + ifTidyChecks(Contains( + AllOf(Diag(Test.range(), "#includes are not sorted properly"), + DiagSource(Diag::ClangTidy), DiagName("llvm-include-order"))))); } TEST(DiagnosticTest, TemplatesInHeaders) { @@ -385,9 +397,9 @@ TEST(DiagnosticTest, NoMultipleDiagnosticInFlight) { TU.ClangTidyProvider = addTidyChecks("modernize-loop-convert"); EXPECT_THAT( *TU.build().getDiagnostics(), - UnorderedElementsAre(::testing::AllOf( + ifTidyChecks(UnorderedElementsAre(::testing::AllOf( Diag(Main.range(), "use range-based for loop instead"), - DiagSource(Diag::ClangTidy), DiagName("modernize-loop-convert")))); + DiagSource(Diag::ClangTidy), DiagName("modernize-loop-convert"))))); } TEST(DiagnosticTest, RespectsDiagnosticConfig) { @@ -430,10 +442,11 @@ TEST(DiagnosticTest, ClangTidySuppressionComment) { TU.ClangTidyProvider = addTidyChecks("bugprone-integer-division"); EXPECT_THAT( *TU.build().getDiagnostics(), - UnorderedElementsAre(::testing::AllOf( + ifTidyChecks(UnorderedElementsAre(::testing::AllOf( Diag(Main.range(), "result of integer division used in a floating " "point context; possible loss of precision"), - DiagSource(Diag::ClangTidy), DiagName("bugprone-integer-division")))); + DiagSource(Diag::ClangTidy), + DiagName("bugprone-integer-division"))))); } TEST(DiagnosticTest, ClangTidyWarningAsError) { @@ -448,11 +461,11 @@ TEST(DiagnosticTest, ClangTidyWarningAsError) { addTidyChecks("bugprone-integer-division", "bugprone-integer-division"); EXPECT_THAT( *TU.build().getDiagnostics(), - UnorderedElementsAre(::testing::AllOf( + ifTidyChecks(UnorderedElementsAre(::testing::AllOf( Diag(Main.range(), "result of integer division used in a floating " "point context; possible loss of precision"), DiagSource(Diag::ClangTidy), DiagName("bugprone-integer-division"), - DiagSeverity(DiagnosticsEngine::Error)))); + DiagSeverity(DiagnosticsEngine::Error))))); } TEST(DiagnosticTest, LongFixMessages) { @@ -528,9 +541,9 @@ TEST(DiagnosticTest, ElseAfterReturnRange) { )cpp"); TestTU TU = TestTU::withCode(Main.code()); TU.ClangTidyProvider = addTidyChecks("llvm-else-after-return"); - EXPECT_THAT( - *TU.build().getDiagnostics(), - ElementsAre(Diag(Main.range(), "do not use 'else' after 'return'"))); + EXPECT_THAT(*TU.build().getDiagnostics(), + ifTidyChecks(ElementsAre( + Diag(Main.range(), "do not use 'else' after 'return'")))); } TEST(DiagnosticsTest, Preprocessor) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index e9b186a81b391..b4d325cb553d6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -126,6 +126,13 @@ New checks Finds calls to ``new`` with missing exception handler for ``std::bad_alloc``. +- New `readability-suspicious-call-argument + `_ check + + Finds function calls where the arguments passed are provided out of order, + based on the difference between the argument name and the parameter names + of the function. + New check aliases ^^^^^^^^^^^^^^^^^ @@ -134,6 +141,7 @@ New check aliases :doc:`concurrency-thread-canceltype-asynchronous ` was added. + Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 83ec376c401f0..ebc99ca8f0eec 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -313,6 +313,7 @@ Clang-Tidy Checks `readability-static-accessed-through-instance `_, "Yes" `readability-static-definition-in-anonymous-namespace `_, "Yes" `readability-string-compare `_, "Yes" + `readability-suspicious-call-argument `_, `readability-uniqueptr-delete-release `_, "Yes" `readability-uppercase-literal-suffix `_, "Yes" `readability-use-anyofallof `_, diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-suspicious-call-argument.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-suspicious-call-argument.rst new file mode 100644 index 0000000000000..a1e0f25834f34 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-suspicious-call-argument.rst @@ -0,0 +1,242 @@ +.. title:: clang-tidy - readability-suspicious-call-argument + +readability-suspicious-call-argument +==================================== + +Finds function calls where the arguments passed are provided out of order, +based on the difference between the argument name and the parameter names +of the function. + +Given a function call ``f(foo, bar);`` and a function signature +``void f(T tvar, U uvar)``, the arguments ``foo`` and ``bar`` are swapped if +``foo`` (the argument name) is more similar to ``uvar`` (the other parameter) +than ``tvar`` (the parameter it is currently passed to) **and** ``bar`` is +more similar to ``tvar`` than ``uvar``. + +Warnings might indicate either that the arguments are swapped, or that the +names' cross-similarity might hinder code comprehension. + +.. _heuristics: + +Heuristics +---------- + +The following heuristics are implemented in the check. +If **any** of the enabled heuristics deem the arguments to be provided out of +order, a warning will be issued. + +The heuristics themselves are implemented by considering pairs of strings, and +are symmetric, so in the following there is no distinction on which string is +the argument name and which string is the parameter name. + +Equality +^^^^^^^^ + +The most trivial heuristic, which compares the two strings for case-insensitive +equality. + +.. _abbreviation_heuristic: + +Abbreviation +^^^^^^^^^^^^ + +Common abbreviations can be specified which will deem the strings similar if +the abbreviated and the abbreviation stand together. +For example, if ``src`` is registered as an abbreviation for ``source``, then +the following code example will be warned about. + +.. code-block:: c++ + + void foo(int source, int x); + + foo(b, src); + +The abbreviations to recognise can be configured with the +:ref:`Abbreviations` check option. +This heuristic is case-insensitive. + +Prefix +^^^^^^ + +The *prefix* heuristic reports if one of the strings is a sufficiently long +prefix of the other string, e.g. ``target`` to ``targetPtr``. +The similarity percentage is the length ratio of the prefix to the longer +string, in the previous example, it would be `6 / 9 = 66.66...`\%. + +This heuristic can be configured with :ref:`bounds`. +The default bounds are: below `25`\% dissimilar and above `30`\% similar. +This heuristic is case-insensitive. + +Suffix +^^^^^^ + +Analogous to the `Prefix` heuristic. +In the case of ``oldValue`` and ``value`` compared, the similarity percentage +is `8 / 5 = 62.5`\%. + +This heuristic can be configured with :ref:`bounds`. +The default bounds are: below `25`\% dissimilar and above `30`\% similar. +This heuristic is case-insensitive. + +Substring +^^^^^^^^^ + +The substring heuristic combines the prefix and the suffix heuristic, and tries +to find the *longest common substring* in the two strings provided. +The similarity percentage is the ratio of the found longest common substring +against the *longer* of the two input strings. +For example, given ``val`` and ``rvalue``, the similarity is `3 / 6 = 50`\%. +If no characters are common in the two string, `0`\%. + +This heuristic can be configured with :ref:`bounds`. +The default bounds are: below `40`\% dissimilar and above `50`\% similar. +This heuristic is case-insensitive. + +Levenshtein distance (as `Levenshtein`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `Levenshtein distance `_ +describes how many single-character changes (additions, changes, or removals) +must be applied to transform one string into another. + +The Levenshtein distance is translated into a similarity percentage by dividing +it with the length of the *longer* string, and taking its complement with +regards to `100`\%. +For example, given ``something`` and ``anything``, the distance is `4` edits, +and the similarity percentage is `100`\% `- 4 / 9 = 55.55...`\%. + +This heuristic can be configured with :ref:`bounds`. +The default bounds are: below `50`\% dissimilar and above `66`\% similar. +This heuristic is case-sensitive. + +Jaro–Winkler distance (as `JaroWinkler`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `Jaro–Winkler distance `_ +is an edit distance like the Levenshtein distance. +It is calculated from the amount of common characters that are sufficiently +close to each other in position, and to-be-changed characters. +The original definition of Jaro has been extended by Winkler to weigh prefix +similarities more. +The similarity percentage is expressed as an average of the common and +non-common characters against the length of both strings. + +This heuristic can be configured with :ref:`bounds`. +The default bounds are: below `75`\% dissimilar and above `85`\% similar. +This heuristic is case-insensitive. + +Sørensen–Dice coefficient (as `Dice`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `Sørensen–Dice coefficient `_ +was originally defined to measure the similarity of two sets. +Formally, the coefficient is calculated by dividing `2 * #(intersection)` with +`#(set1) + #(set2)`, where `#()` is the cardinality function of sets. +This metric is applied to strings by creating bigrams (substring sequences of +length 2) of the two strings and using the set of bigrams for the two strings +as the two sets. + +This heuristic can be configured with :ref:`bounds`. +The default bounds are: below `60`\% dissimilar and above `70`\% similar. +This heuristic is case-insensitive. + + +Options +------- + +.. option:: MinimumIdentifierNameLength + + Sets the minimum required length the argument and parameter names + need to have. Names shorter than this length will be ignored. + Defaults to `3`. + +.. _opt_Abbreviations: + +.. option:: Abbreviations + + For the **Abbreviation** heuristic + (:ref:`see here`), this option configures the + abbreviations in the `"abbreviation=abbreviated_value"` format. + The option is a string, with each value joined by `";"`. + + By default, the following abbreviations are set: + + * `addr=address` + * `arr=array` + * `attr=attribute` + * `buf=buffer` + * `cl=client` + * `cnt=count` + * `col=column` + * `cpy=copy` + * `dest=destination` + * `dist=distance` + * `dst=distance` + * `elem=element` + * `hght=height` + * `i=index` + * `idx=index` + * `len=length` + * `ln=line` + * `lst=list` + * `nr=number` + * `num=number` + * `pos=position` + * `ptr=pointer` + * `ref=reference` + * `src=source` + * `srv=server` + * `stmt=statement` + * `str=string` + * `val=value` + * `var=variable` + * `vec=vector` + * `wdth=width` + +The configuration options for each implemented heuristic (see above) is +constructed dynamically. +In the following, `` refers to one of the keys from the +heuristics implemented. + +.. option:: + + `True` or `False`, whether a particular heuristic, such as `Equality` or + `Levenshtein` is enabled. + + Defaults to `True` for every heuristic. + +.. _opt_Bounds: + +.. option:: DissimilarBelow, SimilarAbove + + A value between `0` and `100`, expressing a percentage. + The bounds set what percentage of similarity the heuristic must deduce + for the two identifiers to be considered similar or dissimilar by the + check. + + Given arguments ``arg1`` and ``arg2`` passed to ``param1`` and ``param2``, + respectively, the bounds check is performed in the following way: + If the similarity of the currently passed argument order + (``arg1`` to ``param1``) is **below** the `DissimilarBelow` threshold, and + the similarity of the suggested swapped order (``arg1`` to ``param2``) is + **above** the `SimilarAbove` threshold, the swap is reported. + + For the defaults of each heuristic, :ref:`see above`. + + +Name synthesis +-------------- + +When comparing the argument names and parameter names, the following logic is +used to gather the names for comparison: + +Parameter names are the identifiers as written in the source code. + +Argument names are: + + * If a variable is passed, the variable's name. + * If a subsequent function call's return value is used as argument, the called + function's name. + * Otherwise, empty string. + +Empty argument or parameter names are ignored by the heuristics. diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp index c2b3d8f9c7395..3ce151035d5be 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t +// RUN: %check_clang_tidy -std=c++17 %s performance-unnecessary-copy-initialization %t template struct Iterator { @@ -596,8 +596,15 @@ void positiveUnusedReferenceIsRemoved() { // CHECK-FIXES: int i = 0; // Foo bar. auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment. // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'TrailingCommentRemoved' is copy-constructed from a const reference but is never used; - // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment. + // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference(); + // CHECK-FIXES-NOT: // Trailing comment. // clang-format on + + auto UnusedAndUnnecessary = ExpensiveTypeReference(); + // Comments on a new line should not be deleted. + // CHECK-MESSAGES: [[@LINE-2]]:8: warning: the variable 'UnusedAndUnnecessary' is copy-constructed + // CHECK-FIXES-NOT: auto UnusedAndUnnecessary = ExpensiveTypeReference(); + // CHECK-FIXES: // Comments on a new line should not be deleted. } void negativeloopedOverObjectIsModified() { @@ -637,3 +644,18 @@ void negativeReferenceIsInitializedOutsideOfBlock() { } }; } + +void negativeStructuredBinding() { + // Structured bindings are not yet supported but can trigger false positives + // since the DecompositionDecl itself is unused and the check doesn't traverse + // VarDecls of the BindingDecls. + struct Pair { + ExpensiveToCopyType first; + ExpensiveToCopyType second; + }; + + Pair P; + const auto [C, D] = P; + C.constMethod(); + D.constMethod(); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-suspicious-call-argument.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-suspicious-call-argument.cpp new file mode 100644 index 0000000000000..2597ee3b9e030 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-suspicious-call-argument.cpp @@ -0,0 +1,487 @@ +// RUN: %check_clang_tidy %s readability-suspicious-call-argument %t -- -- -std=c++11 + +void foo_1(int aaaaaa, int bbbbbb) {} + +void foo_2(int source, int aaaaaa) {} + +void foo_3(int valToRet, int aaaaaa) {} + +void foo_4(int pointer, int aaaaaa) {} + +void foo_5(int aaaaaa, int bbbbbb, int cccccc, ...) {} + +void foo_6(const int dddddd, bool &eeeeee) {} + +void foo_7(int aaaaaa, int bbbbbb, int cccccc, int ffffff = 7) {} + +void foo_8(int frobble1, int frobble2) {} + +// Test functions for convertible argument--parameter types. +void fun(const int &m); +void fun2() { + int m = 3; + fun(m); +} + +// Test cases for parameters of const reference and value. +void value_const_reference(int llllll, const int &kkkkkk); + +void const_ref_value_swapped() { + const int &kkkkkk = 42; + const int &llllll = 42; + value_const_reference(kkkkkk, llllll); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'kkkkkk' (passed to 'llllll') looks like it might be swapped with the 2nd, 'llllll' (passed to 'kkkkkk') [readability-suspicious-call-argument] + // CHECK-MESSAGES: :[[@LINE-7]]:6: note: in the call to 'value_const_reference', declared here +} + +// Const, non const references. +void const_nonconst_parameters(const int &mmmmmm, int &nnnnnn); + +void const_nonconst_swap1() { + const int &nnnnnn = 42; + int mmmmmm; + // Do not check, because non-const reference parameter cannot bind to const reference argument. + const_nonconst_parameters(nnnnnn, mmmmmm); +} + +void const_nonconst_swap3() { + const int nnnnnn = 42; + int m = 42; + int &mmmmmm = m; + // Do not check, const int does not bind to non const reference. + const_nonconst_parameters(nnnnnn, mmmmmm); +} + +void const_nonconst_swap2() { + int nnnnnn; + int mmmmmm; + // Check for swapped arguments. (Both arguments are non-const.) + const_nonconst_parameters(nnnnnn, mmmmmm); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'nnnnnn' (passed to 'mmmmmm') looks like it might be swapped with the 2nd, 'mmmmmm' (passed to 'nnnnnn') +} + +void const_nonconst_pointers(const int *mmmmmm, int *nnnnnn); +void const_nonconst_pointers2(const int *mmmmmm, const int *nnnnnn); + +void const_nonconst_pointers_swapped() { + int *mmmmmm; + const int *nnnnnn; + const_nonconst_pointers(nnnnnn, mmmmmm); +} + +void const_nonconst_pointers_swapped2() { + const int *mmmmmm; + int *nnnnnn; + const_nonconst_pointers2(nnnnnn, mmmmmm); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'nnnnnn' (passed to 'mmmmmm') looks like it might be swapped with the 2nd, 'mmmmmm' (passed to 'nnnnnn') +} + +// Test cases for pointers and arrays. +void pointer_array_parameters( + int *pppppp, int qqqqqq[4]); + +void pointer_array_swap() { + int qqqqqq[5]; + int *pppppp; + // Check for swapped arguments. An array implicitly converts to a pointer. + pointer_array_parameters(qqqqqq, pppppp); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'qqqqqq' (passed to 'pppppp') looks like it might be swapped with the 2nd, 'pppppp' (passed to 'qqqqqq') +} + +// Test cases for multilevel pointers. +void multilevel_pointer_parameters(int *const **pppppp, + const int *const *volatile const *qqqqqq); +void multilevel_pointer_parameters2( + char *****nnnnnn, char *volatile *const *const *const *const &mmmmmm); + +typedef float T; +typedef T *S; +typedef S *const volatile R; +typedef R *Q; +typedef Q *P; +typedef P *O; +void multilevel_pointer_parameters3(float **const volatile ***rrrrrr, O &ssssss); + +void multilevel_pointer_swap() { + int *const **qqqqqq; + int *const **pppppp; + multilevel_pointer_parameters(qqqqqq, pppppp); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'qqqqqq' (passed to 'pppppp') looks like it might be swapped with the 2nd, 'pppppp' (passed to 'qqqqqq') + + char *****mmmmmm; + char *****nnnnnn; + multilevel_pointer_parameters2(mmmmmm, nnnnnn); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'mmmmmm' (passed to 'nnnnnn') looks like it might be swapped with the 2nd, 'nnnnnn' (passed to 'mmmmmm') + + float **const volatile ***rrrrrr; + float **const volatile ***ssssss; + multilevel_pointer_parameters3(ssssss, rrrrrr); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'ssssss' (passed to 'rrrrrr') looks like it might be swapped with the 2nd, 'rrrrrr' (passed to 'ssssss') +} + +void multilevel_pointer_parameters4(char ****pppppp, + char *const volatile **const *qqqqqq); +void multilevel_pointer_parameters5( + bool *****nnnnnn, bool *volatile *const *const *const *&mmmmmm); +void multilevel_pointer_parameters6(double **llllll, char **&kkkkkk); +void multilevel_pointer_parameters7(const volatile int ***iiiiii, + const int *const *const *jjjjjj); + +void multilevel_pointer_swap3() { + char ****qqqqqq; + char *const volatile **const *pppppp; + // Do not check. + multilevel_pointer_parameters4(qqqqqq, pppppp); + + bool *****mmmmmm; + bool *volatile *const *const *const *nnnnnn; + // Do not check. + multilevel_pointer_parameters5(mmmmmm, nnnnnn); + + double **kkkkkk; + char **llllll; + multilevel_pointer_parameters6(kkkkkk, llllll); + + const volatile int ***jjjjjj; + const int *const *const *iiiiii; + multilevel_pointer_parameters7(jjjjjj, iiiiii); +} + +// Test cases for multidimesional arrays. +void multilevel_array_parameters(int pppppp[2][2][2], const int qqqqqq[][2][2]); + +void multilevel_array_parameters2(int (*mmmmmm)[2][2], int nnnnnn[9][2][23]); + +void multilevel_array_parameters3(int (*eeeeee)[2][2], int (&ffffff)[1][2][2]); + +void multilevel_array_parameters4(int (*llllll)[2][2], int kkkkkk[2][2]); + +void multilevel_array_parameters5(int iiiiii[2][2], char jjjjjj[2][2]); + +void multilevel_array_parameters6(int (*bbbbbb)[2][2], int cccccc[1][2][2]); + +void multilevel_array_swap() { + int qqqqqq[1][2][2]; + int pppppp[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; // int [2][2][2] + multilevel_array_parameters(qqqqqq, pppppp); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'qqqqqq' (passed to 'pppppp') looks like it might be swapped with the 2nd, 'pppppp' (passed to 'qqqqqq') + + int(*nnnnnn)[2][2]; + int mmmmmm[9][2][23]; + // Do not check, array sizes has to match in every dimension, except the first. + multilevel_array_parameters2(nnnnnn, mmmmmm); + + int ffffff[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; // int [2][2][2] + int eeeeee[1][2][2] = {{{1, 2}, {1, 2}}}; // int [1][2][2] + // Do not check, for array references, size has to match in every dimension. + multilevel_array_parameters3(ffffff, eeeeee); + + int kkkkkk[2][2][2]; + int(*llllll)[2]; + // Do not check, argument dimensions differ. + multilevel_array_parameters4(kkkkkk, llllll); + + int jjjjjj[2][2]; + char iiiiii[2][2]; + // Do not check, array element types differ. + multilevel_array_parameters5(jjjjjj, iiiiii); + + int t[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; // int [2][2][2] + int(*cccccc)[2][2] = t; // int (*)[2][2] + int bbbbbb[][2][2] = {{{1, 2}, {1, 2}}}; // int [1][2][2] + multilevel_array_parameters6(cccccc, bbbbbb); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'bbbbbb') looks like it might be swapped with the 2nd, 'bbbbbb' (passed to 'cccccc') +} + +void multilevel_array_swap2() { + int qqqqqq[2][2][2]; + const int pppppp[][2][2] = {{{1, 2}, {1, 2}}, {{1, 2}, {1, 2}}}; + // Do not check, pppppp is const and cannot bind to an array with nonconst elements. + multilevel_array_parameters(qqqqqq, pppppp); +} + +// Complex test case. +void multilevel_pointer_array_parameters(const int(*const (*volatile const (*const (*const (*const &aaaaaa)[1])[32])[4])[3][2][2]), const int(*const (*volatile const (*const (*const (*&bbbbbb)[1])[32])[4])[3][2][2])); + +void multilevel_pointer_array_swap() { + const int( + *const(*volatile const(*const(*const(*aaaaaa)[1])[32])[4])[3][2][2]); + const int( + *const(*volatile const(*const(*const(*bbbbbb)[1])[32])[4])[3][2][2]); + multilevel_pointer_array_parameters(bbbbbb, aaaaaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'bbbbbb' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb') +} + +enum class numbers_scoped { one, + two }; + +// Test cases for arithmetic types. +void arithmetic_type_parameters(float vvvvvv, int wwwwww); +void arithmetic_type_parameters2(numbers_scoped vvvvvv, int wwwwww); + +void arithmetic_types_swap1() { + bool wwwwww; + float vvvvvv; + arithmetic_type_parameters(wwwwww, vvvvvv); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww') +} + +void arithmetic_types_swap3() { + char wwwwww; + unsigned long long int vvvvvv; + arithmetic_type_parameters(wwwwww, vvvvvv); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww') +} + +void arithmetic_types_swap4() { + enum numbers { one, + two }; + numbers wwwwww = numbers::one; + int vvvvvv; + arithmetic_type_parameters(wwwwww, vvvvvv); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww') +} + +void arithmetic_types_swap5() { + wchar_t vvvvvv; + float wwwwww; + arithmetic_type_parameters(wwwwww, vvvvvv); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'wwwwww' (passed to 'vvvvvv') looks like it might be swapped with the 2nd, 'vvvvvv' (passed to 'wwwwww') +} + +void arithmetic_types_swap6() { + wchar_t vvvvvv; + numbers_scoped wwwwww = numbers_scoped::one; + // Do not check, numers is a scoped enum type. + arithmetic_type_parameters2(wwwwww, vvvvvv); +} + +// Base, derived +class TestClass { +public: + void thisFunction(int integerParam, int thisIsPARAM) {} +}; + +class DerivedTestClass : public TestClass {}; + +void base_derived_pointer_parameters(TestClass *aaaaaa, + DerivedTestClass *bbbbbb); + +void base_derived_swap1() { + TestClass *bbbbbb; + DerivedTestClass *aaaaaa; + // Do not check, because TestClass does not convert implicitly to DerivedTestClass. + base_derived_pointer_parameters(bbbbbb, aaaaaa); +} + +void base_derived_swap2() { + DerivedTestClass *bbbbbb, *aaaaaa; + // Check for swapped arguments, DerivedTestClass converts to TestClass implicitly. + base_derived_pointer_parameters(bbbbbb, aaaaaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'bbbbbb' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb') +} + +class PrivateDerivedClass : private TestClass {}; + +void private_derived_pointer_parameters(TestClass *aaaaaa, PrivateDerivedClass *bbbbbb); + +void private_base_swap1() { + TestClass *bbbbbb; + PrivateDerivedClass *aaaaaa; + private_derived_pointer_parameters(bbbbbb, aaaaaa); +} + +// Multilevel inheritance +class DerivedOfDerivedTestClass : public DerivedTestClass {}; + +void multi_level_inheritance_swap() { + DerivedOfDerivedTestClass *aaaaaa, *bbbbbb; + // Check for swapped arguments. Derived classes implicitly convert to their base. + base_derived_pointer_parameters( + bbbbbb, aaaaaa); + // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: 1st argument 'bbbbbb' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb') +} + +// Tests for function pointer swaps +void funct_ptr_params(double (*ffffff)(int, int), double (*gggggg)(int, int)); +void funct_ptr_params(double (*ffffff)(int, int), int (*gggggg)(int, int)); + +double ffffff(int a, int b) { return 0; } +double gggggg(int a, int b) { return 0; } + +void funtionc_ptr_params_swap() { + funct_ptr_params(gggggg, ffffff); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'gggggg' (passed to 'ffffff') looks like it might be swapped with the 2nd, 'ffffff' (passed to 'gggggg') +} + +int fffff(int a, int b) { return 0; } + +void function_ptr_swap2() { + // Do not check, because the function `ffffff` cannot convert to a function + // with prototype: double(int,int). + funct_ptr_params(gggggg, fffff); +} + +// Paraphrased example from Z3 (src/qe/qe_arrays.cpp) which originally produced +// a false positive. Operator() calls should ignore the called object +// "argument". +struct type1; +struct type2; +struct type3; + +struct callable1 { + void operator()(type1 &mdl, type2 &arr_vars, type3 &fml, type2 &aux_vars) const {} +}; + +struct callable2 { + void operator()(type1 &mdl, type2 &arr_vars, type3 &fml, type2 &aux_vars, + bool reduce_all_selects) const { + (void)reduce_all_selects; + callable1 pe; + pe(mdl, arr_vars, fml, aux_vars); + // NO-WARN: Argument and parameter names match perfectly, "pe" should be + // ignored! + } +}; + +struct binop_t {}; + +binop_t operator+(const binop_t &lhs, const binop_t &rhs) { return lhs; } +bool operator<(const binop_t &lhs, const binop_t &rhs) { return true; } +bool operator>(const binop_t &aaaaaa, const binop_t &bbbbbb) { return false; } + +void binop_test() { + // NO-WARN: Binary operators are ignored. + binop_t lhs, rhs; + if (lhs + rhs < rhs) + return; + + if (operator<(rhs, lhs)) + return; + + binop_t aaaaaa, cccccc; + if (operator>(cccccc, aaaaaa)) + return; +} + +int recursion(int aaaa, int bbbb) { + if (aaaa) + return 0; + + int cccc = 0; + return recursion(bbbb, cccc); + // NO-WARN: Recursive calls usually shuffle with arguments and we ignore those. +} + +void pass_by_copy(binop_t xxxx, binop_t yyyy) {} + +// Paraphrased example from LLVM's code (lib/Analysis/InstructionSimplify.cpp) +// that generated a false positive. +struct value; +enum opcode { Foo, + Bar }; +static value *SimplifyRightShift( + opcode Opcode, value *Op0, value *Op1, bool isExact, + const type1 &Q, unsigned MaxRecurse) {} +static value *SimplifyLShrInst(value *Op0, value *Op1, bool isExact, + const type1 &Q, unsigned MaxRecurse) { + if (value *V = SimplifyRightShift(Foo, Op0, Op1, isExact, Q, MaxRecurse)) + return V; + // NO-WARN: Argument names perfectly match parameter names, sans the enum. + + return nullptr; +} + +void has_unnamed(int aaaaaa, int) {} + +int main() { + // Equality test. + int aaaaaa, cccccc = 0; + foo_1(cccccc, aaaaaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb') + + binop_t xxxx, yyyy; + pass_by_copy(yyyy, xxxx); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'yyyy' (passed to 'xxxx') looks like it might be swapped with the 2nd, 'xxxx' (passed to 'yyyy') + + // Abbreviation test. + int src = 0; + foo_2(aaaaaa, src); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'aaaaaa' (passed to 'source') looks like it might be swapped with the 2nd, 'src' (passed to 'aaaaaa') + + // Levenshtein test. + int aaaabb = 0; + foo_1(cccccc, aaaabb); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaabb' (passed to 'bbbbbb') + + // Prefix test. + int aaaa = 0; + foo_1(cccccc, aaaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaa' (passed to 'bbbbbb') + + // Suffix test. + int urce = 0; + foo_2(cccccc, urce); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'source') looks like it might be swapped with the 2nd, 'urce' (passed to 'aaaaaa') + + // Substring test. + int ourc = 0; + foo_2(cccccc, ourc); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'source') looks like it might be swapped with the 2nd, 'ourc' (passed to 'aaaaaa') + + // Jaro-Winkler test. + int iPonter = 0; + foo_4(cccccc, iPonter); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'pointer') looks like it might be swapped with the 2nd, 'iPonter' (passed to 'aaaaaa') + + // Dice test. + int aaabaa = 0; + foo_1(cccccc, aaabaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaabaa' (passed to 'bbbbbb') + + // Variadic function test. + int bbbbbb = 0; + foo_5(src, bbbbbb, cccccc, aaaaaa); // Should pass. + foo_5(cccccc, bbbbbb, aaaaaa, src); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 3rd, 'aaaaaa' (passed to 'cccccc') + + // Test function with default argument. + foo_7(src, bbbbbb, cccccc, aaaaaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'src' (passed to 'aaaaaa') looks like it might be swapped with the 4th, 'aaaaaa' (passed to 'ffffff') + + foo_7(cccccc, bbbbbb, aaaaaa, src); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'cccccc' (passed to 'aaaaaa') looks like it might be swapped with the 3rd, 'aaaaaa' (passed to 'cccccc') + + int ffffff = 0; + foo_7(ffffff, bbbbbb, cccccc); // NO-WARN: Even though 'ffffff' is passed to 'aaaaaa' and there is a 4th parameter 'ffffff', there isn't a **swap** here. + + int frobble1 = 1, frobble2 = 2; + foo_8(frobble2, frobble1); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'frobble2' (passed to 'frobble1') looks like it might be swapped with the 2nd, 'frobble1' (passed to 'frobble2') + + int bar1 = 1, bar2 = 2; + foo_8(bar2, bar1); // NO-WARN. + + // Type match + bool dddddd = false; + int eeeeee = 0; + auto szam = 0; + foo_6(eeeeee, dddddd); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'eeeeee' (passed to 'dddddd') looks like it might be swapped with the 2nd, 'dddddd' (passed to 'eeeeee') + foo_1(szam, aaaaaa); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 1st argument 'szam' (passed to 'aaaaaa') looks like it might be swapped with the 2nd, 'aaaaaa' (passed to 'bbbbbb') + + // Test lambda. + auto testMethod = [&](int method, int randomParam) { return 0; }; + int method = 0; + testMethod(method, 0); // Should pass. + + // Member function test. + TestClass test; + int integ, thisIsAnArg = 0; + test.thisFunction(integ, thisIsAnArg); // Should pass. + + has_unnamed(1, bbbbbb); + + return 0; +} diff --git a/clang/docs/AddressSanitizer.rst b/clang/docs/AddressSanitizer.rst index 14f3938496c30..7befbc3173da8 100644 --- a/clang/docs/AddressSanitizer.rst +++ b/clang/docs/AddressSanitizer.rst @@ -276,6 +276,18 @@ library name in the symbolized stack trace of the leak report. See `_ for more details. +Code generation control +======================= + +Instrumentation code outlining +------------------------------ + +By default AddressSanitizer inlines the instumentation code to improve the +run-time performance, which leads to increased binary size. Using the +(clang flag ``-fsanitize-address-outline-instrumentation` default: ``false``) +flag forces all code instumentation to be outlined, which reduces the size +of the generated code, but also reduces the run-time performace. + Limitations =========== diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 2efbafae62fda..68a813177d2ce 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -3455,6 +3455,9 @@ to the same code size limit as with ``unroll(enable)``. Unrolling of a loop can be prevented by specifying ``unroll(disable)``. +Loop unroll parameters can be controlled by options +`-mllvm -unroll-count=n` and `-mllvm -pragma-unroll-threshold=n`. + Loop Distribution ----------------- diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 73309fb081f96..9999565f7f261 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -7701,7 +7701,7 @@

AST Traversal Matchers

While varDecl(hasInitializer(integerLiteral())) varDecl(hasInitializer(declRefExpr())) -only match the declarations for b, c, and d. +only match the declarations for a. diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index 3bd1a0c211486..88d3107c21e7a 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -268,7 +268,7 @@ want to help with the implementation. +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | atomic extension | 'fail' clause on atomic construct | :none:`unclaimed` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| base language | C++ attribute specifier syntax | :part:`worked on` | | +| base language | C++ attribute specifier syntax | :good:`done` | D105648 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | device extension | 'present' map type modifier | :good:`done` | D83061, D83062, D84422 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 57d53415c5807..f7f76ed3f3e20 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1649,6 +1649,14 @@ are listed below. Enable simple code coverage in addition to certain sanitizers. See :doc:`SanitizerCoverage` for more details. +**-f[no-]sanitize-address-outline-instrumentation** + + Controls how address sanitizer code is generated. If enabled will always use + a function call instead of inlining the code. Turning this option on could + reduce the binary size, but might result in a worse run-time performance. + + See :doc: `AddressSanitizer` for more details. + **-f[no-]sanitize-stats** Enable simple statistics gathering for the enabled sanitizers. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index f2c8d5ac7cd9e..6c22ea1e91fe2 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -459,6 +459,7 @@ class ASTContext : public RefCountedBase { friend class ASTWriter; template friend class serialization::AbstractTypeReader; friend class CXXRecordDecl; + friend class IncrementalParser; /// A mapping to contain the template or declaration that /// a variable declaration describes or was instantiated from, @@ -567,7 +568,7 @@ class ASTContext : public RefCountedBase { ImportDecl *FirstLocalImport = nullptr; ImportDecl *LastLocalImport = nullptr; - TranslationUnitDecl *TUDecl; + TranslationUnitDecl *TUDecl = nullptr; mutable ExternCContextDecl *ExternCContext = nullptr; mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr; mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr; @@ -624,6 +625,7 @@ class ASTContext : public RefCountedBase { IdentifierTable &Idents; SelectorTable &Selectors; Builtin::Context &BuiltinInfo; + const TranslationUnitKind TUKind; mutable DeclarationNameTable DeclarationNames; IntrusiveRefCntPtr ExternalSource; ASTMutationListener *Listener = nullptr; @@ -1022,7 +1024,18 @@ class ASTContext : public RefCountedBase { /// Get the initializations to perform when importing a module, if any. ArrayRef getModuleInitializers(Module *M); - TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } + TranslationUnitDecl *getTranslationUnitDecl() const { + return TUDecl->getMostRecentDecl(); + } + void addTranslationUnitDecl() { + assert(!TUDecl || TUKind == TU_Incremental); + TranslationUnitDecl *NewTUDecl = TranslationUnitDecl::Create(*this); + if (TraversalScope.empty() || TraversalScope.back() == TUDecl) + TraversalScope = {NewTUDecl}; + if (TUDecl) + NewTUDecl->setPreviousDecl(TUDecl); + TUDecl = NewTUDecl; + } ExternCContextDecl *getExternCContextDecl() const; BuiltinTemplateDecl *getMakeIntegerSeqDecl() const; @@ -1104,7 +1117,8 @@ class ASTContext : public RefCountedBase { llvm::DenseSet CUDADeviceVarODRUsedByHost; ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, - SelectorTable &sels, Builtin::Context &builtins); + SelectorTable &sels, Builtin::Context &builtins, + TranslationUnitKind TUKind); ASTContext(const ASTContext &) = delete; ASTContext &operator=(const ASTContext &) = delete; ~ASTContext(); diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 567104b2b0624..904860d838bd5 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -79,7 +79,23 @@ class UnresolvedSetImpl; class VarTemplateDecl; /// The top declaration context. -class TranslationUnitDecl : public Decl, public DeclContext { +class TranslationUnitDecl : public Decl, + public DeclContext, + public Redeclarable { + using redeclarable_base = Redeclarable; + + TranslationUnitDecl *getNextRedeclarationImpl() override { + return getNextRedeclaration(); + } + + TranslationUnitDecl *getPreviousDeclImpl() override { + return getPreviousDecl(); + } + + TranslationUnitDecl *getMostRecentDeclImpl() override { + return getMostRecentDecl(); + } + ASTContext &Ctx; /// The (most recently entered) anonymous namespace for this @@ -91,6 +107,16 @@ class TranslationUnitDecl : public Decl, public DeclContext { virtual void anchor(); public: + using redecl_range = redeclarable_base::redecl_range; + using redecl_iterator = redeclarable_base::redecl_iterator; + + using redeclarable_base::getMostRecentDecl; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::isFirstDecl; + using redeclarable_base::redecls; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + ASTContext &getASTContext() const { return Ctx; } NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } diff --git a/clang/include/clang/AST/Redeclarable.h b/clang/include/clang/AST/Redeclarable.h index 87252337a0f4b..77b827c52bfb3 100644 --- a/clang/include/clang/AST/Redeclarable.h +++ b/clang/include/clang/AST/Redeclarable.h @@ -193,6 +193,7 @@ class Redeclarable { public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend class IncrementalParser; Redeclarable(const ASTContext &Ctx) : RedeclLink(LatestDeclLink(Ctx)), diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index a13827df4405a..8e3ee6cb9e7e7 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -913,7 +913,7 @@ AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher, /// varDecl(hasInitializer(integerLiteral())) /// varDecl(hasInitializer(declRefExpr())) /// \endcode -/// only match the declarations for b, c, and d. +/// only match the declarations for a. AST_MATCHER_P(Expr, ignoringImpCasts, internal::Matcher, InnerMatcher) { return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder); diff --git a/clang/include/clang/Basic/BuiltinsNVPTX.def b/clang/include/clang/Basic/BuiltinsNVPTX.def index 1ac5c8e646118..adba236751d21 100644 --- a/clang/include/clang/Basic/BuiltinsNVPTX.def +++ b/clang/include/clang/Basic/BuiltinsNVPTX.def @@ -727,6 +727,7 @@ TARGET_BUILTIN(__hmma_m8n32k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX TARGET_BUILTIN(__bmma_m8n8k128_ld_a_b1, "vi*iC*UiIi", "", AND(SM_75,PTX63)) TARGET_BUILTIN(__bmma_m8n8k128_ld_b_b1, "vi*iC*UiIi", "", AND(SM_75,PTX63)) TARGET_BUILTIN(__bmma_m8n8k128_ld_c, "vi*iC*UiIi", "", AND(SM_75,PTX63)) +TARGET_BUILTIN(__bmma_m8n8k128_mma_and_popc_b1, "vi*iC*iC*iC*Ii", "", AND(SM_75,PTX71)) TARGET_BUILTIN(__bmma_m8n8k128_mma_xor_popc_b1, "vi*iC*iC*iC*Ii", "", AND(SM_75,PTX63)) TARGET_BUILTIN(__bmma_m8n8k128_st_c_i32, "vi*iC*UiIi", "", AND(SM_75,PTX63)) TARGET_BUILTIN(__imma_m16n16k16_ld_a_s8, "vi*iC*UiIi", "", AND(SM_72,PTX63)) diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index baaf5db9d1453..1c83c59e16233 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -29,8 +29,10 @@ #define UNALIASED_CUSTOM_BUILTIN(ID, TYPES, ACCUMULATE) \ CUSTOM_BUILTIN(ID, ID, TYPES, ACCUMULATE) -// builtins for compatibility with the XL compiler +// XL Compatibility built-ins BUILTIN(__builtin_ppc_popcntb, "ULiULi", "") +BUILTIN(__builtin_ppc_poppar4, "iUi", "") +BUILTIN(__builtin_ppc_poppar8, "iULLi", "") BUILTIN(__builtin_ppc_eieio, "v", "") BUILTIN(__builtin_ppc_iospace_eieio, "v", "") BUILTIN(__builtin_ppc_isync, "v", "") @@ -59,6 +61,57 @@ BUILTIN(__builtin_ppc_ldarx, "LiLiD*", "") BUILTIN(__builtin_ppc_lwarx, "iiD*", "") BUILTIN(__builtin_ppc_stdcx, "iLiD*Li", "") BUILTIN(__builtin_ppc_stwcx, "iiD*i", "") +BUILTIN(__builtin_ppc_tdw, "vLLiLLiIUi", "") +BUILTIN(__builtin_ppc_tw, "viiIUi", "") +BUILTIN(__builtin_ppc_trap, "vi", "") +BUILTIN(__builtin_ppc_trapd, "vLi", "") +BUILTIN(__builtin_ppc_fcfid, "dd", "") +BUILTIN(__builtin_ppc_fcfud, "dd", "") +BUILTIN(__builtin_ppc_fctid, "dd", "") +BUILTIN(__builtin_ppc_fctidz, "dd", "") +BUILTIN(__builtin_ppc_fctiw, "dd", "") +BUILTIN(__builtin_ppc_fctiwz, "dd", "") +BUILTIN(__builtin_ppc_fctudz, "dd", "") +BUILTIN(__builtin_ppc_fctuwz, "dd", "") +// Compare +BUILTIN(__builtin_ppc_cmpeqb, "LLiLLiLLi", "") +BUILTIN(__builtin_ppc_cmprb, "iCIiii", "") +BUILTIN(__builtin_ppc_setb, "LLiLLiLLi", "") +// Multiply +BUILTIN(__builtin_ppc_mulhd, "LLiLiLi", "") +BUILTIN(__builtin_ppc_mulhdu, "ULLiULiULi", "") +BUILTIN(__builtin_ppc_mulhw, "iii", "") +BUILTIN(__builtin_ppc_mulhwu, "UiUiUi", "") +BUILTIN(__builtin_ppc_maddhd, "LLiLLiLLiLLi", "") +BUILTIN(__builtin_ppc_maddhdu, "ULLiULLiULLiULLi", "") +BUILTIN(__builtin_ppc_maddld, "LLiLLiLLiLLi", "") +// Rotate +BUILTIN(__builtin_ppc_rlwnm, "UiUiIUiIUi", "") +BUILTIN(__builtin_ppc_rlwimi, "UiUiUiIUiIUi", "") +BUILTIN(__builtin_ppc_rldimi, "ULLiULLiULLiIUiIULLi", "") +// load +BUILTIN(__builtin_ppc_load2r, "UiUs*", "") +BUILTIN(__builtin_ppc_load4r, "UiUi*", "") +BUILTIN(__builtin_ppc_load8r, "ULLiULLi*", "") +// store +BUILTIN(__builtin_ppc_store2r, "vUiUs*", "") +BUILTIN(__builtin_ppc_store4r, "vUiUi*", "") +BUILTIN(__builtin_ppc_store8r, "vULLiULLi*", "") +BUILTIN(__builtin_ppc_extract_exp, "Uid", "") +BUILTIN(__builtin_ppc_extract_sig, "ULLid", "") +BUILTIN(__builtin_ppc_mtfsb0, "vUIi", "") +BUILTIN(__builtin_ppc_mtfsb1, "vUIi", "") +BUILTIN(__builtin_ppc_mtfsf, "vUIiUi", "") +BUILTIN(__builtin_ppc_mtfsfi, "vUIiUIi", "") +BUILTIN(__builtin_ppc_insert_exp, "ddULLi", "") +BUILTIN(__builtin_ppc_fmsub, "dddd", "") +BUILTIN(__builtin_ppc_fmsubs, "ffff", "") +BUILTIN(__builtin_ppc_fnmadd, "dddd", "") +BUILTIN(__builtin_ppc_fnmadds, "ffff", "") +BUILTIN(__builtin_ppc_fnmsub, "dddd", "") +BUILTIN(__builtin_ppc_fnmsubs, "ffff", "") +BUILTIN(__builtin_ppc_fre, "dd", "") +BUILTIN(__builtin_ppc_fres, "ff", "") BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n") diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index cdaaa5d81f6df..01c80bdf799a9 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -191,19 +191,9 @@ TARGET_BUILTIN(__builtin_wasm_narrow_u_i16x8_i32x4, "V8UsV4iV4i", "nc", "simd128 TARGET_BUILTIN(__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4, "V4iV2d", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4, "V4UiV2d", "nc", "simd128") -TARGET_BUILTIN(__builtin_wasm_demote_zero_f64x2_f32x4, "V4fV2d", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_load32_zero, "V4iiC*", "n", "simd128") TARGET_BUILTIN(__builtin_wasm_load64_zero, "V2LLiLLiC*", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_load8_lane, "V16ScScC*V16ScIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_load16_lane, "V8ssC*V8sIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_load32_lane, "V4iiC*V4iIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_load64_lane, "V2LLiLLiC*V2LLiIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_store8_lane, "vSc*V16ScIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_store16_lane, "vs*V8sIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_store32_lane, "vi*V4iIi", "n", "simd128") -TARGET_BUILTIN(__builtin_wasm_store64_lane, "vLLi*V2LLiIi", "n", "simd128") - #undef BUILTIN #undef TARGET_BUILTIN diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 4dab3a3b39ac3..4dff3379ed35b 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -111,6 +111,8 @@ def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, DefaultFatal; def err_module_prebuilt : Error< "error in loading module '%0' from prebuilt module path">, DefaultFatal; +def err_module_rebuild_finalized : Error< + "cannot rebuild module '%0' as it is already finalized">, DefaultFatal; def note_pragma_entered_here : Note<"#pragma entered here">; def note_decl_hiding_tag_type : Note< "%1 %0 is hidden by a non-type declaration of %0 here">; @@ -367,4 +369,6 @@ def warn_opencl_unsupported_core_feature : Warning< def err_opencl_extension_and_feature_differs : Error< "options %0 and %1 are set to different values">; +def err_opencl_feature_requires : Error< + "feature %0 requires support of %1 feature">; } diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index eb738b24ccda4..cfc10fa15b2d7 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1085,6 +1085,9 @@ def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct, // A warning group for warnings about code that clang accepts but gcc doesn't. def GccCompat : DiagGroup<"gcc-compat">; +// A warning group for warnings about code that may be incompatible on AIX. +def AIXCompat : DiagGroup<"aix-compat">; + // Warnings for Microsoft extensions. def MicrosoftCharize : DiagGroup<"microsoft-charize">; def MicrosoftDrectveSection : DiagGroup<"microsoft-drectve-section">; @@ -1188,8 +1191,11 @@ def OpenMPClauses : DiagGroup<"openmp-clauses">; def OpenMPLoopForm : DiagGroup<"openmp-loop-form">; def OpenMPMapping : DiagGroup<"openmp-mapping">; def OpenMPTarget : DiagGroup<"openmp-target", [OpenMPMapping]>; +def OpenMPPre51Compat : DiagGroup<"pre-openmp-51-compat">; +def OpenMP51Ext : DiagGroup<"openmp-51-extensions">; def OpenMP : DiagGroup<"openmp", [ - SourceUsesOpenMP, OpenMPClauses, OpenMPLoopForm, OpenMPTarget, OpenMPMapping + SourceUsesOpenMP, OpenMPClauses, OpenMPLoopForm, OpenMPTarget, + OpenMPMapping, OpenMP51Ext ]>; // SYCL warnings diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index aecc5859c718e..7e4b0841e06b1 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1427,6 +1427,15 @@ def err_omp_expected_interop_type : Error< def warn_omp_more_one_interop_type : Warning<"interop type '%0' cannot be specified more than once">, InGroup; +def err_expected_sequence_or_directive : Error< + "expected an OpenMP 'directive' or 'sequence' attribute argument">; +def ext_omp_attributes : ExtWarn< + "specifying OpenMP directives with [[]] is an OpenMP 5.1 extension">, + InGroup; +def warn_omp51_compat_attributes : Warning< + "specifying OpenMP directives with [[]] is incompatible with OpenMP " + "standards before OpenMP 5.1">, + InGroup, DefaultIgnore; // Pragma loop support. def err_pragma_loop_missing_argument : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index be7f5f07c9f3d..138f0a2118f2f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -82,11 +82,11 @@ def err_typecheck_converted_constant_expression_indirect : Error< "bind reference to a temporary">; def err_expr_not_cce : Error< "%select{case value|enumerator value|non-type template argument|" - "array size|constexpr if condition|explicit specifier argument}0 " + "array size|explicit specifier argument}0 " "is not a constant expression">; def ext_cce_narrowing : ExtWarn< "%select{case value|enumerator value|non-type template argument|" - "array size|constexpr if condition|explicit specifier argument}0 " + "array size|explicit specifier argument}0 " "%select{cannot be narrowed from type %2 to %3|" "evaluates to %2, which cannot be narrowed to type %3}1">, InGroup, DefaultError, SFINAEFailure; @@ -1520,6 +1520,8 @@ def err_messaging_class_with_direct_method : Error< // C++ declarations def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; +def err_constexpr_if_condition_expression_is_not_constant : Error< + "constexpr if condition is not a constant expression">; def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">; def err_static_assert_requirement_failed : Error< "static_assert failed due to requirement '%0'%select{ %2|}1">; @@ -3291,6 +3293,10 @@ def warn_assume_aligned_too_great : Warning<"requested alignment must be %0 bytes or smaller; maximum " "alignment assumed">, InGroup>; +def warn_not_xl_compatible + : Warning<"requesting an alignment of 16 bytes or greater for struct" + " members is not binary compatible with AIX XL 16.1 and older">, + InGroup; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "%q0 redeclared without %1 attribute: previous %1 ignored">, InGroup; @@ -5881,11 +5887,8 @@ def err_anon_bitfield_has_negative_width : Error< "anonymous bit-field has negative width (%0)">; def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">; def err_bitfield_width_exceeds_type_width : Error< - "width of bit-field %0 (%1 bits) exceeds %select{width|size}2 " - "of its type (%3 bit%s3)">; -def err_anon_bitfield_width_exceeds_type_width : Error< - "width of anonymous bit-field (%0 bits) exceeds %select{width|size}1 " - "of its type (%2 bit%s2)">; + "width of%select{ anonymous|}0 bit-field%select{| %1}0 (%2 bits) exceeds the " + "%select{width|size}3 of its type (%4 bit%s4)">; def err_incorrect_number_of_vector_initializers : Error< "number of elements must be either one or match the size of the vector">; @@ -9777,6 +9780,8 @@ def err_argument_not_shifted_byte : Error< "argument should be an 8-bit value shifted by a multiple of 8 bits">; def err_argument_not_shifted_byte_or_xxff : Error< "argument should be an 8-bit value shifted by a multiple of 8 bits, or in the form 0x??FF">; +def err_argument_not_contiguous_bit_field : Error< + "argument %0 value should represent a contiguous bit field">; def err_rotation_argument_to_cadd : Error<"argument should be the value 90 or 270">; def err_rotation_argument_to_cmla @@ -9805,8 +9810,8 @@ def err_mips_builtin_requires_dspr2 : Error< "this builtin requires 'dsp r2' ASE, please use -mdspr2">; def err_mips_builtin_requires_msa : Error< "this builtin requires 'msa' ASE, please use -mmsa">; -def err_ppc_builtin_only_on_pwr7 : Error< - "this builtin is only valid on POWER7 or later CPUs">; +def err_ppc_builtin_only_on_arch : Error< + "this builtin is only valid on POWER%0 or later CPUs">; def err_ppc_invalid_use_mma_type : Error< "invalid use of PPC MMA type">; def err_x86_builtin_invalid_rounding : Error< @@ -10161,7 +10166,8 @@ def err_opencl_builtin_pipe_invalid_access_modifier : Error< def err_opencl_invalid_access_qualifier : Error< "access qualifier can only be used for pipe and image type">; def err_opencl_invalid_read_write : Error< - "access qualifier %0 can not be used for %1 %select{|prior to OpenCL version 2.0}2">; + "access qualifier %0 can not be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 " + "and without __opencl_c_read_write_images feature}2">; def err_opencl_multiple_access_qualifiers : Error< "multiple access qualifiers">; def note_opencl_typedef_access_qualifier : Note< diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index ce48833a87030..bf3221be004de 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -69,6 +69,9 @@ def err_module_file_not_module : Error< "AST file '%0' was not built as a module">, DefaultFatal; def err_module_file_missing_top_level_submodule : Error< "module file '%0' is missing its top-level submodule">, DefaultFatal; +def note_module_file_conflict : Note< + "this is generally caused by modules with the same name found in multiple " + "paths">; def remark_module_import : Remark< "importing module '%0'%select{| into '%3'}2 from '%1'">, diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index b82c2775c4e89..de1fb26a2d7cc 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -715,7 +715,11 @@ enum TranslationUnitKind { TU_Prefix, /// The translation unit is a module. - TU_Module + TU_Module, + + /// The translation unit is a is a complete translation unit that we might + /// incrementally extend later. + TU_Incremental }; } // namespace clang diff --git a/clang/include/clang/Basic/OpenCLOptions.h b/clang/include/clang/Basic/OpenCLOptions.h index 44fda029411f1..1a035626fade4 100644 --- a/clang/include/clang/Basic/OpenCLOptions.h +++ b/clang/include/clang/Basic/OpenCLOptions.h @@ -19,6 +19,9 @@ namespace clang { +class DiagnosticsEngine; +class TargetInfo; + namespace { // This enum maps OpenCL version(s) into value. These values are used as // a mask to indicate in which OpenCL version(s) extension is a core or @@ -64,7 +67,23 @@ static inline bool isOpenCLVersionContainedInMask(const LangOptions &LO, /// OpenCL supported extensions and optional core features class OpenCLOptions { + public: + // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the + // __constant address space. + // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static + // variables inside a function can also be declared in the global + // address space. + // OpenCL C v3.0 s6.7.1 - Variables at program scope or static or extern + // variables inside functions can be declared in global address space if + // the __opencl_c_program_scope_global_variables feature is supported + // C++ for OpenCL inherits rule from OpenCL C v2.0. + bool areProgramScopeVariablesSupported(const LangOptions &Opts) const { + return Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200 || + (Opts.OpenCLVersion == 300 && + isSupported("__opencl_c_program_scope_global_variables", Opts)); + } + struct OpenCLOptionInfo { // Does this option have pragma. bool WithPragma = false; @@ -179,6 +198,16 @@ class OpenCLOptions { return OpenCLOptionInfo(std::forward(args)...).isAvailableIn(LO); } + // Diagnose feature dependencies for OpenCL C 3.0. Return false if target + // doesn't follow these requirements. + static bool diagnoseUnsupportedFeatureDependencies(const TargetInfo &TI, + DiagnosticsEngine &Diags); + + // Diagnose that features and equivalent extension are set to same values. + // Return false if target doesn't follow these requirements. + static bool diagnoseFeatureExtensionDifferences(const TargetInfo &TI, + DiagnosticsEngine &Diags); + private: // Option is enabled via pragma bool isEnabled(llvm::StringRef Ext) const; diff --git a/clang/include/clang/Basic/SourceLocation.h b/clang/include/clang/Basic/SourceLocation.h index fc722b1d563db..0ba0f9bd3ddf2 100644 --- a/clang/include/clang/Basic/SourceLocation.h +++ b/clang/include/clang/Basic/SourceLocation.h @@ -16,7 +16,6 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/PointerLikeTypeTraits.h" #include #include #include @@ -510,20 +509,6 @@ namespace llvm { static void Profile(const clang::SourceLocation &X, FoldingSetNodeID &ID); }; - // Teach SmallPtrSet how to handle SourceLocation. - template<> - struct PointerLikeTypeTraits { - static constexpr int NumLowBitsAvailable = 0; - - static void *getAsVoidPointer(clang::SourceLocation L) { - return L.getPtrEncoding(); - } - - static clang::SourceLocation getFromVoidPointer(void *P) { - return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P); - } - }; - } // namespace llvm #endif // LLVM_CLANG_BASIC_SOURCELOCATION_H diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 248389af2050c..63d10781d1d5d 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -873,6 +873,13 @@ PRAGMA_ANNOTATION(pragma_ms_pragma) PRAGMA_ANNOTATION(pragma_opencl_extension) // Annotations for OpenMP pragma directives - #pragma omp ... +// The parser produces this annotation token when it parses an [[omp::*]] +// attribute. The tokens from the attribute argument list are replayed to the +// token stream with this leading token (and a trailing pragma_openmp_end) so +// that the parser can reuse the OpenMP parsing logic but still be able to +// distinguish between a real pragma and a converted pragma. It is not marked +// as a PRAGMA_ANNOTATION because it doesn't get generated from a #pragma. +ANNOTATION(attr_openmp) // The lexer produces these so that they only take effect when the parser // handles #pragma omp ... directives. PRAGMA_ANNOTATION(pragma_openmp) diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td index 495e5ef45218d..336f02cd9c25b 100644 --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -131,7 +131,7 @@ // There are a number of attributes that are used to constraint the number and // shape of the builtins generated. Refer to the comments below for them. class RVVBuiltin { + string mangled_suffix = ""> { // Base name that will be prepended in __builtin_rvv_ and appended the // computed Suffix. string Name = NAME; @@ -145,6 +145,10 @@ class RVVBuiltin; - def vreinterpret_i_f : RVVBuiltin<"Fvv", "vFv", "il">; - def vreinterpret_u_i : RVVBuiltin<"vUv", "Uvv", "csil">; - def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "il">; - def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "il">; - def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "il">; + def vreinterpret_i_u : RVVBuiltin<"Uvv", "vUv", "csil", "v">; + def vreinterpret_i_f : RVVBuiltin<"Fvv", "vFv", "il", "v">; + def vreinterpret_u_i : RVVBuiltin<"vUv", "Uvv", "csil", "Uv">; + def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "il", "Uv">; + def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "il", "Fv">; + def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "il", "Fv">; // Reinterpret between different SEW under the same LMUL foreach dst_sew = ["(FixedSEW:8)", "(FixedSEW:16)", "(FixedSEW:32)", "(FixedSEW:64)"] in { - def vreinterpret_i_ # dst_sew : RVVBuiltin<"v" # dst_sew # "v", dst_sew # "vv", "csil">; - def vreinterpret_u_ # dst_sew : RVVBuiltin<"Uv" # dst_sew # "Uv", dst_sew # "UvUv", "csil">; + def vreinterpret_i_ # dst_sew : RVVBuiltin<"v" # dst_sew # "v", + dst_sew # "vv", "csil", dst_sew # "v">; + def vreinterpret_u_ # dst_sew : RVVBuiltin<"Uv" # dst_sew # "Uv", + dst_sew # "UvUv", "csil", dst_sew # "Uv">; } } - let Name = "vundefined", + let Name = "vundefined", HasNoMaskedOverloaded = false, ManualCodegen = [{ return llvm::UndefValue::get(ResultType); }] in { @@ -1743,7 +1748,7 @@ let HasMask = false, HasVL = false, HasNoMaskedOverloaded = false, // LMUL truncation // C/C++ Operand: VecTy, IR Operand: VecTy, Index - let Name = "vlmul_trunc_v", + let Name = "vlmul_trunc_v", MangledName = "vlmul_trunc", ManualCodegen = [{ { ID = Intrinsic::experimental_vector_extract; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -1752,14 +1757,16 @@ let HasMask = false, HasVL = false, HasNoMaskedOverloaded = false, } }] in { foreach dst_lmul = ["(SFixedLog2LMUL:-3)", "(SFixedLog2LMUL:-2)", "(SFixedLog2LMUL:-1)", "(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in { - def vlmul_trunc # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vv", "csilfd">; - def vlmul_trunc_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUv", "csil">; + def vlmul_trunc # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v", + dst_lmul # "vv", "csilfd", dst_lmul # "v">; + def vlmul_trunc_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv", + dst_lmul # "UvUv", "csil", dst_lmul # "Uv">; } } // LMUL extension // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index - let Name = "vlmul_ext_v", + let Name = "vlmul_ext_v", MangledName = "vlmul_ext", ManualCodegen = [{ ID = Intrinsic::experimental_vector_insert; IntrinsicTypes = {ResultType, Ops[0]->getType()}; @@ -1770,8 +1777,10 @@ let HasMask = false, HasVL = false, HasNoMaskedOverloaded = false, }] in { foreach dst_lmul = ["(LFixedLog2LMUL:-2)", "(LFixedLog2LMUL:-1)", "(LFixedLog2LMUL:-0)", "(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in { - def vlmul_ext # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vv", "csilfd">; - def vlmul_ext_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUv", "csil">; + def vlmul_ext # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v", + dst_lmul # "vv", "csilfd", dst_lmul # "v">; + def vlmul_ext_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv", + dst_lmul # "UvUv", "csil", dst_lmul # "Uv">; } } @@ -1788,8 +1797,8 @@ let HasMask = false, HasVL = false, HasNoMaskedOverloaded = false, } }] in { foreach dst_lmul = ["(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in { - def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vvKz", "csilfd">; - def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUvKz", "csil">; + def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vvKz", "csilfd", dst_lmul # "v">; + def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUvKz", "csil", dst_lmul # "Uv">; } } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 05d6203453c20..db66023ceb61c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1579,6 +1579,12 @@ def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-o Group, Flags<[CoreOption, NoXarchOption]>, HelpText<"Disable origins tracking in MemorySanitizer">; +def fsanitize_address_outline_instrumentation : Flag<["-"], "fsanitize-address-outline-instrumentation">, + Group, + HelpText<"Always generate function calls for address sanitizer instrumentation">; +def fno_sanitize_address_outline_instrumentation : Flag<["-"], "fno-sanitize-address-outline-instrumentation">, + Group, + HelpText<"Use default code inlining logic for the address sanitizer">; def fsanitize_hwaddress_experimental_aliasing : Flag<["-"], "fsanitize-hwaddress-experimental-aliasing">, Group, diff --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h index 63a195fdf7537..e9e329e7cb53f 100644 --- a/clang/include/clang/Driver/SanitizerArgs.h +++ b/clang/include/clang/Driver/SanitizerArgs.h @@ -44,6 +44,7 @@ class SanitizerArgs { bool AsanUseOdrIndicator = false; bool AsanInvalidPointerCmp = false; bool AsanInvalidPointerSub = false; + bool AsanOutlineInstrumentation = false; llvm::AsanDtorKind AsanDtorKind = llvm::AsanDtorKind::Invalid; std::string HwasanAbi; bool LinkRuntimes = true; diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index d4dd8731da184..020cbe2db3d06 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_INTERPRETER_INTERPRETER_H #define LLVM_CLANG_INTERPRETER_INTERPRETER_H -#include "clang/Interpreter/Transaction.h" +#include "clang/Interpreter/PartialTranslationUnit.h" #include "llvm/Support/Error.h" @@ -55,14 +55,14 @@ class Interpreter { static llvm::Expected> create(std::unique_ptr CI); const CompilerInstance *getCompilerInstance() const; - llvm::Expected Parse(llvm::StringRef Code); - llvm::Error Execute(Transaction &T); + llvm::Expected Parse(llvm::StringRef Code); + llvm::Error Execute(PartialTranslationUnit &T); llvm::Error ParseAndExecute(llvm::StringRef Code) { - auto ErrOrTransaction = Parse(Code); - if (auto Err = ErrOrTransaction.takeError()) - return Err; - if (ErrOrTransaction->TheModule) - return Execute(*ErrOrTransaction); + auto PTU = Parse(Code); + if (!PTU) + return PTU.takeError(); + if (PTU->TheModule) + return Execute(*PTU); return llvm::Error::success(); } }; diff --git a/clang/include/clang/Interpreter/Transaction.h b/clang/include/clang/Interpreter/PartialTranslationUnit.h similarity index 74% rename from clang/include/clang/Interpreter/Transaction.h rename to clang/include/clang/Interpreter/PartialTranslationUnit.h index 15639d4af0f98..bf91d559452b8 100644 --- a/clang/include/clang/Interpreter/Transaction.h +++ b/clang/include/clang/Interpreter/PartialTranslationUnit.h @@ -11,11 +11,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_INTERPRETER_TRANSACTION_H -#define LLVM_CLANG_INTERPRETER_TRANSACTION_H +#ifndef LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H +#define LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H #include -#include namespace llvm { class Module; @@ -23,17 +22,16 @@ class Module; namespace clang { -class DeclGroupRef; +class TranslationUnitDecl; /// The class keeps track of various objects created as part of processing /// incremental inputs. -struct Transaction { - /// The decls created for the input. - std::vector Decls; +struct PartialTranslationUnit { + TranslationUnitDecl *TUPart = nullptr; /// The llvm IR produced for the input. std::unique_ptr TheModule; }; } // namespace clang -#endif // LLVM_CLANG_INTERPRETER_TRANSACTION_H +#endif // LLVM_CLANG_INTERPRETER_PARTIALTRANSLATIONUNIT_H diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 2d6335471383c..7ab13640ce2c0 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -264,9 +264,11 @@ class Preprocessor { /// avoid tearing the Lexer and etc. down). bool IncrementalProcessing = false; +public: /// The kind of translation unit we are processing. - TranslationUnitKind TUKind; + const TranslationUnitKind TUKind; +private: /// The code-completion handler. CodeCompletionHandler *CodeComplete = nullptr; @@ -781,8 +783,7 @@ class Preprocessor { /// deserializing from PCH, we don't need to deserialize identifier & macros /// just so that we can report that they are unused, we just warn using /// the SourceLocations of this set (that will be filled by the ASTReader). - /// We are using SmallPtrSet instead of a vector for faster removal. - using WarnUnusedMacroLocsTy = llvm::SmallPtrSet; + using WarnUnusedMacroLocsTy = llvm::SmallDenseSet; WarnUnusedMacroLocsTy WarnUnusedMacroLocs; /// A "freelist" of MacroArg objects that can be diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d0147a800f41a..2a3f6942fd451 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2773,6 +2773,16 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *ScopeName, SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax); + void ReplayOpenMPAttributeTokens(CachedTokens &OpenMPTokens) { + // If parsing the attributes found an OpenMP directive, emit those tokens + // to the parse stream now. + if (!OpenMPTokens.empty()) { + PP.EnterToken(Tok, /*IsReinject*/ true); + PP.EnterTokenStream(OpenMPTokens, /*DisableMacroExpansion*/ true, + /*IsReinject*/ true); + ConsumeAnyToken(/*ConsumeCodeCompletionTok*/ true); + } + } void MaybeParseCXX11Attributes(Declarator &D) { if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); @@ -2802,8 +2812,18 @@ class Parser : public CodeCompletionHandler { return false; } - void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, - SourceLocation *EndLoc = nullptr); + void ParseOpenMPAttributeArgs(IdentifierInfo *AttrName, + CachedTokens &OpenMPTokens); + + void ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, + CachedTokens &OpenMPTokens, + SourceLocation *EndLoc = nullptr); + void ParseCXX11AttributeSpecifier(ParsedAttributes &Attrs, + SourceLocation *EndLoc = nullptr) { + CachedTokens OpenMPTokens; + ParseCXX11AttributeSpecifierInternal(Attrs, OpenMPTokens, EndLoc); + ReplayOpenMPAttributeTokens(OpenMPTokens); + } void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *EndLoc = nullptr); /// Parses a C++11 (or C2x)-style attribute argument list. Returns true @@ -2812,7 +2832,8 @@ class Parser : public CodeCompletionHandler { SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc); + SourceLocation ScopeLoc, + CachedTokens &OpenMPTokens); IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index aa5a33a67875e..6fb75a47c61ce 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1545,7 +1545,7 @@ class Sema final { /// initializers for tentative definitions in C) once parsing has /// completed. Modules and precompiled headers perform different kinds of /// checks. - TranslationUnitKind TUKind; + const TranslationUnitKind TUKind; llvm::BumpPtrAllocator BumpAlloc; @@ -3742,7 +3742,6 @@ class Sema final { CCEK_Enumerator, ///< Enumerator value with fixed underlying type. CCEK_TemplateArg, ///< Value of a non-type template parameter. CCEK_ArrayBound, ///< Array bound in array declarator or new-expression. - CCEK_ConstexprIf, ///< Condition in a constexpr if statement. CCEK_ExplicitBool ///< Condition in an explicit(bool) specifier. }; ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, @@ -6339,6 +6338,12 @@ class Sema final { void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, bool IsDereference, SourceRange Range); + // Checks that the vector type should be initialized from a scalar + // by splatting the value rather than populating a single element. + // This is the case for AltiVecVector types as well as with + // AltiVecPixel and AltiVecBool when -faltivec-src-compat=xl is specified. + bool ShouldSplatAltivecScalarInCast(const VectorType *VecTy); + /// ActOnCXXNamedCast - Parse /// {dynamic,static,reinterpret,const,addrspace}_cast's. ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, @@ -12920,6 +12925,7 @@ class Sema final { bool SemaBuiltinComplex(CallExpr *TheCall); bool SemaBuiltinVSX(CallExpr *TheCall); bool SemaBuiltinOSLogFormat(CallExpr *TheCall); + bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum); public: // Used by C++ template instantiation. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 6932d9c86d0cc..4819a5aecefaf 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1401,6 +1401,9 @@ class ASTReader llvm::iterator_range getModulePreprocessedEntities(ModuleFile &Mod) const; + bool canRecoverFromOutOfDate(StringRef ModuleFileName, + unsigned ClientLoadCapabilities); + public: class ModuleDeclIterator : public llvm::iterator_adaptor_base< diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 99cd24a52f2df..3c93ebeccde8d 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -432,6 +432,8 @@ class PathSensitiveBugReport : public BugReport { void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough); + void markNotInteresting(SymbolRef sym); + /// Marks a region as interesting. Different kinds of interestingness will /// be processed differently by visitors (e.g. if the tracking kind is /// condition, will append "will be used as a condition" to the message). @@ -439,6 +441,8 @@ class PathSensitiveBugReport : public BugReport { const MemRegion *R, bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough); + void markNotInteresting(const MemRegion *R); + /// Marks a symbolic value as interesting. Different kinds of interestingness /// will be processed differently by visitors (e.g. if the tracking kind is /// condition, will append "will be used as a condition" to the message). diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index f253c14cc4870..a81d67ab30639 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -13,7 +13,9 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H +#include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" +#include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/Optional.h" #include @@ -69,6 +71,45 @@ Nullability getNullabilityAnnotation(QualType Type); /// token for an integer. If we cannot parse the value then None is returned. llvm::Optional tryExpandAsInteger(StringRef Macro, const Preprocessor &PP); +class OperatorKind { + union { + BinaryOperatorKind Bin; + UnaryOperatorKind Un; + } Op; + bool IsBinary; + +public: + explicit OperatorKind(BinaryOperatorKind Bin) : Op{Bin}, IsBinary{true} {} + explicit OperatorKind(UnaryOperatorKind Un) : IsBinary{false} { Op.Un = Un; } + bool IsBinaryOp() const { return IsBinary; } + + BinaryOperatorKind GetBinaryOpUnsafe() const { + assert(IsBinary && "cannot get binary operator - we have a unary operator"); + return Op.Bin; + } + + Optional GetBinaryOp() const { + if (IsBinary) + return Op.Bin; + return {}; + } + + UnaryOperatorKind GetUnaryOpUnsafe() const { + assert(!IsBinary && + "cannot get unary operator - we have a binary operator"); + return Op.Un; + } + + Optional GetUnaryOp() const { + if (!IsBinary) + return Op.Un; + return {}; + } +}; + +OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, + bool IsBinary); + } // namespace ento } // namespace clang diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 64c61a3514be8..87a49cf4ffe9a 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -238,6 +238,14 @@ class SValBuilder { const LocationContext *LCtx, unsigned Count); + /// Conjure a symbol representing heap allocated memory region. + /// + /// Note, now, the expression *doesn't* need to represent a location. + /// But the type need to! + DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E, + const LocationContext *LCtx, + QualType type, unsigned Count); + DefinedOrUnknownSVal getDerivedRegionValueSymbolVal( SymbolRef parentSymbol, const TypedValueRegion *region); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 27c4e82a1285d..e1981bc983ca7 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -966,7 +966,7 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, - Builtin::Context &builtins) + Builtin::Context &builtins, TranslationUnitKind TUKind) : ConstantArrayTypes(this_()), FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()), @@ -978,11 +978,10 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, LangOpts.XRayAttrListFiles, SM)), ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), - BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM), - CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), + BuiltinInfo(builtins), TUKind(TUKind), DeclarationNames(*this), + Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), CompCategories(this_()), LastSDM(nullptr, 0) { - TUDecl = TranslationUnitDecl::Create(*this); - TraversalScope = {TUDecl}; + addTranslationUnitDecl(); } ASTContext::~ASTContext() { @@ -1196,9 +1195,10 @@ ExternCContextDecl *ASTContext::getExternCContextDecl() const { BuiltinTemplateDecl * ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, const IdentifierInfo *II) const { - auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK); + auto *BuiltinTemplate = + BuiltinTemplateDecl::Create(*this, getTranslationUnitDecl(), II, BTK); BuiltinTemplate->setImplicit(); - TUDecl->addDecl(BuiltinTemplate); + getTranslationUnitDecl()->addDecl(BuiltinTemplate); return BuiltinTemplate; } @@ -1490,7 +1490,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // MSVC predeclares struct _GUID, and we need it to create MSGuidDecls. if (LangOpts.MicrosoftExt || LangOpts.Borland) { MSGuidTagDecl = buildImplicitRecord("_GUID"); - TUDecl->addDecl(MSGuidTagDecl); + getTranslationUnitDecl()->addDecl(MSGuidTagDecl); } } @@ -6634,7 +6634,7 @@ QualType ASTContext::getCFConstantStringType() const { QualType ASTContext::getObjCSuperType() const { if (ObjCSuperType.isNull()) { RecordDecl *ObjCSuperTypeDecl = buildImplicitRecord("objc_super"); - TUDecl->addDecl(ObjCSuperTypeDecl); + getTranslationUnitDecl()->addDecl(ObjCSuperTypeDecl); ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl); } return ObjCSuperType; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 008c8ed510e7f..32c07ebe4c34c 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -102,7 +102,7 @@ bool Decl::isOutOfLine() const { TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, nullptr, SourceLocation()), - DeclContext(TranslationUnit), Ctx(ctx) {} + DeclContext(TranslationUnit), redeclarable_base(ctx), Ctx(ctx) {} //===----------------------------------------------------------------------===// // NamedDecl Implementation diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 80b591e2a81a2..3467da2b549e2 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1219,7 +1219,6 @@ bool DeclContext::Encloses(const DeclContext *DC) const { DeclContext *DeclContext::getPrimaryContext() { switch (getDeclKind()) { - case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::LinkageSpec: case Decl::Export: @@ -1231,6 +1230,8 @@ DeclContext *DeclContext::getPrimaryContext() { // There is only one DeclContext for these entities. return this; + case Decl::TranslationUnit: + return static_cast(this)->getFirstDecl(); case Decl::Namespace: // The original namespace is our primary context. return static_cast(this)->getOriginalNamespace(); @@ -1285,21 +1286,25 @@ DeclContext *DeclContext::getPrimaryContext() { } } -void -DeclContext::collectAllContexts(SmallVectorImpl &Contexts){ - Contexts.clear(); +template +void collectAllContextsImpl(T *Self, SmallVectorImpl &Contexts) { + for (T *D = Self->getMostRecentDecl(); D; D = D->getPreviousDecl()) + Contexts.push_back(D); - if (getDeclKind() != Decl::Namespace) { - Contexts.push_back(this); - return; - } + std::reverse(Contexts.begin(), Contexts.end()); +} - auto *Self = static_cast(this); - for (NamespaceDecl *N = Self->getMostRecentDecl(); N; - N = N->getPreviousDecl()) - Contexts.push_back(N); +void DeclContext::collectAllContexts(SmallVectorImpl &Contexts) { + Contexts.clear(); - std::reverse(Contexts.begin(), Contexts.end()); + Decl::Kind Kind = getDeclKind(); + + if (Kind == Decl::TranslationUnit) + collectAllContextsImpl(static_cast(this), Contexts); + else if (Kind == Decl::Namespace) + collectAllContextsImpl(static_cast(this), Contexts); + else + Contexts.push_back(this); } std::pair diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 0ff9813ed987c..26f75bc65bd17 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -490,6 +490,8 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context, void DeclRefExpr::setDecl(ValueDecl *NewD) { D = NewD; + if (getType()->isUndeducedType()) + setType(NewD->getType()); setDependence(computeDependence(this, NewD->getASTContext())); } @@ -1777,8 +1779,10 @@ MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, return new (Mem) MemberExpr(EmptyShell()); } -void MemberExpr::setMemberDecl(ValueDecl *D) { - MemberDecl = D; +void MemberExpr::setMemberDecl(ValueDecl *NewD) { + MemberDecl = NewD; + if (getType()->isUndeducedType()) + setType(NewD->getType()); setDependence(computeDependence(this)); } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 88ea3e6d23952..861062446c3ba 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -2756,7 +2756,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) { case CC_X86FastCall: Out << 'I'; break; case CC_X86VectorCall: Out << 'Q'; break; case CC_Swift: Out << 'S'; break; - case CC_SwiftAsync: Out << 'T'; break; + case CC_SwiftAsync: Out << 'W'; break; case CC_PreserveMost: Out << 'U'; break; case CC_X86RegCall: Out << 'w'; break; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index f46290454d631..4230ea6b7a5a7 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1775,6 +1775,12 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { !D->getIdentifier()) FieldAlign = UnpackedFieldAlign = 1; + // On AIX, zero-width bitfields pad out to the alignment boundary, but then + // do not affect overall record alignment if there is a pragma pack or + // pragma align(packed). + if (isAIXLayout(Context) && !MaxFieldAlignment.isZero() && !FieldSize) + FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); + // Diagnose differences in layout due to padding or packing. if (!UseExternalLayout) CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset, diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 2d6f00a5df3f7..15d70c5339db1 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1801,6 +1801,9 @@ namespace { } // Only these types can contain the desired 'auto' type. + Type *VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + return Visit(T->getReplacementType()); + } Type *VisitElaboratedType(const ElaboratedType *T) { return Visit(T->getNamedType()); diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index ff6dbf870fcf4..62eea9c590825 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -20,6 +20,14 @@ int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, else if (ScopeName == "_Clang") ScopeName = "clang"; + // As a special case, look for the omp::sequence and omp::directive + // attributes. We support those, but not through the typical attribute + // machinery that goes through TableGen. We support this in all OpenMP modes + // so long as double square brackets are enabled. + if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes && + ScopeName == "omp") + return (Name == "directive" || Name == "sequence") ? 1 : 0; + #include "clang/Basic/AttrHasAttributeImpl.inc" return 0; diff --git a/clang/lib/Basic/OpenCLOptions.cpp b/clang/lib/Basic/OpenCLOptions.cpp index 7a647f02b1bd0..2e215b185f662 100644 --- a/clang/lib/Basic/OpenCLOptions.cpp +++ b/clang/lib/Basic/OpenCLOptions.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/OpenCLOptions.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/TargetInfo.h" namespace clang { @@ -104,4 +106,43 @@ void OpenCLOptions::disableAll() { Opt.getValue().Enabled = false; } +bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies( + const TargetInfo &TI, DiagnosticsEngine &Diags) { + // Feature pairs. First feature in a pair requires the second one to be + // supported. + static const llvm::StringMap DependentFeaturesMap = { + {"__opencl_c_read_write_images", "__opencl_c_images"}}; + + auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); + + bool IsValid = true; + for (auto &FeaturePair : DependentFeaturesMap) + if (TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getKey()) && + !TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getValue())) { + IsValid = false; + Diags.Report(diag::err_opencl_feature_requires) + << FeaturePair.getKey() << FeaturePair.getValue(); + } + return IsValid; +} + +bool OpenCLOptions::diagnoseFeatureExtensionDifferences( + const TargetInfo &TI, DiagnosticsEngine &Diags) { + // Extensions and equivalent feature pairs. + static const llvm::StringMap FeatureExtensionMap = { + {"cl_khr_fp64", "__opencl_c_fp64"}}; + + auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts(); + + bool IsValid = true; + for (auto &ExtAndFeat : FeatureExtensionMap) + if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getKey()) != + TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getValue())) { + IsValid = false; + Diags.Report(diag::err_opencl_extension_and_feature_differs) + << ExtAndFeat.getKey() << ExtAndFeat.getValue(); + } + return IsValid; +} + } // end namespace clang diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 88086fa2fed74..b647a2fb8a679 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -396,6 +396,19 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { HalfFormat = &llvm::APFloat::IEEEhalf(); FloatFormat = &llvm::APFloat::IEEEsingle(); LongDoubleFormat = &llvm::APFloat::IEEEquad(); + + // OpenCL C v3.0 s6.7.5 - The generic address space requires support for + // OpenCL C 2.0 or OpenCL C 3.0 with the __opencl_c_generic_address_space + // feature + // FIXME: OpenCLGenericAddressSpace is also defined in setLangDefaults() + // for OpenCL C 2.0 but with no access to target capabilities. Target + // should be immutable once created and thus this language option needs + // to be defined only once. + if (Opts.OpenCLVersion >= 300) { + const auto &OpenCLFeaturesMap = getSupportedOpenCLOpts(); + Opts.OpenCLGenericAddressSpace = hasFeatureEnabled( + OpenCLFeaturesMap, "__opencl_c_generic_address_space"); + } } if (Opts.DoubleSize) { diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index c51fdc52f3b28..94524383aa3ee 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -778,15 +778,6 @@ bool TargetInfo::validateOpenCLTarget(const LangOptions &Opts, if (Opts.OpenCLCPlusPlus || Opts.OpenCLVersion < 300) return true; - // Feature and corresponding equivalent extension must be set - // simultaneously to the same value. - for (auto &ExtAndFeat : {std::make_pair("cl_khr_fp64", "__opencl_c_fp64")}) - if (hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.first) != - hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.second)) { - Diags.Report(diag::err_opencl_extension_and_feature_differs) - << ExtAndFeat.first << ExtAndFeat.second; - return false; - } - - return true; + return OpenCLOptions::diagnoseUnsupportedFeatureDependencies(*this, Diags) && + OpenCLOptions::diagnoseFeatureExtensionDifferences(*this, Diags); } diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index e3c77b2e4450b..10af8494c44ec 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -73,6 +73,12 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector &Features, HasROPProtect = true; } else if (Feature == "+privileged") { HasPrivileged = true; + } else if (Feature == "+isa-v207-instructions") { + IsISA2_07 = true; + } else if (Feature == "+isa-v30-instructions") { + IsISA3_0 = true; + } else if (Feature == "+isa-v31-instructions") { + IsISA3_1 = true; } // TODO: Finish this list and add an assert that we've handled them // all. @@ -83,6 +89,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector &Features, static void defineXLCompatMacros(MacroBuilder &Builder) { Builder.defineMacro("__popcntb", "__builtin_ppc_popcntb"); + Builder.defineMacro("__poppar4", "__builtin_ppc_poppar4"); + Builder.defineMacro("__poppar8", "__builtin_ppc_poppar8"); Builder.defineMacro("__eieio", "__builtin_ppc_eieio"); Builder.defineMacro("__iospace_eieio", "__builtin_ppc_iospace_eieio"); Builder.defineMacro("__isync", "__builtin_ppc_isync"); @@ -112,6 +120,52 @@ static void defineXLCompatMacros(MacroBuilder &Builder) { Builder.defineMacro("__lwarx", "__builtin_ppc_lwarx"); Builder.defineMacro("__stdcx", "__builtin_ppc_stdcx"); Builder.defineMacro("__stwcx", "__builtin_ppc_stwcx"); + Builder.defineMacro("__tdw", "__builtin_ppc_tdw"); + Builder.defineMacro("__tw", "__builtin_ppc_tw"); + Builder.defineMacro("__trap", "__builtin_ppc_trap"); + Builder.defineMacro("__trapd", "__builtin_ppc_trapd"); + Builder.defineMacro("__fcfid", "__builtin_ppc_fcfid"); + Builder.defineMacro("__fcfud", "__builtin_ppc_fcfud"); + Builder.defineMacro("__fctid", "__builtin_ppc_fctid"); + Builder.defineMacro("__fctidz", "__builtin_ppc_fctidz"); + Builder.defineMacro("__fctiw", "__builtin_ppc_fctiw"); + Builder.defineMacro("__fctiwz", "__builtin_ppc_fctiwz"); + Builder.defineMacro("__fctudz", "__builtin_ppc_fctudz"); + Builder.defineMacro("__fctuwz", "__builtin_ppc_fctuwz"); + Builder.defineMacro("__cmpeqb", "__builtin_ppc_cmpeqb"); + Builder.defineMacro("__cmprb", "__builtin_ppc_cmprb"); + Builder.defineMacro("__setb", "__builtin_ppc_setb"); + Builder.defineMacro("__mulhd", "__builtin_ppc_mulhd"); + Builder.defineMacro("__mulhdu", "__builtin_ppc_mulhdu"); + Builder.defineMacro("__mulhw", "__builtin_ppc_mulhw"); + Builder.defineMacro("__mulhwu", "__builtin_ppc_mulhwu"); + Builder.defineMacro("__maddhd", "__builtin_ppc_maddhd"); + Builder.defineMacro("__maddhdu", "__builtin_ppc_maddhdu"); + Builder.defineMacro("__maddld", "__builtin_ppc_maddld"); + Builder.defineMacro("__rlwnm", "__builtin_ppc_rlwnm"); + Builder.defineMacro("__rlwimi", "__builtin_ppc_rlwimi"); + Builder.defineMacro("__rldimi", "__builtin_ppc_rldimi"); + Builder.defineMacro("__load2r", "__builtin_ppc_load2r"); + Builder.defineMacro("__load4r", "__builtin_ppc_load4r"); + Builder.defineMacro("__load8r", "__builtin_ppc_load8r"); + Builder.defineMacro("__store2r", "__builtin_ppc_store2r"); + Builder.defineMacro("__store4r", "__builtin_ppc_store4r"); + Builder.defineMacro("__store8r", "__builtin_ppc_store8r"); + Builder.defineMacro("__extract_exp", "__builtin_ppc_extract_exp"); + Builder.defineMacro("__extract_sig", "__builtin_ppc_extract_sig"); + Builder.defineMacro("__mtfsb0", "__builtin_ppc_mtfsb0"); + Builder.defineMacro("__mtfsb1", "__builtin_ppc_mtfsb1"); + Builder.defineMacro("__mtfsf", "__builtin_ppc_mtfsf"); + Builder.defineMacro("__mtfsfi", "__builtin_ppc_mtfsfi"); + Builder.defineMacro("__insert_exp", "__builtin_ppc_insert_exp"); + Builder.defineMacro("__fmsub", "__builtin_ppc_fmsub"); + Builder.defineMacro("__fmsubs", "__builtin_ppc_fmsubs"); + Builder.defineMacro("__fnmadd", "__builtin_ppc_fnmadd"); + Builder.defineMacro("__fnmadds", "__builtin_ppc_fnmadds"); + Builder.defineMacro("__fnmsub", "__builtin_ppc_fnmsub"); + Builder.defineMacro("__fnmsubs", "__builtin_ppc_fnmsubs"); + Builder.defineMacro("__fre", "__builtin_ppc_fre"); + Builder.defineMacro("__fres", "__builtin_ppc_fres"); } /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific @@ -378,6 +432,15 @@ bool PPCTargetInfo::initFeatureMap( .Case("e500", true) .Default(false); + Features["isa-v207-instructions"] = llvm::StringSwitch(CPU) + .Case("ppc64le", true) + .Case("pwr9", true) + .Case("pwr8", true) + .Default(false); + + Features["isa-v30-instructions"] = + llvm::StringSwitch(CPU).Case("pwr9", true).Default(false); + // Power10 includes all the same features as Power9 plus any features specific // to the Power10 core. if (CPU == "pwr10" || CPU == "power10") { @@ -434,6 +497,7 @@ void PPCTargetInfo::addP10SpecificFeatures( Features["power10-vector"] = true; Features["pcrelative-memops"] = true; Features["prefix-instrs"] = true; + Features["isa-v31-instructions"] = true; return; } @@ -464,6 +528,9 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const { .Case("mma", HasMMA) .Case("rop-protect", HasROPProtect) .Case("privileged", HasPrivileged) + .Case("isa-v207-instructions", IsISA2_07) + .Case("isa-v30-instructions", IsISA3_0) + .Case("isa-v31-instructions", IsISA3_1) .Default(false); } diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index bd79c68ce3f71..7c14a4eb9410c 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -74,6 +74,9 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { bool HasP10Vector = false; bool HasPCRelativeMemops = false; bool HasPrefixInstrs = false; + bool IsISA2_07 = false; + bool IsISA3_0 = false; + bool IsISA3_1 = false; protected: std::string ABI; diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 1f31f471db3a4..9705129b39d8f 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -87,6 +87,9 @@ bool RISCVTargetInfo::validateAsmConstraint( // An address that is held in a general-purpose register. Info.setAllowsMemory(); return true; + case 'S': // A symbolic address + Info.setAllowsRegister(); + return true; case 'v': // A vector register. if (Name[1] == 'r' || Name[1] == 'm') { diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index f69b75eabe06e..7480dd48d78ee 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1293,7 +1293,6 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // Only enable CGProfilePass when using integrated assembler, since // non-integrated assemblers don't recognize .cgprofile section. PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS; - PTO.Coroutines = LangOpts.Coroutines; LoopAnalysisManager LAM; FunctionAnalysisManager FAM; diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index e5c5e5babf232..b6722ad4e4f18 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -85,7 +85,7 @@ namespace { (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * lvalue.getAlignment(); VoidPtrAddr = CGF.Builder.CreateConstGEP1_64( - VoidPtrAddr, OffsetInChars.getQuantity()); + CGF.Int8Ty, VoidPtrAddr, OffsetInChars.getQuantity()); auto Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( VoidPtrAddr, CGF.Builder.getIntNTy(AtomicSizeInBits)->getPointerTo(), diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 769501a036e60..f39a56f81d416 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1375,7 +1375,7 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry", Init)); b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(), - b.CreateStructGEP(literal, 0), + b.CreateStructGEP(literal->getValueType(), literal, 0), CGM.getPointerAlign().getAsAlign()); b.CreateRetVoid(); // We can't use the normal LLVM global initialisation array, because we diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index e79d72885e549..4fad44a105cdc 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -261,7 +261,8 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name), + return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Offset), Name), Addr.getAlignment().alignmentAtOffset(Offset)); } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index cad934228b9b7..6231fc3fb8a64 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -994,6 +994,46 @@ static llvm::Value *EmitBitTestIntrinsic(CodeGenFunction &CGF, ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res"); } +static llvm::Value *emitPPCLoadReserveIntrinsic(CodeGenFunction &CGF, + unsigned BuiltinID, + const CallExpr *E) { + Value *Addr = CGF.EmitScalarExpr(E->getArg(0)); + + SmallString<64> Asm; + raw_svector_ostream AsmOS(Asm); + llvm::IntegerType *RetType = CGF.Int32Ty; + + switch (BuiltinID) { + case clang::PPC::BI__builtin_ppc_ldarx: + AsmOS << "ldarx "; + RetType = CGF.Int64Ty; + break; + case clang::PPC::BI__builtin_ppc_lwarx: + AsmOS << "lwarx "; + RetType = CGF.Int32Ty; + break; + default: + llvm_unreachable("Expected only PowerPC load reserve intrinsics"); + } + + AsmOS << "$0, ${1:y}"; + + std::string Constraints = "=r,*Z,~{memory}"; + std::string MachineClobbers = CGF.getTarget().getClobbers(); + if (!MachineClobbers.empty()) { + Constraints += ','; + Constraints += MachineClobbers; + } + + llvm::Type *IntPtrType = RetType->getPointerTo(); + llvm::FunctionType *FTy = + llvm::FunctionType::get(RetType, {IntPtrType}, false); + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, Asm, Constraints, /*hasSideEffects=*/true); + return CGF.Builder.CreateCall(IA, {Addr}); +} + namespace { enum class MSVCSetJmpKind { _setjmpex, @@ -9324,7 +9364,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, llvm::Value *Val = Builder.CreateCall(F, MemAddr); llvm::Value *ToRet; for (size_t i = 0; i < 8; i++) { - llvm::Value *ValOffsetPtr = Builder.CreateGEP(ValPtr, Builder.getInt32(i)); + llvm::Value *ValOffsetPtr = + Builder.CreateGEP(Int64Ty, ValPtr, Builder.getInt32(i)); Address Addr(ValOffsetPtr, CharUnits::fromQuantity(8)); ToRet = Builder.CreateStore(Builder.CreateExtractValue(Val, i), Addr); } @@ -9335,7 +9376,8 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, SmallVector Args; Args.push_back(MemAddr); for (size_t i = 0; i < 8; i++) { - llvm::Value *ValOffsetPtr = Builder.CreateGEP(ValPtr, Builder.getInt32(i)); + llvm::Value *ValOffsetPtr = + Builder.CreateGEP(Int64Ty, ValPtr, Builder.getInt32(i)); Address Addr(ValOffsetPtr, CharUnits::fromQuantity(8)); Args.push_back(Builder.CreateLoad(Addr)); } @@ -14735,7 +14777,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, for (int i = 0; i < 6; ++i) { Value *Extract = Builder.CreateExtractValue(Call, i + 1); - Value *Ptr = Builder.CreateConstGEP1_32(Ops[2], i * 16); + Value *Ptr = Builder.CreateConstGEP1_32(Int8Ty, Ops[2], i * 16); Ptr = Builder.CreateBitCast( Ptr, llvm::PointerType::getUnqual(Extract->getType())); Builder.CreateAlignedStore(Extract, Ptr, Align(1)); @@ -14751,7 +14793,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, for (int i = 0; i < 7; ++i) { Value *Extract = Builder.CreateExtractValue(Call, i + 1); - Value *Ptr = Builder.CreateConstGEP1_32(Ops[3], i * 16); + Value *Ptr = Builder.CreateConstGEP1_32(Int8Ty, Ops[3], i * 16); Ptr = Builder.CreateBitCast( Ptr, llvm::PointerType::getUnqual(Extract->getType())); Builder.CreateAlignedStore(Extract, Ptr, Align(1)); @@ -14839,7 +14881,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *InOps[9]; InOps[0] = Ops[2]; for (int i = 0; i != 8; ++i) { - Value *Ptr = Builder.CreateConstGEP1_32(Ops[1], i); + Value *Ptr = Builder.CreateConstGEP1_32(Ty, Ops[1], i); InOps[i + 1] = Builder.CreateAlignedLoad(Ty, Ptr, Align(16)); } @@ -14857,7 +14899,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Builder.SetInsertPoint(NoError); for (int i = 0; i != 8; ++i) { Value *Extract = Builder.CreateExtractValue(Call, i + 1); - Value *Ptr = Builder.CreateConstGEP1_32(Ops[0], i); + Value *Ptr = Builder.CreateConstGEP1_32(Extract->getType(), Ops[0], i); Builder.CreateAlignedStore(Extract, Ptr, Align(16)); } Builder.CreateBr(End); @@ -14866,7 +14908,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, for (int i = 0; i != 8; ++i) { Value *Out = Builder.CreateExtractValue(Call, i + 1); Constant *Zero = llvm::Constant::getNullValue(Out->getType()); - Value *Ptr = Builder.CreateConstGEP1_32(Ops[0], i); + Value *Ptr = Builder.CreateConstGEP1_32(Out->getType(), Ops[0], i); Builder.CreateAlignedStore(Zero, Ptr, Align(16)); } Builder.CreateBr(End); @@ -14914,7 +14956,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Ops[0] = Builder.CreateBitCast(Ops[0], Int8PtrTy); }else { Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy); - Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]); + Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]); Ops.pop_back(); } @@ -14982,7 +15024,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy); }else { Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy); - Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]); + Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]); Ops.pop_back(); } @@ -15138,6 +15180,45 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, else return Builder.CreateSub(Ops[0], Ops[1], "vsubuqm"); } + // Rotate and insert under mask operation. + // __rldimi(rs, is, shift, mask) + // (rotl64(rs, shift) & mask) | (is & ~mask) + // __rlwimi(rs, is, shift, mask) + // (rotl(rs, shift) & mask) | (is & ~mask) + case PPC::BI__builtin_ppc_rldimi: + case PPC::BI__builtin_ppc_rlwimi: { + llvm::Type *Ty = Ops[0]->getType(); + Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty); + if (BuiltinID == PPC::BI__builtin_ppc_rldimi) + Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty); + Value *Shift = Builder.CreateCall(F, {Ops[0], Ops[0], Ops[2]}); + Value *X = Builder.CreateAnd(Shift, Ops[3]); + Value *Y = Builder.CreateAnd(Ops[1], Builder.CreateNot(Ops[3])); + return Builder.CreateOr(X, Y); + } + // Rotate and insert under mask operation. + // __rlwnm(rs, shift, mask) + // rotl(rs, shift) & mask + case PPC::BI__builtin_ppc_rlwnm: { + llvm::Type *Ty = Ops[0]->getType(); + Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty); + Value *Shift = Builder.CreateCall(F, {Ops[0], Ops[0], Ops[1]}); + return Builder.CreateAnd(Shift, Ops[2]); + } + case PPC::BI__builtin_ppc_poppar4: + case PPC::BI__builtin_ppc_poppar8: { + llvm::Type *ArgType = Ops[0]->getType(); + Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType); + Value *Tmp = Builder.CreateCall(F, Ops[0]); + + llvm::Type *ResultType = ConvertType(E->getType()); + Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1)); + if (Result->getType() != ResultType) + Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, + "cast"); + return Result; + } + // Copy sign case PPC::BI__builtin_vsx_xvcpsgnsp: case PPC::BI__builtin_vsx_xvcpsgndp: { @@ -15483,10 +15564,10 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, if (BuiltinID == PPC::BI__builtin_vsx_lxvp || BuiltinID == PPC::BI__builtin_mma_lxvp) { Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy); - Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]); + Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]); } else { Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy); - Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]); + Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]); } Ops.pop_back(); llvm::Function *F = CGM.getIntrinsic(ID); @@ -15538,6 +15619,22 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, llvm::AtomicOrdering::Monotonic); } + case PPC::BI__builtin_ppc_ldarx: + case PPC::BI__builtin_ppc_lwarx: + return emitPPCLoadReserveIntrinsic(*this, BuiltinID, E); + case PPC::BI__builtin_ppc_popcntb: { + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + llvm::Type *ArgType = ArgValue->getType(); + Function *F = CGM.getIntrinsic(Intrinsic::ppc_popcntb, {ArgType, ArgType}); + return Builder.CreateCall(F, Ops, "popcntb"); + } + case PPC::BI__builtin_ppc_mtfsf: { + // The builtin takes a uint32 that needs to be cast to an + // f64 to be passed to the intrinsic. + Value *Cast = Builder.CreateUIToFP(Ops[1], DoubleTy); + llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtfsf); + return Builder.CreateCall(F, {Ops[0], Cast}, ""); + } } } @@ -15568,7 +15665,7 @@ Value *EmitAMDGPUWorkGroupSize(CodeGenFunction &CGF, unsigned Index) { auto *DP = EmitAMDGPUDispatchPtr(CGF); // Indexing the HSA kernel_dispatch_packet struct. auto *Offset = llvm::ConstantInt::get(CGF.Int32Ty, XOffset + Index * 2); - auto *GEP = CGF.Builder.CreateGEP(DP, Offset); + auto *GEP = CGF.Builder.CreateGEP(CGF.Int8Ty, DP, Offset); auto *DstTy = CGF.Int16Ty->getPointerTo(GEP->getType()->getPointerAddressSpace()); auto *Cast = CGF.Builder.CreateBitCast(GEP, DstTy); @@ -15588,7 +15685,7 @@ Value *EmitAMDGPUGridSize(CodeGenFunction &CGF, unsigned Index) { auto *DP = EmitAMDGPUDispatchPtr(CGF); // Indexing the HSA kernel_dispatch_packet struct. auto *Offset = llvm::ConstantInt::get(CGF.Int32Ty, XOffset + Index * 4); - auto *GEP = CGF.Builder.CreateGEP(DP, Offset); + auto *GEP = CGF.Builder.CreateGEP(CGF.Int8Ty, DP, Offset); auto *DstTy = CGF.Int32Ty->getPointerTo(GEP->getType()->getPointerAddressSpace()); auto *Cast = CGF.Builder.CreateBitCast(GEP, DstTy); @@ -16562,9 +16659,18 @@ static NVPTXMmaInfo getNVPTXMmaInfo(unsigned BuiltinID) { 0, \ 0 // b1 MMA does not support .satfinite. -#define MMA_VARIANTS_B1(geom, type) \ +#define MMA_VARIANTS_B1_XOR(geom, type) \ + 0, \ + Intrinsic::nvvm_wmma_##geom##_mma_xor_popc_row_col_##type, \ + 0, \ 0, \ - Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \ + 0, \ + 0, \ + 0, \ + 0 +#define MMA_VARIANTS_B1_AND(geom, type) \ + 0, \ + Intrinsic::nvvm_wmma_##geom##_mma_and_popc_row_col_##type, \ 0, \ 0, \ 0, \ @@ -16621,7 +16727,9 @@ static NVPTXMmaInfo getNVPTXMmaInfo(unsigned BuiltinID) { case NVPTX::BI__imma_m8n8k32_mma_u4: return {1, 1, 2, 2, {{MMA_VARIANTS_I4(m8n8k32, u4)}}}; case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1: - return {1, 1, 2, 2, {{MMA_VARIANTS_B1(m8n8k128, b1)}}}; + return {1, 1, 2, 2, {{MMA_VARIANTS_B1_XOR(m8n8k128, b1)}}}; + case NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1: + return {1, 1, 2, 2, {{MMA_VARIANTS_B1_AND(m8n8k128, b1)}}}; // Double MMA case NVPTX::BI__dmma_m8n8k4_mma_f64: @@ -16642,7 +16750,8 @@ static NVPTXMmaInfo getNVPTXMmaInfo(unsigned BuiltinID) { #undef MMA_VARIANTS #undef MMA_SATF_VARIANTS #undef MMA_VARIANTS_I4 -#undef MMA_VARIANTS_B1 +#undef MMA_VARIANTS_B1_AND +#undef MMA_VARIANTS_B1_XOR } } // namespace @@ -16978,7 +17087,7 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), Dst.getElementType()), - Builder.CreateGEP(Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); } @@ -17051,6 +17160,7 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { case NVPTX::BI__imma_m8n8k32_mma_s4: case NVPTX::BI__imma_m8n8k32_mma_u4: case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1: + case NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1: case NVPTX::BI__dmma_m8n8k4_mma_f64: case NVPTX::BI__mma_bf16_m16n16k16_mma_f32: case NVPTX::BI__mma_bf16_m8n32k16_mma_f32: @@ -17068,7 +17178,8 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (Layout < 0 || Layout > 3) return nullptr; llvm::APSInt SatfArg; - if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1) + if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1 || + BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1) SatfArg = 0; // .b1 does not have satf argument. else if (Optional OptSatfArg = E->getArg(5)->getIntegerConstantExpr(getContext())) @@ -17119,7 +17230,8 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { for (unsigned i = 0; i < MI.NumEltsD; ++i) Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)), + Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); return Result; } @@ -17203,7 +17315,7 @@ RValue CodeGenFunction::EmitBuiltinAlignTo(const CallExpr *E, bool AlignUp) { // can use an inbounds GEP to enable better optimization. Value *Base = EmitCastToVoidPtr(Args.Src); if (getLangOpts().isSignedOverflowDefined()) - Result = Builder.CreateGEP(Base, Difference, "aligned_result"); + Result = Builder.CreateGEP(Int8Ty, Base, Difference, "aligned_result"); else Result = EmitCheckedInBoundsGEP(Base, Difference, /*SignedIndices=*/true, @@ -17729,11 +17841,6 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Builder.getInt32(2), Builder.getInt32(3)}); return Builder.CreateShuffleVector(Trunc, Splat, ConcatMask); } - case WebAssembly::BI__builtin_wasm_demote_zero_f64x2_f32x4: { - Value *Vec = EmitScalarExpr(E->getArg(0)); - Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_demote_zero); - return Builder.CreateCall(Callee, Vec); - } case WebAssembly::BI__builtin_wasm_load32_zero: { Value *Ptr = EmitScalarExpr(E->getArg(0)); Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_load32_zero); @@ -17744,52 +17851,6 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_load64_zero); return Builder.CreateCall(Callee, {Ptr}); } - case WebAssembly::BI__builtin_wasm_load8_lane: - case WebAssembly::BI__builtin_wasm_load16_lane: - case WebAssembly::BI__builtin_wasm_load32_lane: - case WebAssembly::BI__builtin_wasm_load64_lane: - case WebAssembly::BI__builtin_wasm_store8_lane: - case WebAssembly::BI__builtin_wasm_store16_lane: - case WebAssembly::BI__builtin_wasm_store32_lane: - case WebAssembly::BI__builtin_wasm_store64_lane: { - Value *Ptr = EmitScalarExpr(E->getArg(0)); - Value *Vec = EmitScalarExpr(E->getArg(1)); - Optional LaneIdxConst = - E->getArg(2)->getIntegerConstantExpr(getContext()); - assert(LaneIdxConst && "Constant arg isn't actually constant?"); - Value *LaneIdx = llvm::ConstantInt::get(getLLVMContext(), *LaneIdxConst); - unsigned IntNo; - switch (BuiltinID) { - case WebAssembly::BI__builtin_wasm_load8_lane: - IntNo = Intrinsic::wasm_load8_lane; - break; - case WebAssembly::BI__builtin_wasm_load16_lane: - IntNo = Intrinsic::wasm_load16_lane; - break; - case WebAssembly::BI__builtin_wasm_load32_lane: - IntNo = Intrinsic::wasm_load32_lane; - break; - case WebAssembly::BI__builtin_wasm_load64_lane: - IntNo = Intrinsic::wasm_load64_lane; - break; - case WebAssembly::BI__builtin_wasm_store8_lane: - IntNo = Intrinsic::wasm_store8_lane; - break; - case WebAssembly::BI__builtin_wasm_store16_lane: - IntNo = Intrinsic::wasm_store16_lane; - break; - case WebAssembly::BI__builtin_wasm_store32_lane: - IntNo = Intrinsic::wasm_store32_lane; - break; - case WebAssembly::BI__builtin_wasm_store64_lane: - IntNo = Intrinsic::wasm_store64_lane; - break; - default: - llvm_unreachable("unexpected builtin ID"); - } - Function *Callee = CGM.getIntrinsic(IntNo); - return Builder.CreateCall(Callee, {Ptr, Vec, LaneIdx}); - } case WebAssembly::BI__builtin_wasm_shuffle_i8x16: { Value *Ops[18]; size_t OpIdx = 0; diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index bfd2c16c12827..88030fee501be 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -326,7 +326,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, VoidPtrTy); CGF.Builder.CreateDefaultAlignedStore( - VoidVarPtr, CGF.Builder.CreateConstGEP1_32(KernelArgs.getPointer(), i)); + VoidVarPtr, + CGF.Builder.CreateConstGEP1_32(VoidPtrTy, KernelArgs.getPointer(), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 641740c37a68a..86f548191d653 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -262,7 +262,7 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF, VTableIndex += VTLayout.getVTableOffset(AddressPoint.VTableIndex) + AddressPoint.AddressPointIndex; llvm::Value *VFuncPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); + CGF.Builder.CreateConstInBoundsGEP1_64(Ty, VTable, VTableIndex, "vfnkxt"); llvm::Value *VFunc = CGF.Builder.CreateAlignedLoad( Ty, VFuncPtr, llvm::Align(CGF.PointerAlignInBytes)); CGCallee Callee(GD, VFunc); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 3551c5e51f3a1..9895a23b70938 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -467,8 +467,6 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, const CXXRecordDecl *RD = cast(CurCodeDecl)->getParent(); const CXXRecordDecl *Base = cast(GD.getDecl())->getParent(); - llvm::Value *VTT; - uint64_t SubVTTIndex; if (Delegating) { @@ -494,15 +492,14 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { // A VTT parameter was passed to the constructor, use it. - VTT = LoadCXXVTT(); - VTT = Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex); + llvm::Value *VTT = LoadCXXVTT(); + return Builder.CreateConstInBoundsGEP1_64(VoidPtrTy, VTT, SubVTTIndex); } else { // We're the complete constructor, so get the VTT by name. - VTT = CGM.getVTables().GetAddrOfVTT(RD); - VTT = Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex); + llvm::GlobalValue *VTT = CGM.getVTables().GetAddrOfVTT(RD); + return Builder.CreateConstInBoundsGEP2_64( + VTT->getValueType(), VTT, 0, SubVTTIndex); } - - return VTT; } namespace { @@ -1744,6 +1741,7 @@ namespace { llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity()); llvm::Value *OffsetPtr = CGF.Builder.CreateGEP( + CGF.Int8Ty, CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 640da72ffd84b..77c426cf2f667 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -249,26 +249,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const { } StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { - assert(FD && "Invalid FunctionDecl!"); - IdentifierInfo *FII = FD->getIdentifier(); - FunctionTemplateSpecializationInfo *Info = - FD->getTemplateSpecializationInfo(); - - if (!Info && FII) - return FII->getName(); - - SmallString<128> NS; - llvm::raw_svector_ostream OS(NS); - FD->printName(OS); - - // Add any template specialization args. - if (Info) { - const TemplateArgumentList *TArgs = Info->TemplateArguments; - printTemplateArgumentList(OS, TArgs->asArray(), getPrintingPolicy()); - } - - // Copy this name on the side and use its reference. - return internString(OS.str()); + return internString(GetName(FD)); } StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { @@ -301,16 +282,8 @@ StringRef CGDebugInfo::getSelectorName(Selector S) { StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { if (isa(RD)) { - SmallString<128> Name; - llvm::raw_svector_ostream OS(Name); - PrintingPolicy PP = getPrintingPolicy(); - PP.PrintCanonicalTypes = true; - PP.SuppressInlineNamespace = false; - RD->getNameForDiagnostic(OS, PP, - /*Qualified*/ false); - // Copy this name on the side and use its reference. - return internString(Name); + return internString(GetName(RD)); } // quick optimization to avoid having to intern strings that are already @@ -4010,12 +3983,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, return; llvm::TimeTraceScope TimeScope("DebugFunction", [&]() { - std::string Name; - llvm::raw_string_ostream OS(Name); - if (const NamedDecl *ND = dyn_cast(D)) - ND->getNameForDiagnostic(OS, getPrintingPolicy(), - /*Qualified=*/true); - return Name; + return GetName(D, true); }); llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; @@ -4783,6 +4751,18 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( return GVE; } +std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const { + std::string Name; + llvm::raw_string_ostream OS(Name); + if (const NamedDecl *ND = dyn_cast(D)) { + PrintingPolicy PP = getPrintingPolicy(); + PP.PrintCanonicalTypes = true; + PP.SuppressInlineNamespace = false; + ND->getNameForDiagnostic(OS, PP, Qualified); + } + return Name; +} + void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); @@ -4790,11 +4770,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, return; llvm::TimeTraceScope TimeScope("DebugGlobalVariable", [&]() { - std::string Name; - llvm::raw_string_ostream OS(Name); - D->getNameForDiagnostic(OS, getPrintingPolicy(), - /*Qualified=*/true); - return Name; + return GetName(D, true); }); // If we already created a DIGlobalVariable for this declaration, just attach @@ -4858,11 +4834,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { if (VD->hasAttr()) return; llvm::TimeTraceScope TimeScope("DebugConstGlobalVariable", [&]() { - std::string Name; - llvm::raw_string_ostream OS(Name); - VD->getNameForDiagnostic(OS, getPrintingPolicy(), - /*Qualified=*/true); - return Name; + return GetName(VD, true); }); auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index de363b0d4918c..f3322fa91f57f 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -576,6 +576,8 @@ class CGDebugInfo { llvm::DIType *WrappedType; }; + std::string GetName(const Decl*, bool Qualified = false) const; + /// Build up structure info for the byref. See \a BuildByRefType. BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD, uint64_t *OffSet); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 16241990680b9..bd87abec0ab5c 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2294,8 +2294,9 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, // Shift the address back by one element. llvm::Value *negativeOne = llvm::ConstantInt::get(SizeTy, -1, true); - llvm::Value *element = Builder.CreateInBoundsGEP(elementPast, negativeOne, - "arraydestroy.element"); + llvm::Value *element = Builder.CreateInBoundsGEP( + elementPast->getType()->getPointerElementType(), elementPast, negativeOne, + "arraydestroy.element"); if (useEHCleanup) pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign, @@ -2335,8 +2336,11 @@ static void emitPartialArrayDestroy(CodeGenFunction &CGF, llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); SmallVector gepIndices(arrayDepth+1, zero); - begin = CGF.Builder.CreateInBoundsGEP(begin, gepIndices, "pad.arraybegin"); - end = CGF.Builder.CreateInBoundsGEP(end, gepIndices, "pad.arrayend"); + llvm::Type *elemTy = begin->getType()->getPointerElementType(); + begin = CGF.Builder.CreateInBoundsGEP( + elemTy, begin, gepIndices, "pad.arraybegin"); + end = CGF.Builder.CreateInBoundsGEP( + elemTy, end, gepIndices, "pad.arrayend"); } // Destroy the array. We don't ever need an EH cleanup because we diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index db97e4cd58f51..ae4e3c34b58e3 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -266,6 +266,58 @@ llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD, return fn; } +/// Create a stub function, suitable for being passed to __pt_atexit_np, +/// which passes the given address to the given destructor function. +llvm::Function *CodeGenFunction::createTLSAtExitStub( + const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr, + llvm::FunctionCallee &AtExit) { + SmallString<256> FnName; + { + llvm::raw_svector_ostream Out(FnName); + CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out); + } + + const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo( + getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false, + {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All); + + // Get the stub function type, int(*)(int,...). + llvm::FunctionType *StubTy = + llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy}, true); + + llvm::Function *DtorStub = CGM.CreateGlobalInitOrCleanUpFunction( + StubTy, FnName.str(), FI, D.getLocation()); + + CodeGenFunction CGF(CGM); + + FunctionArgList Args; + ImplicitParamDecl IPD(CGM.getContext(), CGM.getContext().IntTy, + ImplicitParamDecl::Other); + Args.push_back(&IPD); + QualType ResTy = CGM.getContext().IntTy; + + CGF.StartFunction(GlobalDecl(&D, DynamicInitKind::AtExit), ResTy, DtorStub, + FI, Args, D.getLocation(), D.getInit()->getExprLoc()); + + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(CGF); + + llvm::CallInst *call = CGF.Builder.CreateCall(Dtor, Addr); + + // Make sure the call and the callee agree on calling convention. + if (auto *DtorFn = dyn_cast( + Dtor.getCallee()->stripPointerCastsAndAliases())) + call->setCallingConv(DtorFn->getCallingConv()); + + // Return 0 from function + CGF.Builder.CreateStore(llvm::Constant::getNullValue(CGM.IntTy), + CGF.ReturnValue); + + CGF.FinishFunction(); + + return DtorStub; +} + /// Register a global destructor using the C atexit runtime function. void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD, llvm::FunctionCallee dtor, diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index e76b3f4554c72..ee6711c50ca3b 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -417,8 +417,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field); llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxStart[] = { Zero, Zero }; - llvm::Value *ArrayStart = - Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxStart, "arraystart"); + llvm::Value *ArrayStart = Builder.CreateInBoundsGEP( + ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart"); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; @@ -434,8 +434,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { ArrayType->getElementType())) { // End pointer. llvm::Value *IdxEnd[] = { Zero, Size }; - llvm::Value *ArrayEnd = - Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxEnd, "arrayend"); + llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( + ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { // Length. @@ -484,12 +484,14 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = - Builder.CreateInBoundsGEP(DestPtr.getPointer(), indices, "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP( + DestPtr.getElementType(), DestPtr.getPointer(), indices, + "arrayinit.begin"); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = DestPtr.getAlignment().alignmentOfArrayElement(elementSize); + llvm::Type *llvmElementType = begin->getType()->getPointerElementType(); // Consider initializing the array by copying from a global. For this to be // more efficient than per-element initialization, the size of the elements @@ -552,7 +554,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, for (uint64_t i = 0; i != NumInitElements; ++i) { // Advance to the next element. if (i > 0) { - element = Builder.CreateInBoundsGEP(element, one, "arrayinit.element"); + element = Builder.CreateInBoundsGEP( + llvmElementType, element, one, "arrayinit.element"); // Tell the cleanup that it needs to destroy up to this // element. TODO: some of these stores can be trivially @@ -581,14 +584,15 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // Advance to the start of the rest of the array. if (NumInitElements) { - element = Builder.CreateInBoundsGEP(element, one, "arrayinit.start"); + element = Builder.CreateInBoundsGEP( + llvmElementType, element, one, "arrayinit.start"); if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit); } // Compute the end of the array. - llvm::Value *end = Builder.CreateInBoundsGEP(begin, - llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements), - "arrayinit.end"); + llvm::Value *end = Builder.CreateInBoundsGEP( + llvmElementType, begin, + llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements), "arrayinit.end"); llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body"); @@ -616,8 +620,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, } // Move on to the next element. - llvm::Value *nextElement = - Builder.CreateInBoundsGEP(currentElement, one, "arrayinit.next"); + llvm::Value *nextElement = Builder.CreateInBoundsGEP( + llvmElementType, currentElement, one, "arrayinit.next"); // Tell the EH cleanup that we finished with the last element. if (endOfInit.isValid()) Builder.CreateStore(nextElement, endOfInit); @@ -1779,8 +1783,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP( + destPtr.getElementType(), destPtr.getPointer(), indices, + "arrayinit.begin"); // Prepare to special-case multidimensional array initialization: we avoid // emitting multiple destructor loops in that case. @@ -1802,7 +1807,8 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, llvm::PHINode *index = Builder.CreatePHI(zero->getType(), 2, "arrayinit.index"); index->addIncoming(zero, entryBB); - llvm::Value *element = Builder.CreateInBoundsGEP(begin, index); + llvm::Value *element = Builder.CreateInBoundsGEP( + begin->getType()->getPointerElementType(), begin, index); // Prepare for a cleanup. QualType::DestructionKind dtorKind = elementType.isDestructedType(); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 3673deb165605..cac580f542d0f 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2609,7 +2609,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *numElts = CGF.getVLASize(vla).NumElts; if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize"); if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, numElts, "vla.inc"); + value = Builder.CreateGEP(value->getType()->getPointerElementType(), + value, numElts, "vla.inc"); else value = CGF.EmitCheckedInBoundsGEP( value, numElts, /*SignedIndices=*/false, isSubtraction, @@ -2621,7 +2622,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, value = CGF.EmitCastToVoidPtr(value); if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, amt, "incdec.funcptr"); + value = Builder.CreateGEP(CGF.Int8Ty, value, amt, "incdec.funcptr"); else value = CGF.EmitCheckedInBoundsGEP(value, amt, /*SignedIndices=*/false, isSubtraction, E->getExprLoc(), @@ -2632,7 +2633,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } else { llvm::Value *amt = Builder.getInt32(amount); if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, amt, "incdec.ptr"); + value = Builder.CreateGEP(value->getType()->getPointerElementType(), + value, amt, "incdec.ptr"); else value = CGF.EmitCheckedInBoundsGEP(value, amt, /*SignedIndices=*/false, isSubtraction, E->getExprLoc(), @@ -2741,7 +2743,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity()); if (CGF.getLangOpts().isSignedOverflowDefined()) - value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); + value = Builder.CreateGEP(CGF.Int8Ty, value, sizeValue, "incdec.objptr"); else value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, /*SignedIndices=*/false, isSubtraction, @@ -3466,7 +3468,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, index = CGF.Builder.CreateMul(index, objectSize); Value *result = CGF.Builder.CreateBitCast(pointer, CGF.VoidPtrTy); - result = CGF.Builder.CreateGEP(result, index, "add.ptr"); + result = CGF.Builder.CreateGEP(CGF.Int8Ty, result, index, "add.ptr"); return CGF.Builder.CreateBitCast(result, pointer->getType()); } @@ -3482,7 +3484,9 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, // multiply. We suppress this if overflow is not undefined behavior. if (CGF.getLangOpts().isSignedOverflowDefined()) { index = CGF.Builder.CreateMul(index, numElements, "vla.index"); - pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr"); + pointer = CGF.Builder.CreateGEP( + pointer->getType()->getPointerElementType(), pointer, index, + "add.ptr"); } else { index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index"); pointer = @@ -3497,12 +3501,13 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, // future proof. if (elementType->isVoidType() || elementType->isFunctionType()) { Value *result = CGF.EmitCastToVoidPtr(pointer); - result = CGF.Builder.CreateGEP(result, index, "add.ptr"); + result = CGF.Builder.CreateGEP(CGF.Int8Ty, result, index, "add.ptr"); return CGF.Builder.CreateBitCast(result, pointer->getType()); } if (CGF.getLangOpts().isSignedOverflowDefined()) - return CGF.Builder.CreateGEP(pointer, index, "add.ptr"); + return CGF.Builder.CreateGEP( + pointer->getType()->getPointerElementType(), pointer, index, "add.ptr"); return CGF.EmitCheckedInBoundsGEP(pointer, index, isSigned, isSubtraction, op.E->getExprLoc(), "add.ptr"); @@ -5034,14 +5039,14 @@ Value * CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, ArrayRef IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name) { - Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name); + llvm::Type *PtrTy = Ptr->getType(); + Value *GEPVal = Builder.CreateInBoundsGEP( + PtrTy->getPointerElementType(), Ptr, IdxList, Name); // If the pointer overflow sanitizer isn't enabled, do nothing. if (!SanOpts.has(SanitizerKind::PointerOverflow)) return GEPVal; - llvm::Type *PtrTy = Ptr->getType(); - // Perform nullptr-and-offset check unless the nullptr is defined. bool PerformNullCheck = !NullPointerIsDefined( Builder.GetInsertBlock()->getParent(), PtrTy->getPointerAddressSpace()); diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index b865780ffe93c..937a0e8a3b692 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -925,10 +925,11 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, IvarSize = TInfo.Width; IvarAlignment = TInfo.Align; - // If we have a copy property, we always have to use getProperty/setProperty. - // TODO: we could actually use setProperty and an expression for non-atomics. + // If we have a copy property, we always have to use setProperty. + // If the property is atomic we need to use getProperty, but in + // the nonatomic case we can just use expression. if (IsCopy) { - Kind = GetSetProperty; + Kind = IsAtomic ? GetSetProperty : SetPropertyAndExpressionGet; return; } @@ -1903,8 +1904,9 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ Builder.CreateLoad(StateItemsPtr, "stateitems"); // Fetch the value at the current index from the buffer. - llvm::Value *CurrentItemPtr = - Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr"); + llvm::Value *CurrentItemPtr = Builder.CreateGEP( + EnumStateItems->getType()->getPointerElementType(), EnumStateItems, index, + "currentitem.ptr"); llvm::Value *CurrentItem = Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign()); diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index 9e47dbf7bdf1e..3f361f4e79317 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -945,7 +945,8 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { /// Generate the name of a symbol for a reference to a class. Accesses to /// classes should be indirected via this. - typedef std::pair> EarlyInitPair; + typedef std::pair> + EarlyInitPair; std::vector EarlyInitList; std::string SymbolForClassRef(StringRef Name, bool isWeak) { @@ -1096,7 +1097,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { } } } - auto *ObjCStrGV = + llvm::GlobalVariable *ObjCStrGV = Fields.finishAndCreateGlobal( isNamed ? StringRef(StringName) : ".objc_string", Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage @@ -1107,7 +1108,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility); } if (CGM.getTriple().isOSBinFormatCOFF()) { - std::pair v{ObjCStrGV, 0}; + std::pair v{ObjCStrGV, 0}; EarlyInitList.emplace_back(Sym, v); } llvm::Constant *ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStrGV, IdTy); @@ -1654,9 +1655,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { for (const auto &lateInit : EarlyInitList) { auto *global = TheModule.getGlobalVariable(lateInit.first); if (global) { + llvm::GlobalVariable *GV = lateInit.second.first; b.CreateAlignedStore( global, - b.CreateStructGEP(lateInit.second.first, lateInit.second.second), + b.CreateStructGEP(GV->getValueType(), GV, lateInit.second.second), CGM.getPointerAlign().getAsAlign()); } } @@ -1938,7 +1940,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { // struct objc_property_list *properties classFields.add(GeneratePropertyList(OID, classDecl)); - auto *classStruct = + llvm::GlobalVariable *classStruct = classFields.finishAndCreateGlobal(SymbolForClass(className), CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage); @@ -1949,12 +1951,12 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { if (IsCOFF) { // we can't import a class struct. if (OID->getClassInterface()->hasAttr()) { - cast(classStruct)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); cast(classRefSymbol)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); } if (SuperClass) { - std::pair v{classStruct, 1}; + std::pair v{classStruct, 1}; EarlyInitList.emplace_back(std::string(SuperClass->getName()), std::move(v)); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 8b04629883453..a9f7b0906f65a 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -698,7 +698,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, SrcBegin = SrcAddr.getPointer(); llvm::Value *DestBegin = DestAddr.getPointer(); // Cast from pointer to array type to pointer to single element. - llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); + llvm::Value *DestEnd = + CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); @@ -743,13 +744,15 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, if (DRD) { // Shift the address forward by one element. llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( - SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); + SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1, + "omp.arraycpy.dest.element"); SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); } // Shift the address forward by one element. llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( - DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); + DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1, + "omp.arraycpy.dest.element"); // Check whether we've reached the end. llvm::Value *Done = CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); @@ -1010,13 +1013,14 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, LValue BaseLValue = loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), OriginalBaseLValue); + Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( - BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); + BaseLValue.getPointer(CGF), SharedAddr.getPointer()); llvm::Value *PrivatePointer = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.getPointer(), - SharedAddresses[N].first.getAddress(CGF).getType()); - llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); + PrivateAddr.getPointer(), SharedAddr.getType()); + llvm::Value *Ptr = CGF.Builder.CreateGEP( + SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), OriginalBaseLValue.getAddress(CGF).getType(), @@ -4155,8 +4159,9 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { dyn_cast(E->IgnoreParenImpCasts())) { LValue UpAddrLVal = CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); - llvm::Value *UpAddr = - CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1); + Address UpAddrAddress = UpAddrLVal.getAddress(CGF); + llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( + UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); @@ -4471,7 +4476,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, std::tie(Addr, Size) = getPointerAndSize(CGF, E); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); LValue Base = CGF.MakeAddrLValue( - Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx), + Address(CGF.Builder.CreateGEP(AffinitiesArray.getElementType(), + AffinitiesArray.getPointer(), Idx), AffinitiesArray.getAlignment()), KmpTaskAffinityInfoTy); // affs[i].base_addr = &; @@ -4638,7 +4644,7 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getPointer(), + Addr.getElementType(), Addr.getPointer(), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, @@ -4678,7 +4684,8 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue &PosLVal = *Pos.get(); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( - Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx), + Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(), + DependenciesArray.getPointer(), Idx), DependenciesArray.getAlignment()), KmpDependInfoTy); } @@ -4738,7 +4745,7 @@ emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getPointer(), + Addr.getElementType(), Addr.getPointer(), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, @@ -4799,7 +4806,7 @@ static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, // Get number of elements in a single depobj. llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getPointer(), + Addr.getElementType(), Addr.getPointer(), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, @@ -4816,7 +4823,8 @@ static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Address DepAddr = - Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos), + Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(), + DependenciesArray.getPointer(), Pos), DependenciesArray.getAlignment()); CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); @@ -5044,7 +5052,7 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getPointer(), + Addr.getElementType(), Addr.getPointer(), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, CGF.VoidPtrTy); @@ -5074,7 +5082,8 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Begin = Base.getAddress(CGF); // Cast from pointer to array type to pointer to single element. - llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); + llvm::Value *End = CGF.Builder.CreateGEP( + Begin.getElementType(), Begin.getPointer(), NumDeps); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); @@ -5337,7 +5346,8 @@ static void EmitOMPAggregateReduction( llvm::Value *RHSBegin = RHSAddr.getPointer(); llvm::Value *LHSBegin = LHSAddr.getPointer(); // Cast from pointer to array type to pointer to single element. - llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); + llvm::Value *LHSEnd = + CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); @@ -5375,9 +5385,11 @@ static void EmitOMPAggregateReduction( // Shift the address forward by one element. llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( - LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); + LHSAddr.getElementType(), LHSElementPHI, /*Idx0=*/1, + "omp.arraycpy.dest.element"); llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( - RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); + RHSAddr.getElementType(), RHSElementPHI, /*Idx0=*/1, + "omp.arraycpy.src.element"); // Check whether we've reached the end. llvm::Value *Done = CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); @@ -8728,7 +8740,8 @@ class MappableExprsHandler { CombinedInfo.Mappers.push_back(nullptr); // Size is (addr of {highest+1} element) - (addr of lowest element) llvm::Value *HB = HBAddr.getPointer(); - llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); + llvm::Value *HAddr = + CGF.Builder.CreateConstGEP1_32(HBAddr.getElementType(), HB, /*Idx0=*/1); llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); @@ -9741,7 +9754,8 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); - llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); + llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP( + PtrBegin->getType()->getPointerElementType(), PtrBegin, Size); llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, C.getPointerType(Int64Ty), Loc); @@ -9898,8 +9912,9 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, // Update the pointer to point to the next element that needs to be mapped, // and check whether we have mapped all elements. + llvm::Type *ElemTy = PtrPHI->getType()->getPointerElementType(); llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( - PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); + ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); PtrPHI->addIncoming(PtrNext, LastBB); llvm::Value *IsDone = MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 1cb367ec71885..1ad1460be7112 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -2172,7 +2172,8 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, Address ElemPtr = Address(ElemPtrPtr, Align); ElemPtr = Bld.CreateElementBitCast(ElemPtr, CopyType); if (NumIters > 1) { - ElemPtr = Address(Bld.CreateGEP(ElemPtr.getPointer(), Cnt), + ElemPtr = Address(Bld.CreateGEP(ElemPtr.getElementType(), + ElemPtr.getPointer(), Cnt), ElemPtr.getAlignment()); } @@ -2241,7 +2242,8 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, Address TargetElemPtr = Address(TargetElemPtrVal, Align); TargetElemPtr = Bld.CreateElementBitCast(TargetElemPtr, CopyType); if (NumIters > 1) { - TargetElemPtr = Address(Bld.CreateGEP(TargetElemPtr.getPointer(), Cnt), + TargetElemPtr = Address(Bld.CreateGEP(TargetElemPtr.getElementType(), + TargetElemPtr.getPointer(), Cnt), TargetElemPtr.getAlignment()); } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 1057e9aa8a723..486b48bca0a62 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -698,7 +698,8 @@ void CodeGenFunction::EmitOMPAggregateAssign( llvm::Value *SrcBegin = SrcAddr.getPointer(); llvm::Value *DestBegin = DestAddr.getPointer(); // Cast from pointer to array type to pointer to single element. - llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements); + llvm::Value *DestEnd = + Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body"); llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done"); @@ -731,9 +732,11 @@ void CodeGenFunction::EmitOMPAggregateAssign( // Shift the address forward by one element. llvm::Value *DestElementNext = Builder.CreateConstGEP1_32( - DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); + DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1, + "omp.arraycpy.dest.element"); llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32( - SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); + SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1, + "omp.arraycpy.src.element"); // Check whether we've reached the end. llvm::Value *Done = Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f1aed1c9b06b1..2a7e0865b08a9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4368,6 +4368,11 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr); + llvm::Function *createTLSAtExitStub(const VarDecl &VD, + llvm::FunctionCallee Dtor, + llvm::Constant *Addr, + llvm::FunctionCallee &AtExit); + /// Call atexit() with a function that passes the given argument to /// the given function. void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn, diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index d6d5d74e8aaad..86871ece921d8 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -337,14 +337,20 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { /// Determine whether we will definitely emit this variable with a constant /// initializer, either because the language semantics demand it or because /// we know that the initializer is a constant. - bool isEmittedWithConstantInitializer(const VarDecl *VD) const { + // For weak definitions, any initializer available in the current translation + // is not necessarily reflective of the initializer used; such initializers + // are ignored unless if InspectInitForWeakDef is true. + bool + isEmittedWithConstantInitializer(const VarDecl *VD, + bool InspectInitForWeakDef = false) const { VD = VD->getMostRecentDecl(); if (VD->hasAttr()) return true; // All later checks examine the initializer specified on the variable. If // the variable is weak, such examination would not be correct. - if (VD->isWeak() || VD->hasAttr()) + if (!InspectInitForWeakDef && + (VD->isWeak() || VD->hasAttr())) return false; const VarDecl *InitDecl = VD->getInitializingDeclaration(); @@ -720,7 +726,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( } if (ShouldEmitVFEInfo) { - llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); + llvm::Value *VFPAddr = + Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset); // If doing VFE, load from the vtable with a type.checked.load intrinsic // call. Note that we use the GEP to calculate the address to load from @@ -738,7 +745,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // When not doing VFE, emit a normal load, as it allows more // optimisations than type.checked.load. if (ShouldEmitCFICheck || ShouldEmitWPDInfo) { - llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset); + llvm::Value *VFPAddr = + Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset); CheckResult = Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::type_test), {Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId}); @@ -751,7 +759,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( {VTable, VTableOffset}); VirtualFn = CGF.Builder.CreateBitCast(VirtualFn, FTy->getPointerTo()); } else { - llvm::Value *VFPAddr = CGF.Builder.CreateGEP(VTable, VTableOffset); + llvm::Value *VFPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset); VFPAddr = CGF.Builder.CreateBitCast( VFPAddr, FTy->getPointerTo()->getPointerTo()); VirtualFn = CGF.Builder.CreateAlignedLoad( @@ -1254,7 +1263,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // Track back to entry -2 and pull out the offset there. llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64( - VTable, -2, "complete-offset.ptr"); + CGF.IntPtrTy, VTable, -2, "complete-offset.ptr"); llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(CGF.IntPtrTy, OffsetPtr, CGF.getPointerAlign()); // Apply the offset. @@ -1466,7 +1475,8 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF, Value = CGF.Builder.CreateBitCast(Value, StdTypeInfoPtrTy->getPointerTo()); } else { // Load the type info. - Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL); + Value = + CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL); } return CGF.Builder.CreateAlignedLoad(StdTypeInfoPtrTy, Value, CGF.getPointerAlign()); @@ -1547,7 +1557,8 @@ llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl); // Get the offset-to-top from the vtable. - OffsetToTop = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL); + OffsetToTop = + CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL); OffsetToTop = CGF.Builder.CreateAlignedLoad( PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); } @@ -1576,8 +1587,9 @@ ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl); llvm::Value *VBaseOffsetPtr = - CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(), - "vbase.offset.ptr"); + CGF.Builder.CreateConstGEP1_64( + CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(), + "vbase.offset.ptr"); llvm::Value *VBaseOffset; if (CGM.getItaniumVTableContext().isRelativeLayout()) { @@ -1871,7 +1883,8 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( /// Load the VTT. llvm::Value *VTT = CGF.LoadCXXVTT(); if (VirtualPointerIndex) - VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex); + VTT = CGF.Builder.CreateConstInBoundsGEP1_64( + CGF.VoidPtrTy, VTT, VirtualPointerIndex); // And load the address point from the VTT. return CGF.Builder.CreateAlignedLoad(CGF.VoidPtrTy, VTT, @@ -1942,9 +1955,10 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, Address This, llvm::Type *Ty, SourceLocation Loc) { + llvm::Type *TyPtr = Ty->getPointerTo(); auto *MethodDecl = cast(GD.getDecl()); llvm::Value *VTable = CGF.GetVTablePtr( - This, Ty->getPointerTo()->getPointerTo(), MethodDecl->getParent()); + This, TyPtr->getPointerTo(), MethodDecl->getParent()); uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); llvm::Value *VFunc; @@ -1961,14 +1975,14 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *Load = CGF.Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}), {VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)}); - VFuncLoad = CGF.Builder.CreateBitCast(Load, Ty->getPointerTo()); + VFuncLoad = CGF.Builder.CreateBitCast(Load, TyPtr); } else { VTable = - CGF.Builder.CreateBitCast(VTable, Ty->getPointerTo()->getPointerTo()); - llvm::Value *VTableSlotPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn"); + CGF.Builder.CreateBitCast(VTable, TyPtr->getPointerTo()); + llvm::Value *VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64( + TyPtr, VTable, VTableIndex, "vfn"); VFuncLoad = - CGF.Builder.CreateAlignedLoad(Ty->getPointerTo(), VTableSlotPtr, + CGF.Builder.CreateAlignedLoad(TyPtr, VTableSlotPtr, CGF.getPointerAlign()); } @@ -2107,8 +2121,8 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr); llvm::Value *Offset; - llvm::Value *OffsetPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment); + llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64( + CGF.Int8Ty, VTablePtr, VirtualAdjustment); if (CGF.CGM.getItaniumVTableContext().isRelativeLayout()) { // Load the adjustment offset from the vtable as a 32-bit int. OffsetPtr = @@ -2137,7 +2151,7 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, // In a derived-to-base conversion, the non-virtual adjustment is // applied second. if (NonVirtualAdjustment && IsReturnAdjustment) { - ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ResultPtr, + ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr, NonVirtualAdjustment); } @@ -2551,6 +2565,8 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, llvm::FunctionCallee dtor, llvm::Constant *addr, bool TLS) { + assert(!CGF.getTarget().getTriple().isOSAIX() && + "unexpected call to emitGlobalDtorWithCXAAtExit"); assert((TLS || CGF.getTypes().getCodeGenOpts().CXAAtExit) && "__cxa_atexit is disabled"); const char *Name = "__cxa_atexit"; @@ -2944,6 +2960,33 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( } llvm::LLVMContext &Context = CGM.getModule().getContext(); + + // The linker on AIX is not happy with missing weak symbols. However, + // other TUs will not know whether the initialization routine exists + // so create an empty, init function to satisfy the linker. + // This is needed whenever a thread wrapper function is not used, and + // also when the symbol is weak. + if (CGM.getTriple().isOSAIX() && VD->hasDefinition() && + isEmittedWithConstantInitializer(VD, true) && + !VD->needsDestruction(getContext())) { + // Init should be null. If it were non-null, then the logic above would + // either be defining the function to be an alias or declaring the + // function with the expectation that the definition of the variable + // is elsewhere. + assert(Init == nullptr && "Expected Init to be null."); + + llvm::Function *Func = llvm::Function::Create( + InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule()); + const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, + cast(Func), + /*IsThunk=*/false); + // Create a function body that just returns + llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func); + CGBuilderTy Builder(CGM, Entry); + Builder.CreateRetVoid(); + } + llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper); CGBuilderTy Builder(CGM, Entry); if (HasConstantInitialization) { @@ -2958,6 +3001,15 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); } } + } else if (CGM.getTriple().isOSAIX()) { + // On AIX, except if constinit and also neither of class type or of + // (possibly multi-dimensional) array of class type, thread_local vars + // will have init routines regardless of whether they are + // const-initialized. Since the routine is guaranteed to exist, we can + // unconditionally call it without testing for its existance. This + // avoids potentially unresolved weak symbols which the AIX linker + // isn't happy with. + Builder.CreateCall(InitFnTy, Init); } else { // Don't know whether we have an init function. Call it if it exists. llvm::Value *Have = Builder.CreateIsNotNull(Init); @@ -4449,7 +4501,8 @@ static void InitCatchParam(CodeGenFunction &CGF, // we have to skip past in order to reach the exception data. unsigned HeaderSize = CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException(); - AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize); + AdjustedExn = + CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize); // However, if we're catching a pointer-to-record type that won't // work, because the personality function might have adjusted @@ -4724,20 +4777,43 @@ WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, /// Register a global destructor as best as we know how. void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, - llvm::FunctionCallee dtor, - llvm::Constant *addr) { - if (D.getTLSKind() != VarDecl::TLS_None) - llvm::report_fatal_error("thread local storage not yet implemented on AIX"); + llvm::FunctionCallee Dtor, + llvm::Constant *Addr) { + if (D.getTLSKind() != VarDecl::TLS_None) { + // atexit routine expects "int(*)(int,...)" + llvm::FunctionType *FTy = + llvm::FunctionType::get(CGM.IntTy, CGM.IntTy, true); + llvm::PointerType *FpTy = FTy->getPointerTo(); + + // extern "C" int __pt_atexit_np(int flags, int(*)(int,...), ...); + llvm::FunctionType *AtExitTy = + llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, FpTy}, true); + + // Fetch the actual function. + llvm::FunctionCallee AtExit = + CGM.CreateRuntimeFunction(AtExitTy, "__pt_atexit_np"); + + // Create __dtor function for the var decl. + llvm::Function *DtorStub = CGF.createTLSAtExitStub(D, Dtor, Addr, AtExit); + + // Register above __dtor with atexit(). + // First param is flags and must be 0, second param is function ptr + llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy); + CGF.EmitNounwindRuntimeCall(AtExit, {NV, DtorStub}); + + // Cannot unregister TLS __dtor so done + return; + } // Create __dtor function for the var decl. - llvm::Function *dtorStub = CGF.createAtExitStub(D, dtor, addr); + llvm::Function *DtorStub = CGF.createAtExitStub(D, Dtor, Addr); // Register above __dtor with atexit(). - CGF.registerGlobalDtorWithAtExit(dtorStub); + CGF.registerGlobalDtorWithAtExit(DtorStub); // Emit __finalize function to unregister __dtor and (as appropriate) call // __dtor. - emitCXXStermFinalizer(D, dtorStub, addr); + emitCXXStermFinalizer(D, DtorStub, Addr); } void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub, diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 68f2828febe2b..990648b131fee 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1228,7 +1228,7 @@ void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers( llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(CGF.Int8Ty, Int8This, VBaseOffset); // vtorDisp is always the 32-bits before the vbase in the class layout. - VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4); + VtorDispPtr = Builder.CreateConstGEP1_32(CGF.Int8Ty, VtorDispPtr, -4); VtorDispPtr = Builder.CreateBitCast( VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr"); @@ -1951,7 +1951,7 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc); llvm::Value *VFuncPtr = - Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); + Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.Index, "vfn"); VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.getPointerAlign()); } @@ -2080,14 +2080,14 @@ MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD, // Load the vfptr and then callee from the vftable. The callee should have // adjusted 'this' so that the vfptr is at offset zero. + llvm::Type *ThunkPtrTy = ThunkTy->getPointerTo(); llvm::Value *VTable = CGF.GetVTablePtr( - getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->getParent()); + getThisAddress(CGF), ThunkPtrTy->getPointerTo(), MD->getParent()); - llvm::Value *VFuncPtr = - CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn"); + llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64( + ThunkPtrTy, VTable, ML.Index, "vfn"); llvm::Value *Callee = - CGF.Builder.CreateAlignedLoad(ThunkTy->getPointerTo(), VFuncPtr, - CGF.getPointerAlign()); + CGF.Builder.CreateAlignedLoad(ThunkPtrTy, VFuncPtr, CGF.getPointerAlign()); CGF.EmitMustTailThunk(MD, getThisValue(CGF), {ThunkTy, Callee}); @@ -2201,7 +2201,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); VtorDispPtr = CGF.Builder.CreateElementBitCast(VtorDispPtr, CGF.Int32Ty); llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getPointer(), + V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(), CGF.Builder.CreateNeg(VtorDisp)); // Unfortunately, having applied the vtordisp means that we no @@ -2227,7 +2227,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, // Non-virtual adjustment might result in a pointer outside the allocated // object, e.g. if the final overrider class is laid out after the virtual // base that declares a method in the most derived class. - V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual); + V = CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, V, TA.NonVirtual); } // Don't need to bitcast back, the call CodeGen will handle this. diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index f2bac305169fd..cec54c9608594 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -3966,8 +3966,8 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF, uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8; llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, (SizeInBytes + 7) & ~7); - overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset, - "overflow_arg_area.next"); + overflow_arg_area = CGF.Builder.CreateGEP(CGF.Int8Ty, overflow_arg_area, + Offset, "overflow_arg_area.next"); CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p); // AMD64-ABI 3.5.7p5: Step 11. Return the fetched type. @@ -4061,8 +4061,10 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, "Unexpected ABI info for mixed regs"); llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo); llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi); - llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegSaveArea, gp_offset); - llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegSaveArea, fp_offset); + llvm::Value *GPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset); + llvm::Value *FPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset); llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr; llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr; @@ -4081,7 +4083,7 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, RegAddr = CGF.Builder.CreateElementBitCast(Tmp, LTy); } else if (neededInt) { - RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, gp_offset), + RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), CharUnits::fromQuantity(8)); RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy); @@ -4099,7 +4101,7 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, } } else if (neededSSE == 1) { - RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset), + RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), CharUnits::fromQuantity(16)); RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy); } else { @@ -4110,7 +4112,8 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // to assume that the slots are 16-byte aligned, since the stack is // naturally 16-byte aligned and the prologue is expected to store // all the SSE registers to the RSA. - Address RegAddrLo = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset), + Address RegAddrLo = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, + fp_offset), CharUnits::fromQuantity(16)); Address RegAddrHi = CGF.Builder.CreateConstInBoundsByteGEP(RegAddrLo, @@ -7460,7 +7463,8 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV, + CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), + OverflowArgArea.getPointer(), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); @@ -7510,7 +7514,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr"); llvm::Value *RegSaveArea = CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area"); - Address RawRegAddr(CGF.Builder.CreateGEP(RegSaveArea, RegOffset, + Address RawRegAddr(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"), PaddedSize); Address RegAddr = @@ -7539,7 +7543,8 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV, + CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), + OverflowArgArea.getPointer(), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); CGF.EmitBranch(ContBlock); @@ -8471,7 +8476,7 @@ Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF, // Add offset to the current pointer to access the argument. __overflow_area_pointer = - CGF.Builder.CreateGEP(__overflow_area_pointer, Offset); + CGF.Builder.CreateGEP(CGF.Int8Ty, __overflow_area_pointer, Offset); llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty); @@ -8494,7 +8499,8 @@ Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF, uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4); __overflow_area_pointer = CGF.Builder.CreateGEP( - __overflow_area_pointer, llvm::ConstantInt::get(CGF.Int32Ty, Offset), + CGF.Int8Ty, __overflow_area_pointer, + llvm::ConstantInt::get(CGF.Int32Ty, Offset), "__overflow_area_pointer.next"); CGF.Builder.CreateStore(__overflow_area_pointer, __overflow_area_pointer_p); @@ -8525,7 +8531,7 @@ Address HexagonABIInfo::EmitVAArgForHexagon(CodeGenFunction &CGF, uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4); llvm::Value *NextAddr = Builder.CreateGEP( - Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next"); + CGF.Int8Ty, Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next"); Builder.CreateStore(NextAddr, VAListAddrAsBPP); return AddrTyped; @@ -8597,7 +8603,7 @@ Address HexagonABIInfo::EmitVAArgForHexagonLinux(CodeGenFunction &CGF, } llvm::Value *__new_saved_reg_area_pointer = - CGF.Builder.CreateGEP(__current_saved_reg_area_pointer, + CGF.Builder.CreateGEP(CGF.Int8Ty, __current_saved_reg_area_pointer, llvm::ConstantInt::get(CGF.Int32Ty, ArgSize), "__new_saved_reg_area_pointer"); @@ -8653,7 +8659,8 @@ Address HexagonABIInfo::EmitVAArgForHexagonLinux(CodeGenFunction &CGF, // Get the pointer for next argument in overflow area and store it // to overflow area pointer. llvm::Value *__new_overflow_area_pointer = CGF.Builder.CreateGEP( - __overflow_area_pointer, llvm::ConstantInt::get(CGF.Int32Ty, ArgSize), + CGF.Int8Ty, __overflow_area_pointer, + llvm::ConstantInt::get(CGF.Int32Ty, ArgSize), "__overflow_area_pointer.next"); CGF.Builder.CreateStore(__new_overflow_area_pointer, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index fb2ec73acaf4a..0fad8ee54c6c0 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3324,7 +3324,7 @@ class OffloadingActionBuilder final { StringRef getCanonicalOffloadArch(StringRef ArchStr) override { CudaArch Arch = StringToCudaArch(ArchStr); - if (Arch == CudaArch::UNKNOWN) { + if (Arch == CudaArch::UNKNOWN || !IsNVIDIAGpuArch(Arch)) { C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr; return StringRef(); } diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 68975aafcd370..8770fb1cf9fef 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -805,6 +805,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, options::OPT_fno_sanitize_address_poison_custom_array_cookie, AsanPoisonCustomArrayCookie); + AsanOutlineInstrumentation = + Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation, + options::OPT_fno_sanitize_address_outline_instrumentation, + AsanOutlineInstrumentation); + // As a workaround for a bug in gold 2.26 and earlier, dead stripping of // globals in ASan is disabled by default on ELF targets. // See https://sourceware.org/bugzilla/show_bug.cgi?id=19002 @@ -1118,6 +1123,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back("-asan-detect-invalid-pointer-sub"); } + if (AsanOutlineInstrumentation) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0"); + } + // Only pass the option to the frontend if the user requested, // otherwise the frontend will just use the codegen default. if (AsanDtorKind != llvm::AsanDtorKind::Invalid) { diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 35a57d52a7400..f3cda040c936b 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -451,6 +451,9 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC, if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid()) return "i686"; + if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32()) + return "x32"; + return llvm::Triple::getArchTypeName(TC.getArch()); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index df01fe9c93c5e..b483f5eb99f1e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -501,14 +501,6 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC, Default); } -static bool ShouldDisableDwarfDirectory(const ArgList &Args, - const ToolChain &TC) { - bool UseDwarfDirectory = - Args.hasFlag(options::OPT_fdwarf_directory_asm, - options::OPT_fno_dwarf_directory_asm, TC.useIntegratedAs()); - return !UseDwarfDirectory; -} - // Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases // to the corresponding DebugInfoKind. static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { @@ -4249,6 +4241,14 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D, } } + // To avoid join/split of directory+filename, the integrated assembler prefers + // the directory form of .file on all DWARF versions. GNU as doesn't allow the + // form before DWARF v5. + if (!Args.hasFlag(options::OPT_fdwarf_directory_asm, + options::OPT_fno_dwarf_directory_asm, + TC.useIntegratedAs() || EffectiveDWARFVersion >= 5)) + CmdArgs.push_back("-fno-dwarf-directory-asm"); + // Decide how to render forward declarations of template instantiations. // SCE wants full descriptions, others just get them in the name. if (DebuggerTuning == llvm::DebuggerKind::SCE) @@ -5944,9 +5944,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } - if (ShouldDisableDwarfDirectory(Args, TC)) - CmdArgs.push_back("-fno-dwarf-directory-asm"); - if (!ShouldEnableAutolink(Args, TC, JA)) CmdArgs.push_back("-fno-autolink"); @@ -6423,8 +6420,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ); if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling, - options::OPT_fno_pseudo_probe_for_profiling, false)) + options::OPT_fno_pseudo_probe_for_profiling, false)) { CmdArgs.push_back("-fpseudo-probe-for-profiling"); + // Enforce -funique-internal-linkage-names if it's not explicitly turned + // off. + if (Args.hasFlag(options::OPT_funique_internal_linkage_names, + options::OPT_fno_unique_internal_linkage_names, true)) + CmdArgs.push_back("-funique-internal-linkage-names"); + } } RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp index 8695330a7ec2d..4a4a881b4a25a 100644 --- a/clang/lib/Driver/ToolChains/HIP.cpp +++ b/clang/lib/Driver/ToolChains/HIP.cpp @@ -118,8 +118,7 @@ void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, // for backward compatibility. For code object version 4 and greater, the // offload kind in bundle ID is 'hipv4'. std::string OffloadKind = "hip"; - if (haveAMDGPUCodeObjectVersionArgument(C.getDriver(), Args) && - getAMDGPUCodeObjectVersion(C.getDriver(), Args) >= 4) + if (getAMDGPUCodeObjectVersion(C.getDriver(), Args) >= 4) OffloadKind = OffloadKind + "v4"; for (const auto &II : Inputs) { const auto* A = II.getAction(); diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 52717efd6d02f..7d4b67a611e7b 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -714,7 +714,7 @@ SanitizerMask Linux::getSupportedSanitizers() const { if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 || IsRISCV64 || IsSystemZ) Res |= SanitizerKind::Leak; - if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64) + if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ) Res |= SanitizerKind::Thread; if (IsX86_64) Res |= SanitizerKind::KernelMemory; diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp index 0b8c52096933d..075c1dc11b210 100644 --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -184,6 +184,7 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_u); ToolChain.AddFilePathLibArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e, options::OPT_s, diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 2b83ff4f78503..54e6c7d38e7de 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2476,6 +2476,14 @@ static bool isFunctionDeclarationName(const FormatToken &Current, if (Next->MatchingParen->Next && Next->MatchingParen->Next->is(TT_PointerOrReference)) return true; + // Check for K&R C function definitions, e.g.: + // int f(i) + // { + // return i + 1; + // } + if (Next->Next && Next->Next->is(tok::identifier) && + !(Next->MatchingParen->Next && Next->MatchingParen->Next->is(tok::semi))) + return true; for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen; Tok = Tok->Next) { if (Tok->is(TT_TypeDeclarationParen)) diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 4f92833e4229c..996783aa9cf4b 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -807,7 +807,8 @@ std::unique_ptr ASTUnit::LoadFromASTFile( if (ToLoad >= LoadASTOnly) AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), PP.getIdentifierTable(), PP.getSelectorTable(), - PP.getBuiltinInfo()); + PP.getBuiltinInfo(), + AST->getTranslationUnitKind()); DisableValidationForModuleKind disableValid = DisableValidationForModuleKind::None; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 95b8e03b805f4..41d2d5d4c4dbc 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -554,7 +554,7 @@ void CompilerInstance::createASTContext() { Preprocessor &PP = getPreprocessor(); auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(), PP.getIdentifierTable(), PP.getSelectorTable(), - PP.getBuiltinInfo()); + PP.getBuiltinInfo(), PP.TUKind); Context->InitBuiltinTypes(getTarget(), getAuxTarget()); setASTContext(Context); } @@ -1057,6 +1057,15 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, [](CompilerInstance &) {}) { llvm::TimeTraceScope TimeScope("Module Compile", ModuleName); + // Never compile a module that's already finalized - this would cause the + // existing module to be freed, causing crashes if it is later referenced + if (ImportingInstance.getModuleCache().isPCMFinal(ModuleFileName)) { + ImportingInstance.getDiagnostics().Report( + ImportLoc, diag::err_module_rebuild_finalized) + << ModuleName; + return false; + } + // Construct a compiler invocation for creating this module. auto Invocation = std::make_shared(ImportingInstance.getInvocation()); diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 382d40b2c0a99..8131f6005dc21 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -38,6 +38,7 @@ set(files avxvnniintrin.h bmi2intrin.h bmiintrin.h + builtins.h __clang_cuda_builtin_vars.h __clang_cuda_math.h __clang_cuda_cmath.h diff --git a/clang/lib/Headers/altivec.h b/clang/lib/Headers/altivec.h index c916017fad6af..862ec290e1c95 100644 --- a/clang/lib/Headers/altivec.h +++ b/clang/lib/Headers/altivec.h @@ -8386,11 +8386,7 @@ vec_vrlw(vector unsigned int __a, vector unsigned int __b) { /* vec_round */ static __inline__ vector float __ATTRS_o_ai vec_round(vector float __a) { -#ifdef __VSX__ - return __builtin_vsx_xvrspi(__a); -#else return __builtin_altivec_vrfin(__a); -#endif } #ifdef __VSX__ @@ -14898,8 +14894,7 @@ static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b, - (vector unsigned char)__a); + return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __b, (vector signed char)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a, @@ -14936,8 +14931,7 @@ static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b, - (vector unsigned short)__a); + return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __b, (vector signed short)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a, @@ -14973,8 +14967,7 @@ static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b, - (vector unsigned int)__a); + return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __b, (vector signed int)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a, @@ -15012,8 +15005,8 @@ static __inline__ int __ATTRS_o_ai vec_all_ge(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b, - (vector unsigned long long)__a); + return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __b, + (vector signed long long)__a); } static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a, @@ -15081,8 +15074,7 @@ static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a, - (vector unsigned char)__b); + return __builtin_altivec_vcmpgtsb_p(__CR6_LT, (vector signed char)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a, @@ -15119,8 +15111,7 @@ static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a, - (vector unsigned short)__b); + return __builtin_altivec_vcmpgtsh_p(__CR6_LT, (vector signed short)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a, @@ -15156,8 +15147,7 @@ static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a, - (vector unsigned int)__b); + return __builtin_altivec_vcmpgtsw_p(__CR6_LT, (vector signed int)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a, @@ -15195,8 +15185,8 @@ static __inline__ int __ATTRS_o_ai vec_all_gt(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a, - (vector unsigned long long)__b); + return __builtin_altivec_vcmpgtsd_p(__CR6_LT, (vector signed long long)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a, @@ -15271,8 +15261,7 @@ static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a, - (vector unsigned char)__b); + return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, (vector signed char)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a, @@ -15309,8 +15298,7 @@ static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a, - (vector unsigned short)__b); + return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, (vector signed short)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a, @@ -15346,8 +15334,7 @@ static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a, - (vector unsigned int)__b); + return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, (vector signed int)__a, __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a, @@ -15386,8 +15373,8 @@ static __inline__ int __ATTRS_o_ai vec_all_le(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a, - (vector unsigned long long)__b); + return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, (vector signed long long)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a, @@ -15455,8 +15442,7 @@ static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b, - (vector unsigned char)__a); + return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __b, (vector signed char)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a, @@ -15493,8 +15479,7 @@ static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b, - (vector unsigned short)__a); + return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __b, (vector signed short)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a, @@ -15530,8 +15515,7 @@ static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b, - (vector unsigned int)__a); + return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __b, (vector signed int)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a, @@ -15570,8 +15554,8 @@ static __inline__ int __ATTRS_o_ai vec_all_lt(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b, - (vector unsigned long long)__a); + return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __b, + (vector signed long long)__a); } static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a, @@ -16146,8 +16130,8 @@ static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b, - (vector unsigned char)__a); + return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __b, + (vector signed char)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a, @@ -16185,8 +16169,8 @@ static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b, - (vector unsigned short)__a); + return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __b, + (vector signed short)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a, @@ -16223,8 +16207,8 @@ static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b, - (vector unsigned int)__a); + return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __b, + (vector signed int)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a, @@ -16264,9 +16248,8 @@ static __inline__ int __ATTRS_o_ai vec_any_ge(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, - (vector unsigned long long)__b, - (vector unsigned long long)__a); + return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __b, + (vector signed long long)__a); } static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a, @@ -16337,8 +16320,8 @@ static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a, - (vector unsigned char)__b); + return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a, @@ -16376,8 +16359,8 @@ static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a, - (vector unsigned short)__b); + return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, (vector signed short)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a, @@ -16414,8 +16397,8 @@ static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a, - (vector unsigned int)__b); + return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, (vector signed int)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a, @@ -16455,9 +16438,8 @@ static __inline__ int __ATTRS_o_ai vec_any_gt(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, - (vector unsigned long long)__a, - (vector unsigned long long)__b); + return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, + (vector signed long long)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a, @@ -16528,8 +16510,8 @@ static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a, - (vector unsigned char)__b); + return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a, @@ -16567,8 +16549,8 @@ static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a, - (vector unsigned short)__b); + return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, (vector signed short)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a, @@ -16605,8 +16587,8 @@ static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a, - (vector unsigned int)__b); + return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, (vector signed int)__a, + __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a, @@ -16646,9 +16628,8 @@ static __inline__ int __ATTRS_o_ai vec_any_le(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV, - (vector unsigned long long)__a, - (vector unsigned long long)__b); + return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, + (vector signed long long)__a, __b); } static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a, @@ -16719,8 +16700,8 @@ static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned char __a, static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a, vector signed char __b) { - return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b, - (vector unsigned char)__a); + return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __b, + (vector signed char)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a, @@ -16758,8 +16739,8 @@ static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned short __a, static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a, vector short __b) { - return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b, - (vector unsigned short)__a); + return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __b, + (vector signed short)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a, @@ -16796,8 +16777,8 @@ static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned int __a, static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a, vector int __b) { - return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b, - (vector unsigned int)__a); + return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __b, + (vector signed int)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a, @@ -16837,9 +16818,8 @@ static __inline__ int __ATTRS_o_ai vec_any_lt(vector unsigned long long __a, static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a, vector signed long long __b) { - return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV, - (vector unsigned long long)__b, - (vector unsigned long long)__a); + return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __b, + (vector signed long long)__a); } static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a, diff --git a/clang/lib/Headers/builtins.h b/clang/lib/Headers/builtins.h new file mode 100644 index 0000000000000..65095861ca9b1 --- /dev/null +++ b/clang/lib/Headers/builtins.h @@ -0,0 +1,16 @@ +/*===---- builtins.h - Standard header for extra builtins -----------------===*\ + * + * 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 + * +\*===----------------------------------------------------------------------===*/ + +/// Some legacy compilers have builtin definitions in a file named builtins.h. +/// This header file has been added to allow compatibility with code that was +/// written for those compilers. Code may have an include line for this file +/// and to avoid an error an empty file with this name is provided. +#ifndef __BUILTINS_H +#define __BUILTINS_H + +#endif /* __BUILTINS_H */ diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index bfdd9b84dcede..d50f0b8d2e8f5 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -7259,7 +7259,7 @@ half16 __ovld __cnfn fmod(half16 x, half16 y); * Returns fmin(x - floor (x), 0x1.fffffep-1f ). * floor(x) is returned in iptr. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld fract(float x, float *iptr); float2 __ovld fract(float2 x, float2 *iptr); float3 __ovld fract(float3 x, float3 *iptr); @@ -7341,7 +7341,7 @@ half4 __ovld fract(half4 x, __private half4 *iptr); half8 __ovld fract(half8 x, __private half8 *iptr); half16 __ovld fract(half16 x, __private half16 *iptr); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Extract mantissa and exponent from x. For each @@ -7349,7 +7349,7 @@ half16 __ovld fract(half16 x, __private half16 *iptr); * magnitude in the interval [1/2, 1) or 0. Each * component of x equals mantissa returned * 2^exp. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld frexp(float x, int *exp); float2 __ovld frexp(float2 x, int2 *exp); float3 __ovld frexp(float3 x, int3 *exp); @@ -7431,7 +7431,7 @@ half4 __ovld frexp(half4 x, __private int4 *exp); half8 __ovld frexp(half8 x, __private int8 *exp); half16 __ovld frexp(half16 x, __private int16 *exp); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Compute the value of the square root of x^2 + y^2 @@ -7556,7 +7556,7 @@ half8 __ovld __cnfn lgamma(half8 x); half16 __ovld __cnfn lgamma(half16 x); #endif //cl_khr_fp16 -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld lgamma_r(float x, int *signp); float2 __ovld lgamma_r(float2 x, int2 *signp); float3 __ovld lgamma_r(float3 x, int3 *signp); @@ -7638,7 +7638,7 @@ half4 __ovld lgamma_r(half4 x, __private int4 *signp); half8 __ovld lgamma_r(half8 x, __private int8 *signp); half16 __ovld lgamma_r(half16 x, __private int16 *signp); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Compute natural logarithm. @@ -7862,7 +7862,7 @@ half16 __ovld __cnfn minmag(half16 x, half16 y); * the argument. It stores the integral part in the object * pointed to by iptr. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld modf(float x, float *iptr); float2 __ovld modf(float2 x, float2 *iptr); float3 __ovld modf(float3 x, float3 *iptr); @@ -7944,7 +7944,7 @@ half4 __ovld modf(half4 x, __private half4 *iptr); half8 __ovld modf(half8 x, __private half8 *iptr); half16 __ovld modf(half16 x, __private half16 *iptr); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Returns a quiet NaN. The nancode may be placed @@ -8122,7 +8122,7 @@ half16 __ovld __cnfn remainder(half16 x, half16 y); * sign as x/y. It stores this signed value in the object * pointed to by quo. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld remquo(float x, float y, int *quo); float2 __ovld remquo(float2 x, float2 y, int2 *quo); float3 __ovld remquo(float3 x, float3 y, int3 *quo); @@ -8205,7 +8205,7 @@ half4 __ovld remquo(half4 x, half4 y, __private int4 *quo); half8 __ovld remquo(half8 x, half8 y, __private int8 *quo); half16 __ovld remquo(half16 x, half16 y, __private int16 *quo); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Round to integral value (using round to nearest * even rounding mode) in floating-point format. @@ -8346,7 +8346,7 @@ half16 __ovld __cnfn sin(half16); * is the return value and computed cosine is returned * in cosval. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld sincos(float x, float *cosval); float2 __ovld sincos(float2 x, float2 *cosval); float3 __ovld sincos(float3 x, float3 *cosval); @@ -8428,7 +8428,7 @@ half4 __ovld sincos(half4 x, __private half4 *cosval); half8 __ovld sincos(half8 x, __private half8 *cosval); half16 __ovld sincos(half16 x, __private half16 *cosval); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Compute hyperbolic sine. @@ -11249,7 +11249,7 @@ half8 __ovld vload8(size_t offset, const __constant half *p); half16 __ovld vload16(size_t offset, const __constant half *p); #endif //cl_khr_fp16 -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) char2 __ovld vload2(size_t offset, const char *p); uchar2 __ovld vload2(size_t offset, const uchar *p); short2 __ovld vload2(size_t offset, const short *p); @@ -11487,9 +11487,9 @@ half4 __ovld vload4(size_t offset, const __private half *p); half8 __ovld vload8(size_t offset, const __private half *p); half16 __ovld vload16(size_t offset, const __private half *p); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) void __ovld vstore2(char2 data, size_t offset, char *p); void __ovld vstore2(uchar2 data, size_t offset, uchar *p); void __ovld vstore2(short2 data, size_t offset, short *p); @@ -11723,7 +11723,7 @@ void __ovld vstore4(half4 data, size_t offset, __private half *p); void __ovld vstore8(half8 data, size_t offset, __private half *p); void __ovld vstore16(half16 data, size_t offset, __private half *p); #endif //cl_khr_fp16 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Read sizeof (half) bytes of data from address @@ -11734,13 +11734,13 @@ void __ovld vstore16(half16 data, size_t offset, __private half *p); * must be 16-bit aligned. */ float __ovld vload_half(size_t offset, const __constant half *p); -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld vload_half(size_t offset, const half *p); #else float __ovld vload_half(size_t offset, const __global half *p); float __ovld vload_half(size_t offset, const __local half *p); float __ovld vload_half(size_t offset, const __private half *p); -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * Read sizeof (halfn) bytes of data from address @@ -11755,7 +11755,7 @@ float3 __ovld vload_half3(size_t offset, const __constant half *p); float4 __ovld vload_half4(size_t offset, const __constant half *p); float8 __ovld vload_half8(size_t offset, const __constant half *p); float16 __ovld vload_half16(size_t offset, const __constant half *p); -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float2 __ovld vload_half2(size_t offset, const half *p); float3 __ovld vload_half3(size_t offset, const half *p); float4 __ovld vload_half4(size_t offset, const half *p); @@ -11777,7 +11777,7 @@ float3 __ovld vload_half3(size_t offset, const __private half *p); float4 __ovld vload_half4(size_t offset, const __private half *p); float8 __ovld vload_half8(size_t offset, const __private half *p); float16 __ovld vload_half16(size_t offset, const __private half *p); -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * The float value given by data is first @@ -11790,7 +11790,7 @@ float16 __ovld vload_half16(size_t offset, const __private half *p); * The default current rounding mode is round to * nearest even. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) void __ovld vstore_half(float data, size_t offset, half *p); void __ovld vstore_half_rte(float data, size_t offset, half *p); void __ovld vstore_half_rtz(float data, size_t offset, half *p); @@ -11836,7 +11836,7 @@ void __ovld vstore_half_rtz(double data, size_t offset, __private half *p); void __ovld vstore_half_rtp(double data, size_t offset, __private half *p); void __ovld vstore_half_rtn(double data, size_t offset, __private half *p); #endif //cl_khr_fp64 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * The floatn value given by data is converted to @@ -11849,7 +11849,7 @@ void __ovld vstore_half_rtn(double data, size_t offset, __private half *p); * The default current rounding mode is round to * nearest even. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) void __ovld vstore_half2(float2 data, size_t offset, half *p); void __ovld vstore_half3(float3 data, size_t offset, half *p); void __ovld vstore_half4(float4 data, size_t offset, half *p); @@ -12055,7 +12055,7 @@ void __ovld vstore_half4_rtn(double4 data, size_t offset, __private half *p); void __ovld vstore_half8_rtn(double8 data, size_t offset, __private half *p); void __ovld vstore_half16_rtn(double16 data, size_t offset, __private half *p); #endif //cl_khr_fp64 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * For n = 1, 2, 4, 8 and 16 read sizeof (halfn) @@ -12076,7 +12076,7 @@ float3 __ovld vloada_half3(size_t offset, const __constant half *p); float4 __ovld vloada_half4(size_t offset, const __constant half *p); float8 __ovld vloada_half8(size_t offset, const __constant half *p); float16 __ovld vloada_half16(size_t offset, const __constant half *p); -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) float __ovld vloada_half(size_t offset, const half *p); float2 __ovld vloada_half2(size_t offset, const half *p); float3 __ovld vloada_half3(size_t offset, const half *p); @@ -12102,7 +12102,7 @@ float3 __ovld vloada_half3(size_t offset, const __private half *p); float4 __ovld vloada_half4(size_t offset, const __private half *p); float8 __ovld vloada_half8(size_t offset, const __private half *p); float16 __ovld vloada_half16(size_t offset, const __private half *p); -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) /** * The floatn value given by data is converted to @@ -12120,7 +12120,7 @@ float16 __ovld vloada_half16(size_t offset, const __private half *p); * mode. The default current rounding mode is * round to nearest even. */ -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) void __ovld vstorea_half(float data, size_t offset, half *p); void __ovld vstorea_half2(float2 data, size_t offset, half *p); void __ovld vstorea_half3(float3 data, size_t offset, half *p); @@ -12405,7 +12405,7 @@ void __ovld vstorea_half4_rtn(double4 data,size_t offset, __private half *p); void __ovld vstorea_half8_rtn(double8 data,size_t offset, __private half *p); void __ovld vstorea_half16_rtn(double16 data,size_t offset, __private half *p); #endif //cl_khr_fp64 -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) // OpenCL v1.1 s6.11.8, v1.2 s6.12.8, v2.0 s6.13.8 - Synchronization Functions @@ -12489,7 +12489,7 @@ void __ovld write_mem_fence(cl_mem_fence_flags flags); // OpenCL v2.0 s6.13.9 - Address Space Qualifier Functions -#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__opencl_c_generic_address_space) cl_mem_fence_flags __ovld get_fence(const void *ptr); cl_mem_fence_flags __ovld get_fence(void *ptr); @@ -12500,7 +12500,7 @@ cl_mem_fence_flags __ovld get_fence(void *ptr); * where gentype is builtin type or user defined type. */ -#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif //defined(__opencl_c_generic_address_space) // OpenCL v1.1 s6.11.10, v1.2 s6.12.10, v2.0 s6.13.10 - Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch @@ -13306,91 +13306,35 @@ void __ovld atomic_work_item_fence(cl_mem_fence_flags flags, memory_order order, // atomic_fetch() int __ovld atomic_fetch_add(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_add(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); int __ovld atomic_fetch_sub(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_sub(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); int __ovld atomic_fetch_or(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_or(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); int __ovld atomic_fetch_xor(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_xor(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); int __ovld atomic_fetch_and(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_and(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); int __ovld atomic_fetch_min(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_min(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); int __ovld atomic_fetch_max(volatile atomic_int *object, int operand); -int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order); -int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); uint __ovld atomic_fetch_max(volatile atomic_uint *object, uint operand); -uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order); -uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) long __ovld atomic_fetch_add(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_add(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); long __ovld atomic_fetch_sub(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_sub(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); long __ovld atomic_fetch_or(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_or(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); long __ovld atomic_fetch_xor(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_xor(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); long __ovld atomic_fetch_and(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_and(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); long __ovld atomic_fetch_min(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_min(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); long __ovld atomic_fetch_max(volatile atomic_long *object, long operand); -long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order); -long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); ulong __ovld atomic_fetch_max(volatile atomic_ulong *object, ulong operand); -ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); -ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); #endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) // OpenCL v2.0 s6.13.11.7.5: @@ -13398,151 +13342,259 @@ ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong oper #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) uintptr_t __ovld atomic_fetch_add(volatile atomic_uintptr_t *object, ptrdiff_t operand); -uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order); -uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope); uintptr_t __ovld atomic_fetch_sub(volatile atomic_uintptr_t *object, ptrdiff_t operand); +#endif + +int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order); +int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order); +int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order); +int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order); +int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order); +int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order); +int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order); +uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order); +ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order); +#endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order); uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order); +#endif + +int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope); +uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope); +ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope); +#endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope); uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope); #endif // atomic_store() void __ovld atomic_store(volatile atomic_int *object, int desired); -void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order); -void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope); void __ovld atomic_store(volatile atomic_uint *object, uint desired); -void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order); -void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope); void __ovld atomic_store(volatile atomic_float *object, float desired); -void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order); -void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope); + #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) #ifdef cl_khr_fp64 void __ovld atomic_store(volatile atomic_double *object, double desired); -void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order); -void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope); #endif //cl_khr_fp64 void __ovld atomic_store(volatile atomic_long *object, long desired); -void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order); -void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope); void __ovld atomic_store(volatile atomic_ulong *object, ulong desired); +#endif + +void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order); +void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order); +void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order); +#endif //cl_khr_fp64 +void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order); void __ovld atomic_store_explicit(volatile atomic_ulong *object, ulong desired, memory_order order); +#endif + +void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope); +void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope); +void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope); +#endif //cl_khr_fp64 +void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope); void __ovld atomic_store_explicit(volatile atomic_ulong *object, ulong desired, memory_order order, memory_scope scope); #endif // atomic_load() int __ovld atomic_load(volatile atomic_int *object); -int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order); -int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order, memory_scope scope); uint __ovld atomic_load(volatile atomic_uint *object); -uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order); -uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order, memory_scope scope); float __ovld atomic_load(volatile atomic_float *object); -float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order); -float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order, memory_scope scope); #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) #ifdef cl_khr_fp64 double __ovld atomic_load(volatile atomic_double *object); -double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order); -double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order, memory_scope scope); #endif //cl_khr_fp64 long __ovld atomic_load(volatile atomic_long *object); -long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order); -long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order, memory_scope scope); ulong __ovld atomic_load(volatile atomic_ulong *object); +#endif + +int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order); +uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order); +float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order); +#endif //cl_khr_fp64 +long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order); ulong __ovld atomic_load_explicit(volatile atomic_ulong *object, memory_order order); +#endif + +int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order, memory_scope scope); +uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order, memory_scope scope); +float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order, memory_scope scope); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order, memory_scope scope); +#endif //cl_khr_fp64 +long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order, memory_scope scope); ulong __ovld atomic_load_explicit(volatile atomic_ulong *object, memory_order order, memory_scope scope); #endif // atomic_exchange() int __ovld atomic_exchange(volatile atomic_int *object, int desired); -int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order); -int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope); uint __ovld atomic_exchange(volatile atomic_uint *object, uint desired); -uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order); -uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope); float __ovld atomic_exchange(volatile atomic_float *object, float desired); -float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order); -float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope); #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) #ifdef cl_khr_fp64 double __ovld atomic_exchange(volatile atomic_double *object, double desired); -double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order); -double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope); #endif //cl_khr_fp64 long __ovld atomic_exchange(volatile atomic_long *object, long desired); -long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order); -long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope); ulong __ovld atomic_exchange(volatile atomic_ulong *object, ulong desired); +#endif + +int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order); +uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order); +float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order); +#endif //cl_khr_fp64 +long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order); ulong __ovld atomic_exchange_explicit(volatile atomic_ulong *object, ulong desired, memory_order order); +#endif + +int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope); +uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope); +float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope); +#endif //cl_khr_fp64 +long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope); ulong __ovld atomic_exchange_explicit(volatile atomic_ulong *object, ulong desired, memory_order order, memory_scope scope); #endif // atomic_compare_exchange_strong() and atomic_compare_exchange_weak() bool __ovld atomic_compare_exchange_strong(volatile atomic_int *object, int *expected, int desired); +bool __ovld atomic_compare_exchange_strong(volatile atomic_uint *object, uint *expected, uint desired); +bool __ovld atomic_compare_exchange_weak(volatile atomic_int *object, int *expected, int desired); +bool __ovld atomic_compare_exchange_weak(volatile atomic_uint *object, uint *expected, uint desired); +bool __ovld atomic_compare_exchange_strong(volatile atomic_float *object, float *expected, float desired); +bool __ovld atomic_compare_exchange_weak(volatile atomic_float *object, float *expected, float desired); + +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +bool __ovld atomic_compare_exchange_strong(volatile atomic_double *object, double *expected, double desired); +bool __ovld atomic_compare_exchange_weak(volatile atomic_double *object, double *expected, double desired); +#endif //cl_khr_fp64 +bool __ovld atomic_compare_exchange_strong(volatile atomic_long *object, long *expected, long desired); +bool __ovld atomic_compare_exchange_weak(volatile atomic_long *object, long *expected, long desired); +bool __ovld atomic_compare_exchange_strong(volatile atomic_ulong *object, ulong *expected, ulong desired); +bool __ovld atomic_compare_exchange_weak(volatile atomic_ulong *object, ulong *expected, ulong desired); +#endif + bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected, int desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected, - int desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_strong(volatile atomic_uint *object, uint *expected, uint desired); bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected, uint desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected, - uint desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_weak(volatile atomic_int *object, int *expected, int desired); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected, int desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected, - int desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_weak(volatile atomic_uint *object, uint *expected, uint desired); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected, uint desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected, - uint desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_strong(volatile atomic_float *object, float *expected, float desired); bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected, float desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected, - float desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_weak(volatile atomic_float *object, float *expected, float desired); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected, float desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected, - float desired, memory_order success, memory_order failure, memory_scope scope); #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) #ifdef cl_khr_fp64 -bool __ovld atomic_compare_exchange_strong(volatile atomic_double *object, double *expected, double desired); bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected, double desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected, - double desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_weak(volatile atomic_double *object, double *expected, double desired); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected, double desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected, - double desired, memory_order success, memory_order failure, memory_scope scope); #endif //cl_khr_fp64 -bool __ovld atomic_compare_exchange_strong(volatile atomic_long *object, long *expected, long desired); bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected, long desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected, - long desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_weak(volatile atomic_long *object, long *expected, long desired); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected, long desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected, - long desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_strong(volatile atomic_ulong *object, ulong *expected, ulong desired); bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected, ulong desired, memory_order success, memory_order failure); -bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected, - ulong desired, memory_order success, memory_order failure, memory_scope scope); -bool __ovld atomic_compare_exchange_weak(volatile atomic_ulong *object, ulong *expected, ulong desired); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected, ulong desired, memory_order success, memory_order failure); +#endif + +bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected, + int desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected, + uint desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected, + int desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected, + uint desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected, + float desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected, + float desired, memory_order success, memory_order failure, memory_scope scope); +#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) +#ifdef cl_khr_fp64 +bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected, + double desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected, + double desired, memory_order success, memory_order failure, memory_scope scope); +#endif //cl_khr_fp64 +bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected, + long desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected, + long desired, memory_order success, memory_order failure, memory_scope scope); +bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected, + ulong desired, memory_order success, memory_order failure, memory_scope scope); bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected, ulong desired, memory_order success, memory_order failure, memory_scope scope); #endif @@ -13550,12 +13602,13 @@ bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, // atomic_flag_test_and_set() and atomic_flag_clear() bool __ovld atomic_flag_test_and_set(volatile atomic_flag *object); -bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order); -bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope); void __ovld atomic_flag_clear(volatile atomic_flag *object); + +bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order); void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order); -void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope); +bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope); +void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope); #endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v1.1 s6.11.12, v1.2 s6.12.12, v2.0 s6.13.12 - Miscellaneous Vector Functions diff --git a/clang/lib/Headers/openmp_wrappers/complex b/clang/lib/Headers/openmp_wrappers/complex index 142e526b81b35..dfd6193c97cbd 100644 --- a/clang/lib/Headers/openmp_wrappers/complex +++ b/clang/lib/Headers/openmp_wrappers/complex @@ -17,7 +17,6 @@ // We require std::math functions in the complex builtins below. #include -#define __CUDA__ #define __OPENMP_NVPTX__ #include <__clang_cuda_complex_builtins.h> #undef __OPENMP_NVPTX__ @@ -26,9 +25,6 @@ // Grab the host header too. #include_next - -#ifdef __cplusplus - // If we are compiling against libc++, the macro _LIBCPP_STD_VER should be set // after including above. Since the complex header we use is a // simplified version of the libc++, we don't need it in this case. If we @@ -48,5 +44,3 @@ #pragma omp end declare variant #endif - -#endif diff --git a/clang/lib/Headers/openmp_wrappers/complex.h b/clang/lib/Headers/openmp_wrappers/complex.h index 00d278548f826..15dc415b8126d 100644 --- a/clang/lib/Headers/openmp_wrappers/complex.h +++ b/clang/lib/Headers/openmp_wrappers/complex.h @@ -17,7 +17,6 @@ // We require math functions in the complex builtins below. #include -#define __CUDA__ #define __OPENMP_NVPTX__ #include <__clang_cuda_complex_builtins.h> #undef __OPENMP_NVPTX__ diff --git a/clang/lib/Headers/wasm_simd128.h b/clang/lib/Headers/wasm_simd128.h index 4869f7de6c7f3..fdb32bd1d059f 100644 --- a/clang/lib/Headers/wasm_simd128.h +++ b/clang/lib/Headers/wasm_simd128.h @@ -170,21 +170,49 @@ wasm_v128_load64_zero(const void *__mem) { return (v128_t)(__i64x2){__v, 0}; } -#define wasm_v128_load8_lane(__ptr, __vec, __i) \ - ((v128_t)__builtin_wasm_load8_lane((const signed char *)(__ptr), \ - (__i8x16)(__vec), (__i))) +static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load8_lane( + const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_load8_lane_struct { + int8_t __v; + } __attribute__((__packed__, __may_alias__)); + int8_t __v = ((const struct __wasm_v128_load8_lane_struct *)__mem)->__v; + __i8x16 __ret = (__i8x16)__vec; + __ret[__i] = __v; + return (v128_t)__ret; +} -#define wasm_v128_load16_lane(__ptr, __vec, __i) \ - ((v128_t)__builtin_wasm_load16_lane((const short *)(__ptr), \ - (__i16x8)(__vec), (__i))) +static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load16_lane( + const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_load16_lane_struct { + int16_t __v; + } __attribute__((__packed__, __may_alias__)); + int16_t __v = ((const struct __wasm_v128_load16_lane_struct *)__mem)->__v; + __i16x8 __ret = (__i16x8)__vec; + __ret[__i] = __v; + return (v128_t)__ret; +} -#define wasm_v128_load32_lane(__ptr, __vec, __i) \ - ((v128_t)__builtin_wasm_load32_lane((const int *)(__ptr), (__i32x4)(__vec), \ - (__i))) +static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load32_lane( + const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_load32_lane_struct { + int32_t __v; + } __attribute__((__packed__, __may_alias__)); + int32_t __v = ((const struct __wasm_v128_load32_lane_struct *)__mem)->__v; + __i32x4 __ret = (__i32x4)__vec; + __ret[__i] = __v; + return (v128_t)__ret; +} -#define wasm_v128_load64_lane(__ptr, __vec, __i) \ - ((v128_t)__builtin_wasm_load64_lane((const long long int *)(__ptr), \ - (__i64x2)(__vec), (__i))) +static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load64_lane( + const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_load64_lane_struct { + int64_t __v; + } __attribute__((__packed__, __may_alias__)); + int64_t __v = ((const struct __wasm_v128_load64_lane_struct *)__mem)->__v; + __i64x2 __ret = (__i64x2)__vec; + __ret[__i] = __v; + return (v128_t)__ret; +} static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store(void *__mem, v128_t __a) { @@ -195,18 +223,48 @@ static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store(void *__mem, ((struct __wasm_v128_store_struct *)__mem)->__v = __a; } -#define wasm_v128_store8_lane(__ptr, __vec, __i) \ - (__builtin_wasm_store8_lane((signed char *)(__ptr), (__i8x16)(__vec), (__i))) +static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store8_lane(void *__mem, + v128_t __vec, + int __i) + __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_store8_lane_struct { + int8_t __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __wasm_v128_store8_lane_struct *)__mem)->__v = ((__i8x16)__vec)[__i]; +} -#define wasm_v128_store16_lane(__ptr, __vec, __i) \ - (__builtin_wasm_store16_lane((short *)(__ptr), (__i16x8)(__vec), (__i))) +static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store16_lane(void *__mem, + v128_t __vec, + int __i) + __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_store16_lane_struct { + int16_t __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __wasm_v128_store16_lane_struct *)__mem)->__v = + ((__i16x8)__vec)[__i]; +} -#define wasm_v128_store32_lane(__ptr, __vec, __i) \ - (__builtin_wasm_store32_lane((int *)(__ptr), (__i32x4)(__vec), (__i))) +static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store32_lane(void *__mem, + v128_t __vec, + int __i) + __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_store32_lane_struct { + int32_t __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __wasm_v128_store32_lane_struct *)__mem)->__v = + ((__i32x4)__vec)[__i]; +} -#define wasm_v128_store64_lane(__ptr, __vec, __i) \ - (__builtin_wasm_store64_lane((long long int *)(__ptr), (__i64x2)(__vec), \ - (__i))) +static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store64_lane(void *__mem, + v128_t __vec, + int __i) + __REQUIRE_CONSTANT(__i) { + struct __wasm_v128_store64_lane_struct { + int64_t __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __wasm_v128_store64_lane_struct *)__mem)->__v = + ((__i64x2)__vec)[__i]; +} static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_make(int8_t __c0, int8_t __c1, int8_t __c2, int8_t __c3, int8_t __c4, @@ -1151,7 +1209,9 @@ wasm_u32x4_trunc_sat_f64x2_zero(v128_t __a) { static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_demote_f64x2_zero(v128_t __a) { - return (v128_t)__builtin_wasm_demote_zero_f64x2_f32x4((__f64x2)__a); + return (v128_t) __builtin_convertvector( + __builtin_shufflevector((__f64x2)__a, (__f64x2){0, 0}, 0, 1, 2, 3), + __f32x4); } static __inline__ v128_t __DEFAULT_FN_ATTRS diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 84b4d779d43c5..897e2cd1aaed8 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -12,6 +12,7 @@ #include "IncrementalParser.h" +#include "clang/AST/DeclContextInternals.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/CodeGen/ModuleBuilder.h" @@ -75,6 +76,9 @@ class IncrementalAction : public WrapperFrontendAction { return Act; }()) {} FrontendAction *getWrapped() const { return WrappedAction.get(); } + TranslationUnitKind getTranslationUnitKind() override { + return TU_Incremental; + } void ExecuteAction() override { CompilerInstance &CI = getCompilerInstance(); assert(CI.hasPreprocessor() && "No PP!"); @@ -130,26 +134,32 @@ IncrementalParser::IncrementalParser(std::unique_ptr Instance, IncrementalParser::~IncrementalParser() { Act->FinalizeAction(); } -llvm::Expected IncrementalParser::ParseOrWrapTopLevelDecl() { - DiagnosticsEngine &Diags = getCI()->getDiagnostics(); - - if (Diags.hasErrorOccurred()) - llvm::report_fatal_error("Previous input had errors, " - "recovery not yet supported", - /*GenCrashDiag=*/false); - +llvm::Expected +IncrementalParser::ParseOrWrapTopLevelDecl() { // Recover resources if we crash before exiting this method. Sema &S = CI->getSema(); llvm::CrashRecoveryContextCleanupRegistrar CleanupSema(&S); Sema::GlobalEagerInstantiationScope GlobalInstantiations(S, /*Enabled=*/true); Sema::LocalEagerInstantiationScope LocalInstantiations(S); + PTUs.emplace_back(PartialTranslationUnit()); + PartialTranslationUnit &LastPTU = PTUs.back(); + // Add a new PTU. + ASTContext &C = S.getASTContext(); + C.addTranslationUnitDecl(); + LastPTU.TUPart = C.getTranslationUnitDecl(); + // Skip previous eof due to last incremental input. - if (P->getCurToken().is(tok::eof)) + if (P->getCurToken().is(tok::eof)) { P->ConsumeToken(); - - Transactions.emplace_back(Transaction()); - Transaction &LastTransaction = Transactions.back(); + // FIXME: Clang does not call ExitScope on finalizing the regular TU, we + // might want to do that around HandleEndOfTranslationUnit. + P->ExitScope(); + S.CurContext = nullptr; + // Start a new PTU. + P->EnterScope(Scope::DeclScope); + S.ActOnTranslationUnitScope(P->getCurScope()); + } Parser::DeclGroupPtrTy ADecl; for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl); !AtEOF; @@ -161,26 +171,50 @@ llvm::Expected IncrementalParser::ParseOrWrapTopLevelDecl() { return llvm::make_error("Parsing failed. " "The consumer rejected a decl", std::error_code()); - LastTransaction.Decls.push_back(ADecl.get()); + } + + DiagnosticsEngine &Diags = getCI()->getDiagnostics(); + if (Diags.hasErrorOccurred()) { + TranslationUnitDecl *MostRecentTU = C.getTranslationUnitDecl(); + TranslationUnitDecl *PreviousTU = MostRecentTU->getPreviousDecl(); + assert(PreviousTU && "Must have a TU from the ASTContext initialization!"); + TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl(); + assert(FirstTU); + FirstTU->RedeclLink.setLatest(PreviousTU); + C.TUDecl = PreviousTU; + S.TUScope->setEntity(PreviousTU); + + // Clean up the lookup table + if (StoredDeclsMap *Map = PreviousTU->getLookupPtr()) { + for (auto I = Map->begin(); I != Map->end(); ++I) { + StoredDeclsList &List = I->second; + DeclContextLookupResult R = List.getLookupResult(); + for (NamedDecl *D : R) + if (D->getTranslationUnitDecl() == MostRecentTU) + List.remove(D); + if (List.isNull()) + Map->erase(I); + } + } + + // FIXME: Do not reset the pragma handlers. + Diags.Reset(); + return llvm::make_error("Parsing failed.", + std::error_code()); } // Process any TopLevelDecls generated by #pragma weak. for (Decl *D : S.WeakTopLevelDecls()) { DeclGroupRef DGR(D); - LastTransaction.Decls.push_back(DGR); Consumer->HandleTopLevelDecl(DGR); } LocalInstantiations.perform(); GlobalInstantiations.perform(); - Consumer->HandleTranslationUnit(S.getASTContext()); - - if (Diags.hasErrorOccurred()) - return llvm::make_error("Parsing failed.", - std::error_code()); + Consumer->HandleTranslationUnit(C); - return LastTransaction; + return LastPTU; } static CodeGenerator *getCodeGen(FrontendAction *Act) { @@ -191,7 +225,8 @@ static CodeGenerator *getCodeGen(FrontendAction *Act) { return static_cast(WrappedAct)->getCodeGenerator(); } -llvm::Expected IncrementalParser::Parse(llvm::StringRef input) { +llvm::Expected +IncrementalParser::Parse(llvm::StringRef input) { Preprocessor &PP = CI->getPreprocessor(); assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?"); @@ -224,9 +259,9 @@ llvm::Expected IncrementalParser::Parse(llvm::StringRef input) { "Cannot enter source file.", std::error_code()); - auto ErrOrTransaction = ParseOrWrapTopLevelDecl(); - if (auto Err = ErrOrTransaction.takeError()) - return std::move(Err); + auto PTU = ParseOrWrapTopLevelDecl(); + if (!PTU) + return PTU.takeError(); if (PP.getLangOpts().DelayedTemplateParsing) { // Microsoft-specific: @@ -246,12 +281,12 @@ llvm::Expected IncrementalParser::Parse(llvm::StringRef input) { if (CodeGenerator *CG = getCodeGen(Act.get())) { std::unique_ptr M(CG->ReleaseModule()); - CG->StartModule("incr_module_" + std::to_string(Transactions.size()), + CG->StartModule("incr_module_" + std::to_string(PTUs.size()), M->getContext()); - ErrOrTransaction->TheModule = std::move(M); + PTU->TheModule = std::move(M); } - return ErrOrTransaction; + return PTU; } } // end namespace clang diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h index 2ebc64e5930e5..aa8142cbe4939 100644 --- a/clang/lib/Interpreter/IncrementalParser.h +++ b/clang/lib/Interpreter/IncrementalParser.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H #define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H -#include "clang/Interpreter/Transaction.h" +#include "clang/Interpreter/PartialTranslationUnit.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -55,7 +55,7 @@ class IncrementalParser { /// List containing every information about every incrementally parsed piece /// of code. - std::list Transactions; + std::list PTUs; public: IncrementalParser(std::unique_ptr Instance, @@ -65,12 +65,12 @@ class IncrementalParser { const CompilerInstance *getCI() const { return CI.get(); } /// Parses incremental input by creating an in-memory file. - ///\returns a \c Transaction which holds information about the \c Decls and - /// \c llvm::Module corresponding to the input. - llvm::Expected Parse(llvm::StringRef Input); + ///\returns a \c PartialTranslationUnit which holds information about the + /// \c TranslationUnitDecl and \c llvm::Module corresponding to the input. + llvm::Expected Parse(llvm::StringRef Input); private: - llvm::Expected ParseOrWrapTopLevelDecl(); + llvm::Expected ParseOrWrapTopLevelDecl(); }; } // end namespace clang diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 768847f9f0352..937504f34739f 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -198,11 +198,12 @@ const CompilerInstance *Interpreter::getCompilerInstance() const { return IncrParser->getCI(); } -llvm::Expected Interpreter::Parse(llvm::StringRef Code) { +llvm::Expected +Interpreter::Parse(llvm::StringRef Code) { return IncrParser->Parse(Code); } -llvm::Error Interpreter::Execute(Transaction &T) { +llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { assert(T.TheModule); if (!IncrExecutor) { const llvm::Triple &Triple = diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index cb2b19b59c4ec..2cc4cae533d07 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -877,6 +877,14 @@ static CharSourceRange makeRangeFromFileLocs(CharSourceRange Range, return CharSourceRange::getCharRange(Begin, End); } +// Assumes that `Loc` is in an expansion. +static bool isInExpansionTokenRange(const SourceLocation Loc, + const SourceManager &SM) { + return SM.getSLocEntry(SM.getFileID(Loc)) + .getExpansion() + .isExpansionTokenRange(); +} + CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts) { @@ -896,10 +904,12 @@ CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range, } if (Begin.isFileID() && End.isMacroID()) { - if ((Range.isTokenRange() && !isAtEndOfMacroExpansion(End, SM, LangOpts, - &End)) || - (Range.isCharRange() && !isAtStartOfMacroExpansion(End, SM, LangOpts, - &End))) + if (Range.isTokenRange()) { + if (!isAtEndOfMacroExpansion(End, SM, LangOpts, &End)) + return {}; + // Use the *original* end, not the expanded one in `End`. + Range.setTokenRange(isInExpansionTokenRange(Range.getEnd(), SM)); + } else if (!isAtStartOfMacroExpansion(End, SM, LangOpts, &End)) return {}; Range.setEnd(End); return makeRangeFromFileLocs(Range, SM, LangOpts); @@ -914,6 +924,9 @@ CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range, &MacroEnd)))) { Range.setBegin(MacroBegin); Range.setEnd(MacroEnd); + // Use the *original* `End`, not the expanded one in `MacroEnd`. + if (Range.isTokenRange()) + Range.setTokenRange(isInExpansionTokenRange(End, SM)); return makeRangeFromFileLocs(Range, SM, LangOpts); } diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index b0335905b6f88..116724a0d50ba 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -778,6 +778,7 @@ void Parser::ParseLexedPragma(LateParsedPragma &LP) { ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); assert(Tok.isAnnotation() && "Expected annotation token."); switch (Tok.getKind()) { + case tok::annot_attr_openmp: case tok::annot_pragma_openmp: { AccessSpecifier AS = LP.getAccessSpecifier(); ParsedAttributesWithRange Attrs(AttrFactory); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 40051218e9c00..35c5b9bb19655 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4073,6 +4073,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___generic: // generic address space is introduced only in OpenCL v2.0 // see OpenCL C Spec v2.0 s6.5.5 + // OpenCL v3.0 introduces __opencl_c_generic_address_space + // feature macro to indicate if generic address space is supported if (!Actions.getLangOpts().OpenCLGenericAddressSpace) { DiagID = diag::err_opencl_unknown_type_specifier; PrevSpec = Tok.getIdentifierInfo()->getNameStart(); @@ -4302,7 +4304,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } - if (Tok.is(tok::annot_pragma_openmp)) { + if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { // Result can be ignored, because it must be always empty. AccessSpecifier AS = AS_none; ParsedAttributesWithRange Attrs(AttrFactory); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 37a5ae1f13770..ca5c013a51fe0 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2667,6 +2667,13 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParsedAttributesViewWithRange FnAttrs; // Optional C++11 attribute-specifier MaybeParseCXX11Attributes(attrs); + + // The next token may be an OpenMP pragma annotation token. That would + // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in + // this case, it came from an *attribute* rather than a pragma. Handle it now. + if (Tok.is(tok::annot_attr_openmp)) + return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs); + // We need to keep these attributes for future diagnostic // before they are taken over by declaration specifier. FnAttrs.addAll(attrs.begin(), attrs.end()); @@ -3261,6 +3268,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( return nullptr; } + case tok::annot_attr_openmp: case tok::annot_pragma_openmp: return ParseOpenMPDeclarativeDirectiveWithExtDecl( AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl); @@ -4135,6 +4143,70 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { } } +void Parser::ParseOpenMPAttributeArgs(IdentifierInfo *AttrName, + CachedTokens &OpenMPTokens) { + // Both 'sequence' and 'directive' attributes require arguments, so parse the + // open paren for the argument list. + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { + Diag(Tok, diag::err_expected) << tok::l_paren; + return; + } + + if (AttrName->isStr("directive")) { + // If the attribute is named `directive`, we can consume its argument list + // and push the tokens from it into the cached token stream for a new OpenMP + // pragma directive. + Token OMPBeginTok; + OMPBeginTok.startToken(); + OMPBeginTok.setKind(tok::annot_attr_openmp); + OMPBeginTok.setLocation(Tok.getLocation()); + OpenMPTokens.push_back(OMPBeginTok); + + ConsumeAndStoreUntil(tok::r_paren, OpenMPTokens, /*StopAtSemi=*/false, + /*ConsumeFinalToken*/ false); + Token OMPEndTok; + OMPEndTok.startToken(); + OMPEndTok.setKind(tok::annot_pragma_openmp_end); + OMPEndTok.setLocation(Tok.getLocation()); + OpenMPTokens.push_back(OMPEndTok); + } else { + assert(AttrName->isStr("sequence") && + "Expected either 'directive' or 'sequence'"); + // If the attribute is named 'sequence', its argument is a list of one or + // more OpenMP attributes (either 'omp::directive' or 'omp::sequence', + // where the 'omp::' is optional). + do { + // We expect to see one of the following: + // * An identifier (omp) for the attribute namespace followed by :: + // * An identifier (directive) or an identifier (sequence). + SourceLocation IdentLoc; + IdentifierInfo *Ident = TryParseCXX11AttributeIdentifier(IdentLoc); + + // If there is an identifier and it is 'omp', a double colon is required + // followed by the actual identifier we're after. + if (Ident && Ident->isStr("omp") && !ExpectAndConsume(tok::coloncolon)) + Ident = TryParseCXX11AttributeIdentifier(IdentLoc); + + // If we failed to find an identifier (scoped or otherwise), or we found + // an unexpected identifier, diagnose. + if (!Ident || (!Ident->isStr("directive") && !Ident->isStr("sequence"))) { + Diag(Tok.getLocation(), diag::err_expected_sequence_or_directive); + SkipUntil(tok::r_paren, StopBeforeMatch); + continue; + } + // We read an identifier. If the identifier is one of the ones we + // expected, we can recurse to parse the args. + ParseOpenMPAttributeArgs(Ident, OpenMPTokens); + + // There may be a comma to signal that we expect another directive in the + // sequence. + } while (TryConsumeToken(tok::comma)); + } + // Parse the closing paren for the argument list. + T.consumeClose(); +} + static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, IdentifierInfo *ScopeName) { switch ( @@ -4175,7 +4247,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc) { + SourceLocation ScopeLoc, + CachedTokens &OpenMPTokens) { assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); SourceLocation LParenLoc = Tok.getLocation(); const LangOptions &LO = getLangOpts(); @@ -4200,6 +4273,18 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, return true; } + if (ScopeName && ScopeName->isStr("omp")) { + Diag(AttrNameLoc, getLangOpts().OpenMP >= 51 + ? diag::warn_omp51_compat_attributes + : diag::ext_omp_attributes); + + ParseOpenMPAttributeArgs(AttrName, OpenMPTokens); + + // We claim that an attribute was parsed and added so that one is not + // created for us by the caller. + return true; + } + unsigned NumArgs; // Some Clang-scoped attributes have some special parsing behavior. if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"))) @@ -4259,11 +4344,12 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, /// /// [C++11] attribute-namespace: /// identifier -void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, - SourceLocation *endLoc) { +void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, + CachedTokens &OpenMPTokens, + SourceLocation *EndLoc) { if (Tok.is(tok::kw_alignas)) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas); - ParseAlignmentSpecifier(attrs, endLoc); + ParseAlignmentSpecifier(Attrs, EndLoc); return; } @@ -4345,11 +4431,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, // Parse attribute arguments if (Tok.is(tok::l_paren)) - AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc, - ScopeName, ScopeLoc); + AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, OpenMPTokens); if (!AttrParsed) { - attrs.addNew( + Attrs.addNew( AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), ScopeName, ScopeLoc, nullptr, 0, @@ -4374,8 +4460,8 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, SkipUntil(tok::r_square); else if (Tok.is(tok::r_square)) checkCompoundToken(CloseLoc, tok::r_square, CompoundToken::AttrEnd); - if (endLoc) - *endLoc = Tok.getLocation(); + if (EndLoc) + *EndLoc = Tok.getLocation(); if (ExpectAndConsume(tok::r_square)) SkipUntil(tok::r_square); } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index d2152fd117938..18e43c3734acb 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1857,7 +1857,8 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind, Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, DeclSpec::TST TagType, Decl *Tag) { - assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && + "Not an OpenMP directive!"); ParsingOpenMPDirectiveRAII DirScope(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1875,7 +1876,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( Toks.push_back(Tok); while (Cnt && Tok.isNot(tok::eof)) { (void)ConsumeAnyToken(); - if (Tok.is(tok::annot_pragma_openmp)) + if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) ++Cnt; else if (Tok.is(tok::annot_pragma_openmp_end)) --Cnt; @@ -2098,7 +2099,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ConsumeAnyToken(); DeclGroupPtrTy Ptr; - if (Tok.is(tok::annot_pragma_openmp)) { + if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, TagType, Tag); } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { @@ -2275,7 +2276,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { - assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && + "Not an OpenMP directive!"); ParsingOpenMPDirectiveRAII DirScope(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector Clauses; diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 7dd8dd1ff3b71..ebfe048513b1f 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -401,7 +401,12 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( return HandlePragmaCaptured(); case tok::annot_pragma_openmp: + // Prohibit attributes that are not OpenMP attributes, but only before + // processing a #pragma omp clause. ProhibitAttributes(Attrs); + LLVM_FALLTHROUGH; + case tok::annot_attr_openmp: + // Do not prohibit attributes if they were OpenMP attributes. return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx); case tok::annot_pragma_ms_pointers_to_members: diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index 9037895a3bbfc..e520151dcad76 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/lib/Parse/ParseStmtAsm.cpp @@ -633,9 +633,9 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SmallVector, 4> OpExprs; SmallVector Constraints; SmallVector Clobbers; - if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, - NumInputs, OpExprs, Constraints, Clobbers, - MII.get(), IP.get(), Callback)) + if (Parser->parseMSInlineAsm(AsmStringIR, NumOutputs, NumInputs, OpExprs, + Constraints, Clobbers, MII.get(), IP.get(), + Callback)) return StmtError(); // Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 55b25d20db51c..c81dd03ffaaae 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -309,6 +309,7 @@ bool Parser::SkipUntil(ArrayRef Toks, SkipUntilFlags Flags) { return false; case tok::annot_pragma_openmp: + case tok::annot_attr_openmp: case tok::annot_pragma_openmp_end: // Stop before an OpenMP pragma boundary. if (OpenMPDirectiveParsing) @@ -798,6 +799,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_opencl_extension: HandlePragmaOpenCLExtension(); return nullptr; + case tok::annot_attr_openmp: case tok::annot_pragma_openmp: { AccessSpecifier AS = AS_none; return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 72b3f687560d6..43d5be076d9be 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -184,6 +184,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr), SyclIntHeader(nullptr), SyclIntFooter(nullptr) { + assert(pp.TUKind == TUKind); TUScope = nullptr; isConstantEvaluatedOverride = false; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 869e414c70959..cac43075f860c 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2624,6 +2624,19 @@ void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) { } } +bool Sema::ShouldSplatAltivecScalarInCast(const VectorType *VecTy) { + bool SrcCompatXL = this->getLangOpts().getAltivecSrcCompat() == + LangOptions::AltivecSrcCompatKind::XL; + VectorType::VectorKind VKind = VecTy->getVectorKind(); + + if ((VKind == VectorType::AltiVecVector) || + (SrcCompatXL && ((VKind == VectorType::AltiVecBool) || + (VKind == VectorType::AltiVecPixel)))) { + return true; + } + return false; +} + void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, bool ListInitialization) { assert(Self.getLangOpts().CPlusPlus); @@ -2678,9 +2691,9 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, // AltiVec vector initialization with a single literal. if (const VectorType *vecTy = DestType->getAs()) - if (vecTy->getVectorKind() == VectorType::AltiVecVector - && (SrcExpr.get()->getType()->isIntegerType() - || SrcExpr.get()->getType()->isFloatingType())) { + if (Self.ShouldSplatAltivecScalarInCast(vecTy) && + (SrcExpr.get()->getType()->isIntegerType() || + SrcExpr.get()->getType()->isFloatingType())) { Kind = CK_VectorSplat; SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); return; @@ -2963,8 +2976,8 @@ void CastOperation::CheckCStyleCast() { } if (const VectorType *DestVecTy = DestType->getAs()) { - if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && - (SrcType->isIntegerType() || SrcType->isFloatingType())) { + if (Self.ShouldSplatAltivecScalarInCast(DestVecTy) && + (SrcType->isIntegerType() || SrcType->isFloatingType())) { Kind = CK_VectorSplat; SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index d53ecdf92ffc9..f1a0906db19cb 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3292,22 +3292,68 @@ static bool isPPC_64Builtin(unsigned BuiltinID) { case PPC::BI__builtin_bpermd: case PPC::BI__builtin_ppc_ldarx: case PPC::BI__builtin_ppc_stdcx: + case PPC::BI__builtin_ppc_tdw: + case PPC::BI__builtin_ppc_trapd: + case PPC::BI__builtin_ppc_cmpeqb: + case PPC::BI__builtin_ppc_setb: + case PPC::BI__builtin_ppc_mulhd: + case PPC::BI__builtin_ppc_mulhdu: + case PPC::BI__builtin_ppc_maddhd: + case PPC::BI__builtin_ppc_maddhdu: + case PPC::BI__builtin_ppc_maddld: + case PPC::BI__builtin_ppc_load8r: + case PPC::BI__builtin_ppc_store8r: + case PPC::BI__builtin_ppc_insert_exp: + case PPC::BI__builtin_ppc_extract_sig: return true; } return false; } static bool SemaFeatureCheck(Sema &S, CallExpr *TheCall, - StringRef FeatureToCheck, unsigned DiagID) { - if (!S.Context.getTargetInfo().hasFeature(FeatureToCheck)) - return S.Diag(TheCall->getBeginLoc(), DiagID) << TheCall->getSourceRange(); - return false; + StringRef FeatureToCheck, unsigned DiagID, + StringRef DiagArg = "") { + if (S.Context.getTargetInfo().hasFeature(FeatureToCheck)) + return false; + + if (DiagArg.empty()) + S.Diag(TheCall->getBeginLoc(), DiagID) << TheCall->getSourceRange(); + else + S.Diag(TheCall->getBeginLoc(), DiagID) + << DiagArg << TheCall->getSourceRange(); + + return true; +} + +/// Returns true if the argument consists of one contiguous run of 1s with any +/// number of 0s on either side. The 1s are allowed to wrap from LSB to MSB, so +/// 0x000FFF0, 0x0000FFFF, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not, +/// since all 1s are not contiguous. +bool Sema::SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) { + llvm::APSInt Result; + // We can't check the value of a dependent argument. + Expr *Arg = TheCall->getArg(ArgNum); + if (Arg->isTypeDependent() || Arg->isValueDependent()) + return false; + + // Check constant-ness first. + if (SemaBuiltinConstantArg(TheCall, ArgNum, Result)) + return true; + + // Check contiguous run of 1s, 0xFF0000FF is also a run of 1s. + if (Result.isShiftedMask() || (~Result).isShiftedMask()) + return false; + + return Diag(TheCall->getBeginLoc(), + diag::err_argument_not_contiguous_bit_field) + << ArgNum << Arg->getSourceRange(); } bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { unsigned i = 0, l = 0, u = 0; bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64; + llvm::APSInt Result; if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit) return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt) @@ -3343,17 +3389,17 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case PPC::BI__builtin_divde: case PPC::BI__builtin_divdeu: return SemaFeatureCheck(*this, TheCall, "extdiv", - diag::err_ppc_builtin_only_on_pwr7); + diag::err_ppc_builtin_only_on_arch, "7"); case PPC::BI__builtin_bpermd: return SemaFeatureCheck(*this, TheCall, "bpermd", - diag::err_ppc_builtin_only_on_pwr7); + diag::err_ppc_builtin_only_on_arch, "7"); case PPC::BI__builtin_unpack_vector_int128: return SemaFeatureCheck(*this, TheCall, "vsx", - diag::err_ppc_builtin_only_on_pwr7) || + diag::err_ppc_builtin_only_on_arch, "7") || SemaBuiltinConstantArgRange(TheCall, 1, 0, 1); case PPC::BI__builtin_pack_vector_int128: return SemaFeatureCheck(*this, TheCall, "vsx", - diag::err_ppc_builtin_only_on_pwr7); + diag::err_ppc_builtin_only_on_arch, "7"); case PPC::BI__builtin_altivec_vgnb: return SemaBuiltinConstantArgRange(TheCall, 1, 2, 7); case PPC::BI__builtin_altivec_vec_replace_elt: @@ -3372,6 +3418,42 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7); case PPC::BI__builtin_vsx_xxpermx: return SemaBuiltinConstantArgRange(TheCall, 3, 0, 7); + case PPC::BI__builtin_ppc_tw: + case PPC::BI__builtin_ppc_tdw: + return SemaBuiltinConstantArgRange(TheCall, 2, 0, 31); + case PPC::BI__builtin_ppc_cmpeqb: + case PPC::BI__builtin_ppc_setb: + case PPC::BI__builtin_ppc_maddhd: + case PPC::BI__builtin_ppc_maddhdu: + case PPC::BI__builtin_ppc_maddld: + return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions", + diag::err_ppc_builtin_only_on_arch, "9"); + case PPC::BI__builtin_ppc_cmprb: + return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions", + diag::err_ppc_builtin_only_on_arch, "9") || + SemaBuiltinConstantArgRange(TheCall, 0, 0, 1); + // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must + // be a constant that represents a contiguous bit field. + case PPC::BI__builtin_ppc_rlwnm: + return SemaBuiltinConstantArg(TheCall, 1, Result) || + SemaValueIsRunOfOnes(TheCall, 2); + case PPC::BI__builtin_ppc_rlwimi: + case PPC::BI__builtin_ppc_rldimi: + return SemaBuiltinConstantArg(TheCall, 2, Result) || + SemaValueIsRunOfOnes(TheCall, 3); + case PPC::BI__builtin_ppc_extract_exp: + case PPC::BI__builtin_ppc_extract_sig: + case PPC::BI__builtin_ppc_insert_exp: + return SemaFeatureCheck(*this, TheCall, "power9-vector", + diag::err_ppc_builtin_only_on_arch, "9"); + case PPC::BI__builtin_ppc_mtfsb0: + case PPC::BI__builtin_ppc_mtfsb1: + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31); + case PPC::BI__builtin_ppc_mtfsf: + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 255); + case PPC::BI__builtin_ppc_mtfsfi: + return SemaBuiltinConstantArgRange(TheCall, 0, 0, 7) || + SemaBuiltinConstantArgRange(TheCall, 1, 0, 15); #define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \ case PPC::BI__builtin_##Name: \ return SemaBuiltinPPCMMACall(TheCall, Types); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 942bbfff1d23f..60d22d6555459 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6476,7 +6476,11 @@ void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) { if (Type->isSamplerT() || Type->isVoidType()) return; LangAS ImplAS = LangAS::opencl_private; - if ((getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) && + // OpenCL C v3.0 s6.7.8 - For OpenCL C 2.0 or with the + // __opencl_c_program_scope_global_variables feature, the address space + // for a variable at program scope or a static or extern variable inside + // a function are inferred to be __global. + if (getOpenCLOptions().areProgramScopeVariablesSupported(getLangOpts()) && Var->hasGlobalStorage()) ImplAS = LangAS::opencl_global; // If the original type from a decayed type is an array type and that array @@ -8077,23 +8081,16 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } - // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the - // __constant address space. - // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static - // variables inside a function can also be declared in the global - // address space. - // C++ for OpenCL inherits rule from OpenCL C v2.0. // FIXME: Adding local AS in C++ for OpenCL might make sense. if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() || NewVD->hasExternalStorage()) { - if (!T->isSamplerT() && - !T->isDependentType() && + if (!T->isSamplerT() && !T->isDependentType() && !(T.getAddressSpace() == LangAS::opencl_constant || (T.getAddressSpace() == LangAS::opencl_global && - (getLangOpts().OpenCLVersion == 200 || - getLangOpts().OpenCLCPlusPlus)))) { + getOpenCLOptions().areProgramScopeVariablesSupported( + getLangOpts())))) { int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1; - if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus) + if (getOpenCLOptions().areProgramScopeVariablesSupported(getLangOpts())) Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) << Scope << "global or constant"; else @@ -16755,14 +16752,9 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, if (CStdConstraintViolation || MSBitfieldViolation) { unsigned DiagWidth = CStdConstraintViolation ? TypeWidth : TypeStorageSize; - if (FieldName) - return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width) - << FieldName << toString(Value, 10) - << !CStdConstraintViolation << DiagWidth; - - return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width) - << toString(Value, 10) << !CStdConstraintViolation - << DiagWidth; + return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width) + << (bool)FieldName << FieldName << toString(Value, 10) + << !CStdConstraintViolation << DiagWidth; } // Warn on types where the user might conceivably expect to get all diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 817843ee15c34..f9d77c13d6ff3 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4881,6 +4881,12 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, return; uint64_t AlignVal = Alignment.getZExtValue(); + // 16 byte ByVal alignment not due to a vector member is not honoured by XL + // on AIX. Emit a warning here that users are generating binary incompatible + // code to be safe. + if (AlignVal >= 16 && isa(D) && + Context.getTargetInfo().getTriple().isOSAIX()) + Diag(AttrLoc, diag::warn_not_xl_compatible) << E->getSourceRange(); // C++11 [dcl.align]p2: // -- if the constant expression evaluates to zero, the alignment @@ -9030,16 +9036,24 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an - // image object can be read and written. - // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe - // object. Using the read_write (or __read_write) qualifier with the pipe - // qualifier is a compilation error. + // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that + // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel + // cannot read from and write to the same pipe object. Using the read_write + // (or __read_write) qualifier with the pipe qualifier is a compilation error. + // OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the + // __opencl_c_read_write_images feature, image objects specified as arguments + // to a kernel can additionally be declared to be read-write. + // C++ for OpenCL inherits rule from OpenCL C v2.0. if (const auto *PDecl = dyn_cast(D)) { const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr(); if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) { + bool ReadWriteImagesUnsupportedForOCLC = + (S.getLangOpts().OpenCLVersion < 200) || + (S.getLangOpts().OpenCLVersion == 300 && + !S.getOpenCLOptions().isSupported("__opencl_c_read_write_images", + S.getLangOpts())); if ((!S.getLangOpts().OpenCLCPlusPlus && - S.getLangOpts().OpenCLVersion < 200) || + ReadWriteImagesUnsupportedForOCLC) || DeclTy->isPipeType()) { S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write) << AL << PDecl->getType() << DeclTy->isImageType(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 249993c992e48..b8d59a7f2538d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7795,7 +7795,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, // initializers must be one or must match the size of the vector. // If a single value is specified in the initializer then it will be // replicated to all the components of the vector - if (VTy->getVectorKind() == VectorType::AltiVecVector) { + if (ShouldSplatAltivecScalarInCast(VTy)) { // The number of initializers must be one or must match the size of the // vector. If a single value is specified in the initializer then it will // be replicated to all the components of the vector diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index daaf62f7ff05d..f644574e8575b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3920,7 +3920,7 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { - // C++ 6.4p4: + // C++11 6.4p4: // The value of a condition that is an initialized declaration in a statement // other than a switch statement is the value of the declared variable // implicitly converted to type bool. If that conversion is ill-formed, the @@ -3928,12 +3928,22 @@ ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { // The value of a condition that is an expression is the value of the // expression, implicitly converted to bool. // + // C++2b 8.5.2p2 + // If the if statement is of the form if constexpr, the value of the condition + // is contextually converted to bool and the converted expression shall be + // a constant expression. + // + + ExprResult E = PerformContextuallyConvertToBool(CondExpr); + if (!IsConstexpr || E.isInvalid() || E.get()->isValueDependent()) + return E; + // FIXME: Return this value to the caller so they don't need to recompute it. - llvm::APSInt Value(/*BitWidth*/1); - return (IsConstexpr && !CondExpr->isValueDependent()) - ? CheckConvertedConstantExpression(CondExpr, Context.BoolTy, Value, - CCEK_ConstexprIf) - : PerformContextuallyConvertToBool(CondExpr); + llvm::APSInt Cond; + E = VerifyIntegerConstantExpression( + E.get(), &Cond, + diag::err_constexpr_if_condition_expression_is_not_constant); + return E; } /// Helper function to determine whether this is the (deprecated) C++ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 8092f0be6ccec..0758fbb841074 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5634,12 +5634,8 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, // implicitly converted to type T, where the converted // expression is a constant expression and the implicit conversion // sequence contains only [... list of conversions ...]. - // C++1z [stmt.if]p2: - // If the if statement is of the form if constexpr, the value of the - // condition shall be a contextually converted constant expression of type - // bool. ImplicitConversionSequence ICS = - CCE == Sema::CCEK_ConstexprIf || CCE == Sema::CCEK_ExplicitBool + CCE == Sema::CCEK_ExplicitBool ? TryContextuallyConvertToBool(S, From) : TryCopyInitialization(S, From, T, /*SuppressUserConversions=*/false, diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7dd0aa37cb26f..1c31600a39d87 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3451,6 +3451,28 @@ const VarDecl *Sema::getCopyElisionCandidate(NamedReturnInfo &Info, return Info.isCopyElidable() ? Info.Candidate : nullptr; } +/// Verify that the initialization sequence that was picked for the +/// first overload resolution is permissible under C++98. +/// +/// Reject (possibly converting) contructors not taking an rvalue reference, +/// or user conversion operators which are not ref-qualified. +static bool +VerifyInitializationSequenceCXX98(const Sema &S, + const InitializationSequence &Seq) { + const auto *Step = llvm::find_if(Seq.steps(), [](const auto &Step) { + return Step.Kind == InitializationSequence::SK_ConstructorInitialization || + Step.Kind == InitializationSequence::SK_UserConversion; + }); + if (Step != Seq.step_end()) { + const auto *FD = Step->Function.Function; + if (isa(FD) + ? !FD->getParamDecl(0)->getType()->isRValueReferenceType() + : cast(FD)->getRefQualifier() == RQ_None) + return false; + } + return true; +} + /// Perform the initialization of a potentially-movable value, which /// is the result of return value. /// @@ -3461,8 +3483,7 @@ ExprResult Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value) { - if (getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus2b && - NRInfo.isMoveEligible()) { + if (!getLangOpts().CPlusPlus2b && NRInfo.isMoveEligible()) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), CK_NoOp, Value, VK_XValue, FPOptionsOverride()); Expr *InitExpr = &AsRvalue; @@ -3470,7 +3491,9 @@ Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, Value->getBeginLoc()); InitializationSequence Seq(*this, Entity, Kind, InitExpr); auto Res = Seq.getFailedOverloadResult(); - if (Res == OR_Success || Res == OR_Deleted) { + if ((Res == OR_Success || Res == OR_Deleted) && + (getLangOpts().CPlusPlus11 || + VerifyInitializationSequenceCXX98(*this, Seq))) { // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. Value = diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 149126a8b53f2..9b10c34b628b0 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2764,7 +2764,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, // If requested by the caller and the module hasn't already been read // or compiled, mark modules on error as out-of-date. if ((ClientLoadCapabilities & ARR_TreatModuleWithErrorsAsOutOfDate) && - !ModuleMgr.getModuleCache().isPCMFinal(F.FileName)) + canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) return OutOfDate; if (!AllowASTWithCompilerErrors) { @@ -2850,9 +2850,14 @@ ASTReader::ReadControlBlock(ModuleFile &F, StoredSignature, Capabilities); // If we diagnosed a problem, produce a backtrace. - if (isDiagnosedResult(Result, Capabilities)) + bool recompilingFinalized = + Result == OutOfDate && (Capabilities & ARR_OutOfDate) && + getModuleManager().getModuleCache().isPCMFinal(F.FileName); + if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized) Diag(diag::note_module_file_imported_by) << F.FileName << !F.ModuleName.empty() << F.ModuleName; + if (recompilingFinalized) + Diag(diag::note_module_file_conflict); switch (Result) { case Failure: return Failure; @@ -2918,7 +2923,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) { auto BuildDir = PP.getFileManager().getDirectory(Blob); if (!BuildDir || *BuildDir != M->Directory) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) Diag(diag::err_imported_module_relocated) << F.ModuleName << Blob << M->Directory->getName(); return OutOfDate; @@ -3928,7 +3933,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation & DisableValidationForModuleKind::Module) && !ModMap) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) { + if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) { if (auto ASTFE = M ? M->getASTFile() : None) { // This module was defined by an imported (explicit) module. Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName @@ -3959,7 +3964,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, assert((ImportedBy || F.Kind == MK_ImplicitModule) && "top-level import should be verified"); bool NotImported = F.Kind == MK_ImplicitModule && !ImportedBy; - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) Diag(diag::err_imported_module_modmap_changed) << F.ModuleName << (NotImported ? F.FileName : ImportedBy->FileName) << ModMap->getName() << F.ModuleMapPath << NotImported; @@ -3970,13 +3975,13 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) { // FIXME: we should use input files rather than storing names. std::string Filename = ReadPath(F, Record, Idx); - auto F = FileMgr.getFile(Filename, false, false); - if (!F) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + auto SF = FileMgr.getFile(Filename, false, false); + if (!SF) { + if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) Error("could not find file '" + Filename +"' referenced by AST file"); return OutOfDate; } - AdditionalStoredMaps.insert(*F); + AdditionalStoredMaps.insert(*SF); } // Check any additional module map files (e.g. module.private.modulemap) @@ -3986,7 +3991,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, // Remove files that match // Note: SmallPtrSet::erase is really remove if (!AdditionalStoredMaps.erase(ModMap)) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) Diag(diag::err_module_different_modmap) << F.ModuleName << /*new*/0 << ModMap->getName(); return OutOfDate; @@ -3997,7 +4002,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, // Check any additional module map files that are in the pcm, but not // found in header search. Cases that match are already removed. for (const FileEntry *ModMap : AdditionalStoredMaps) { - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) Diag(diag::err_module_different_modmap) << F.ModuleName << /*not new*/1 << ModMap->getName(); return OutOfDate; @@ -5924,6 +5929,12 @@ ASTReader::getModulePreprocessedEntities(ModuleFile &Mod) const { PreprocessingRecord::iterator()); } +bool ASTReader::canRecoverFromOutOfDate(StringRef ModuleFileName, + unsigned int ClientLoadCapabilities) { + return ClientLoadCapabilities & ARR_OutOfDate && + !getModuleManager().getModuleCache().isPCMFinal(ModuleFileName); +} + llvm::iterator_range ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) { return llvm::make_range( @@ -7183,6 +7194,11 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { return; } + if (!D->getDeclContext()) { + assert(isa(D) && "Not a TU?"); + return; + } + const DeclContext *DC = D->getDeclContext()->getRedeclContext(); // If this is a named declaration, complete it by looking it up diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h index 92c386bbb2b09..6a40f8eda5fa8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h @@ -22,6 +22,10 @@ namespace smartptr { /// Returns true if the event call is on smart pointer. bool isStdSmartPtrCall(const CallEvent &Call); +bool isStdSmartPtr(const CXXRecordDecl *RD); +bool isStdSmartPtr(const Expr *E); + +bool isStdSmartPtr(const CXXRecordDecl *RD); /// Returns whether the smart pointer is null or not. bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion); diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp index 6ee7bd9252b33..253606b97ec6a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -25,16 +25,20 @@ #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" #include using namespace clang; using namespace ento; namespace { + class SmartPtrModeling : public Checker { @@ -60,7 +64,7 @@ class SmartPtrModeling private: void handleReset(const CallEvent &Call, CheckerContext &C) const; void handleRelease(const CallEvent &Call, CheckerContext &C) const; - void handleSwap(const CallEvent &Call, CheckerContext &C) const; + void handleSwapMethod(const CallEvent &Call, CheckerContext &C) const; void handleGet(const CallEvent &Call, CheckerContext &C) const; bool handleAssignOp(const CallEvent &Call, CheckerContext &C) const; bool handleMoveCtr(const CallEvent &Call, CheckerContext &C, @@ -68,19 +72,56 @@ class SmartPtrModeling bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion, const MemRegion *OtherSmartPtrRegion) const; void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const; + bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const; + bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const; + bool handleSwap(ProgramStateRef State, SVal First, SVal Second, + CheckerContext &C) const; + std::pair + retrieveOrConjureInnerPtrVal(ProgramStateRef State, + const MemRegion *ThisRegion, const Expr *E, + QualType Type, CheckerContext &C) const; using SmartPtrMethodHandlerFn = void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const; CallDescriptionMap SmartPtrMethodHandlers{ {{"reset"}, &SmartPtrModeling::handleReset}, {{"release"}, &SmartPtrModeling::handleRelease}, - {{"swap", 1}, &SmartPtrModeling::handleSwap}, + {{"swap", 1}, &SmartPtrModeling::handleSwapMethod}, {{"get"}, &SmartPtrModeling::handleGet}}; + const CallDescription StdSwapCall{{"std", "swap"}, 2}; + const CallDescription StdMakeUniqueCall{{"std", "make_unique"}}; + const CallDescription StdMakeUniqueForOverwriteCall{ + {"std", "make_unique_for_overwrite"}}; }; } // end of anonymous namespace REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal) +// Checks if RD has name in Names and is in std namespace +static bool hasStdClassWithName(const CXXRecordDecl *RD, + ArrayRef Names) { + if (!RD || !RD->getDeclContext()->isStdNamespace()) + return false; + if (RD->getDeclName().isIdentifier()) { + StringRef Name = RD->getName(); + return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool { + return Name == GivenName; + }); + } + return false; +} + +constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr", + "weak_ptr"}; + +static bool isStdSmartPtr(const CXXRecordDecl *RD) { + return hasStdClassWithName(RD, STD_PTR_NAMES); +} + +static bool isStdSmartPtr(const Expr *E) { + return isStdSmartPtr(E->getType()->getAsCXXRecordDecl()); +} + // Define the inter-checker API. namespace clang { namespace ento { @@ -89,18 +130,24 @@ bool isStdSmartPtrCall(const CallEvent &Call) { const auto *MethodDecl = dyn_cast_or_null(Call.getDecl()); if (!MethodDecl || !MethodDecl->getParent()) return false; + return isStdSmartPtr(MethodDecl->getParent()); +} - const auto *RecordDecl = MethodDecl->getParent(); - if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace()) +bool isStdSmartPtr(const CXXRecordDecl *RD) { + if (!RD || !RD->getDeclContext()->isStdNamespace()) return false; - if (RecordDecl->getDeclName().isIdentifier()) { - StringRef Name = RecordDecl->getName(); + if (RD->getDeclName().isIdentifier()) { + StringRef Name = RD->getName(); return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr"; } return false; } +bool isStdSmartPtr(const Expr *E) { + return isStdSmartPtr(E->getType()->getAsCXXRecordDecl()); +} + bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) { const auto *InnerPointVal = State->get(ThisRegion); return InnerPointVal && @@ -135,28 +182,47 @@ static ProgramStateRef updateSwappedRegion(ProgramStateRef State, return State; } -// Helper method to get the inner pointer type of specialized smart pointer -// Returns empty type if not found valid inner pointer type. -static QualType getInnerPointerType(const CallEvent &Call, CheckerContext &C) { - const auto *MethodDecl = dyn_cast_or_null(Call.getDecl()); - if (!MethodDecl || !MethodDecl->getParent()) - return {}; - - const auto *RecordDecl = MethodDecl->getParent(); - if (!RecordDecl || !RecordDecl->isInStdNamespace()) +static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD) { + if (!RD || !RD->isInStdNamespace()) return {}; - const auto *TSD = dyn_cast(RecordDecl); + const auto *TSD = dyn_cast(RD); if (!TSD) return {}; auto TemplateArgs = TSD->getTemplateArgs().asArray(); - if (TemplateArgs.size() == 0) + if (TemplateArgs.empty()) return {}; auto InnerValueType = TemplateArgs[0].getAsType(); return C.getASTContext().getPointerType(InnerValueType.getCanonicalType()); } +// This is for use with standalone-functions like std::make_unique, +// std::make_unique_for_overwrite, etc. It reads the template parameter and +// returns the pointer type corresponding to it, +static QualType getPointerTypeFromTemplateArg(const CallEvent &Call, + CheckerContext &C) { + const auto *FD = dyn_cast_or_null(Call.getDecl()); + if (!FD || !FD->isFunctionTemplateSpecialization()) + return {}; + const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray(); + if (TemplateArgs.size() == 0) + return {}; + auto ValueType = TemplateArgs[0].getAsType(); + return C.getASTContext().getPointerType(ValueType.getCanonicalType()); +} + +// Helper method to get the inner pointer type of specialized smart pointer +// Returns empty type if not found valid inner pointer type. +static QualType getInnerPointerType(const CallEvent &Call, CheckerContext &C) { + const auto *MethodDecl = dyn_cast_or_null(Call.getDecl()); + if (!MethodDecl || !MethodDecl->getParent()) + return {}; + + const auto *RecordDecl = MethodDecl->getParent(); + return getInnerPointerType(C, RecordDecl); +} + // Helper method to pretty print region and avoid extra spacing. static void checkAndPrettyPrintRegion(llvm::raw_ostream &OS, const MemRegion *Region) { @@ -175,9 +241,100 @@ bool SmartPtrModeling::isBoolConversionMethod(const CallEvent &Call) const { return CD && CD->getConversionType()->isBooleanType(); } +constexpr llvm::StringLiteral BASIC_OSTREAM_NAMES[] = {"basic_ostream"}; + +bool isStdBasicOstream(const Expr *E) { + const auto *RD = E->getType()->getAsCXXRecordDecl(); + return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES); +} + +bool isStdOstreamOperatorCall(const CallEvent &Call) { + if (Call.getNumArgs() != 2 || + !Call.getDecl()->getDeclContext()->isStdNamespace()) + return false; + const auto *FC = dyn_cast(&Call); + if (!FC) + return false; + const FunctionDecl *FD = FC->getDecl(); + if (!FD->isOverloadedOperator()) + return false; + const OverloadedOperatorKind OOK = FD->getOverloadedOperator(); + if (OOK != clang::OO_LessLess) + return false; + return isStdSmartPtr(Call.getArgExpr(1)) && + isStdBasicOstream(Call.getArgExpr(0)); +} + bool SmartPtrModeling::evalCall(const CallEvent &Call, CheckerContext &C) const { + ProgramStateRef State = C.getState(); + + // If any one of the arg is a unique_ptr, then + // we can try this function + if (Call.getNumArgs() == 2 && + Call.getDecl()->getDeclContext()->isStdNamespace()) + if (smartptr::isStdSmartPtr(Call.getArgExpr(0)) || + smartptr::isStdSmartPtr(Call.getArgExpr(1))) + if (handleComparisionOp(Call, C)) + return true; + + if (isStdOstreamOperatorCall(Call)) + return handleOstreamOperator(Call, C); + + if (Call.isCalled(StdSwapCall)) { + // Check the first arg, if it is of std::unique_ptr type. + assert(Call.getNumArgs() == 2 && "std::swap should have two arguments"); + const Expr *FirstArg = Call.getArgExpr(0); + if (!smartptr::isStdSmartPtr(FirstArg->getType()->getAsCXXRecordDecl())) + return false; + return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C); + } + + if (Call.isCalled(StdMakeUniqueCall) || + Call.isCalled(StdMakeUniqueForOverwriteCall)) { + if (!ModelSmartPtrDereference) + return false; + + const Optional ThisRegionOpt = Call.getReturnValueUnderConstruction(); + if (!ThisRegionOpt) + return false; + + const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal( + Call.getOriginExpr(), C.getLocationContext(), + getPointerTypeFromTemplateArg(Call, C), C.blockCount()); + + const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion(); + State = State->set(ThisRegion, PtrVal); + State = State->assume(PtrVal, true); + + // TODO: ExprEngine should do this for us. + // For a bit more context: + // 1) Why do we need this? Since we are modelling a "function" + // that returns a constructed object we need to store this information in + // the program state. + // + // 2) Why does this work? + // `updateObjectsUnderConstruction` does exactly as it sounds. + // + // 3) How should it look like when moved to the Engine? + // It would be nice if we can just + // pretend we don't need to know about this - ie, completely automatic work. + // However, realistically speaking, I think we would need to "signal" the + // ExprEngine evalCall handler that we are constructing an object with this + // function call (constructors obviously construct, hence can be + // automatically deduced). + auto &Engine = State->getStateManager().getOwningEngine(); + State = Engine.updateObjectsUnderConstruction( + *ThisRegionOpt, nullptr, State, C.getLocationContext(), + Call.getConstructionContext(), {}); + + // We don't leave a note here since it is guaranteed the + // unique_ptr from this call is non-null (hence is safe to de-reference). + C.addTransition(State); + return true; + } + if (!smartptr::isStdSmartPtrCall(Call)) return false; @@ -272,6 +429,108 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call, return C.isDifferent(); } +std::pair SmartPtrModeling::retrieveOrConjureInnerPtrVal( + ProgramStateRef State, const MemRegion *ThisRegion, const Expr *E, + QualType Type, CheckerContext &C) const { + const auto *Ptr = State->get(ThisRegion); + if (Ptr) + return {*Ptr, State}; + auto Val = C.getSValBuilder().conjureSymbolVal(E, C.getLocationContext(), + Type, C.blockCount()); + State = State->set(ThisRegion, Val); + return {Val, State}; +} + +bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call, + CheckerContext &C) const { + const auto *FC = dyn_cast(&Call); + if (!FC) + return false; + const FunctionDecl *FD = FC->getDecl(); + if (!FD->isOverloadedOperator()) + return false; + const OverloadedOperatorKind OOK = FD->getOverloadedOperator(); + if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less || + OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual || + OOK == OO_Spaceship)) + return false; + + // There are some special cases about which we can infer about + // the resulting answer. + // For reference, there is a discussion at https://reviews.llvm.org/D104616. + // Also, the cppreference page is good to look at + // https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp. + + auto makeSValFor = [&C, this](ProgramStateRef State, const Expr *E, + SVal S) -> std::pair { + if (S.isZeroConstant()) { + return {S, State}; + } + const MemRegion *Reg = S.getAsRegion(); + assert(Reg && + "this pointer of std::unique_ptr should be obtainable as MemRegion"); + QualType Type = getInnerPointerType(C, E->getType()->getAsCXXRecordDecl()); + return retrieveOrConjureInnerPtrVal(State, Reg, E, Type, C); + }; + + SVal First = Call.getArgSVal(0); + SVal Second = Call.getArgSVal(1); + const auto *FirstExpr = Call.getArgExpr(0); + const auto *SecondExpr = Call.getArgExpr(1); + + const auto *ResultExpr = Call.getOriginExpr(); + const auto *LCtx = C.getLocationContext(); + auto &Bldr = C.getSValBuilder(); + ProgramStateRef State = C.getState(); + + SVal FirstPtrVal, SecondPtrVal; + std::tie(FirstPtrVal, State) = makeSValFor(State, FirstExpr, First); + std::tie(SecondPtrVal, State) = makeSValFor(State, SecondExpr, Second); + BinaryOperatorKind BOK = + operationKindFromOverloadedOperator(OOK, true).GetBinaryOpUnsafe(); + auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal, + Call.getResultType()); + + if (OOK != OO_Spaceship) { + ProgramStateRef TrueState, FalseState; + std::tie(TrueState, FalseState) = + State->assume(*RetVal.getAs()); + if (TrueState) + C.addTransition( + TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(true))); + if (FalseState) + C.addTransition( + FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(false))); + } else { + C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal)); + } + return true; +} + +bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call, + CheckerContext &C) const { + // operator<< does not modify the smart pointer. + // And we don't really have much of modelling of basic_ostream. + // So, we are better off: + // 1) Invalidating the mem-region of the ostream object at hand. + // 2) Setting the SVal of the basic_ostream as the return value. + // Not very satisfying, but it gets the job done, and is better + // than the default handling. :) + + ProgramStateRef State = C.getState(); + const auto StreamVal = Call.getArgSVal(0); + const MemRegion *StreamThisRegion = StreamVal.getAsRegion(); + if (!StreamThisRegion) + return false; + State = + State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(), + C.blockCount(), C.getLocationContext(), false); + State = + State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal); + C.addTransition(State); + return true; +} + void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const { ProgramStateRef State = C.getState(); @@ -395,43 +654,52 @@ void SmartPtrModeling::handleRelease(const CallEvent &Call, // pointer. } -void SmartPtrModeling::handleSwap(const CallEvent &Call, - CheckerContext &C) const { +void SmartPtrModeling::handleSwapMethod(const CallEvent &Call, + CheckerContext &C) const { // To model unique_ptr::swap() method. const auto *IC = dyn_cast(&Call); if (!IC) return; - const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion(); - if (!ThisRegion) - return; + auto State = C.getState(); + handleSwap(State, IC->getCXXThisVal(), Call.getArgSVal(0), C); +} - const auto *ArgRegion = Call.getArgSVal(0).getAsRegion(); - if (!ArgRegion) - return; +bool SmartPtrModeling::handleSwap(ProgramStateRef State, SVal First, + SVal Second, CheckerContext &C) const { + const MemRegion *FirstThisRegion = First.getAsRegion(); + if (!FirstThisRegion) + return false; + const MemRegion *SecondThisRegion = Second.getAsRegion(); + if (!SecondThisRegion) + return false; - auto State = C.getState(); - const auto *ThisRegionInnerPointerVal = - State->get(ThisRegion); - const auto *ArgRegionInnerPointerVal = - State->get(ArgRegion); + const auto *FirstInnerPtrVal = State->get(FirstThisRegion); + const auto *SecondInnerPtrVal = + State->get(SecondThisRegion); - // Swap the tracked region values. - State = updateSwappedRegion(State, ThisRegion, ArgRegionInnerPointerVal); - State = updateSwappedRegion(State, ArgRegion, ThisRegionInnerPointerVal); + State = updateSwappedRegion(State, FirstThisRegion, SecondInnerPtrVal); + State = updateSwappedRegion(State, SecondThisRegion, FirstInnerPtrVal); - C.addTransition( - State, C.getNoteTag([ThisRegion, ArgRegion](PathSensitiveBugReport &BR, - llvm::raw_ostream &OS) { - if (&BR.getBugType() != smartptr::getNullDereferenceBugType() || - !BR.isInteresting(ThisRegion)) - return; - BR.markInteresting(ArgRegion); - OS << "Swapped null smart pointer"; - checkAndPrettyPrintRegion(OS, ArgRegion); - OS << " with smart pointer"; - checkAndPrettyPrintRegion(OS, ThisRegion); - })); + C.addTransition(State, C.getNoteTag([FirstThisRegion, SecondThisRegion]( + PathSensitiveBugReport &BR, + llvm::raw_ostream &OS) { + if (&BR.getBugType() != smartptr::getNullDereferenceBugType()) + return; + if (BR.isInteresting(FirstThisRegion) && + !BR.isInteresting(SecondThisRegion)) { + BR.markInteresting(SecondThisRegion); + BR.markNotInteresting(FirstThisRegion); + } + if (BR.isInteresting(SecondThisRegion) && + !BR.isInteresting(FirstThisRegion)) { + BR.markInteresting(FirstThisRegion); + BR.markNotInteresting(SecondThisRegion); + } + // TODO: We need to emit some note here probably!! + })); + + return true; } void SmartPtrModeling::handleGet(const CallEvent &Call, @@ -446,15 +714,8 @@ void SmartPtrModeling::handleGet(const CallEvent &Call, return; SVal InnerPointerVal; - if (const auto *InnerValPtr = State->get(ThisRegion)) { - InnerPointerVal = *InnerValPtr; - } else { - const auto *CallExpr = Call.getOriginExpr(); - InnerPointerVal = C.getSValBuilder().conjureSymbolVal( - CallExpr, C.getLocationContext(), Call.getResultType(), C.blockCount()); - State = State->set(ThisRegion, InnerPointerVal); - } - + std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal( + State, ThisRegion, Call.getOriginExpr(), Call.getResultType(), C); State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), InnerPointerVal); // TODO: Add NoteTag, for how the raw pointer got using 'get' method. diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 6ace986b4e0df..d6f69ae03afe5 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2249,10 +2249,24 @@ void PathSensitiveBugReport::markInteresting(SymbolRef sym, insertToInterestingnessMap(InterestingSymbols, sym, TKind); + // FIXME: No tests exist for this code and it is questionable: + // How to handle multiple metadata for the same region? if (const auto *meta = dyn_cast(sym)) markInteresting(meta->getRegion(), TKind); } +void PathSensitiveBugReport::markNotInteresting(SymbolRef sym) { + if (!sym) + return; + InterestingSymbols.erase(sym); + + // The metadata part of markInteresting is not reversed here. + // Just making the same region not interesting is incorrect + // in specific cases. + if (const auto *meta = dyn_cast(sym)) + markNotInteresting(meta->getRegion()); +} + void PathSensitiveBugReport::markInteresting(const MemRegion *R, bugreporter::TrackingKind TKind) { if (!R) @@ -2265,6 +2279,17 @@ void PathSensitiveBugReport::markInteresting(const MemRegion *R, markInteresting(SR->getSymbol(), TKind); } +void PathSensitiveBugReport::markNotInteresting(const MemRegion *R) { + if (!R) + return; + + R = R->getBaseRegion(); + InterestingRegions.erase(R); + + if (const auto *SR = dyn_cast(R)) + markNotInteresting(SR->getSymbol()); +} + void PathSensitiveBugReport::markInteresting(SVal V, bugreporter::TrackingKind TKind) { markInteresting(V.getAsRegion(), TKind); diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp index cae728815b412..626ae1ae80663 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp @@ -148,5 +148,39 @@ llvm::Optional tryExpandAsInteger(StringRef Macro, return IntValue.getSExtValue(); } +OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, + bool IsBinary) { + llvm::StringMap BinOps{ +#define BINARY_OPERATION(Name, Spelling) {Spelling, BO_##Name}, +#include "clang/AST/OperationKinds.def" + }; + llvm::StringMap UnOps{ +#define UNARY_OPERATION(Name, Spelling) {Spelling, UO_##Name}, +#include "clang/AST/OperationKinds.def" + }; + + switch (OOK) { +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + case OO_##Name: \ + if (IsBinary) { \ + auto BinOpIt = BinOps.find(Spelling); \ + if (BinOpIt != BinOps.end()) \ + return OperatorKind(BinOpIt->second); \ + else \ + llvm_unreachable("operator was expected to be binary but is not"); \ + } else { \ + auto UnOpIt = UnOps.find(Spelling); \ + if (UnOpIt != UnOps.end()) \ + return OperatorKind(UnOpIt->second); \ + else \ + llvm_unreachable("operator was expected to be unary but is not"); \ + } \ + break; +#include "clang/Basic/OperatorKinds.def" + default: + llvm_unreachable("unexpected operator kind"); + } +} + } // namespace ento } // namespace clang diff --git a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp index dc268e562237f..e5f4e9ea30c97 100644 --- a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp +++ b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp @@ -79,14 +79,17 @@ ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State) { return State; } -static internal::Matcher simpleCondition(StringRef BindName) { - return binaryOperator(anyOf(hasOperatorName("<"), hasOperatorName(">"), - hasOperatorName("<="), hasOperatorName(">="), - hasOperatorName("!=")), - hasEitherOperand(ignoringParenImpCasts(declRefExpr( - to(varDecl(hasType(isInteger())).bind(BindName))))), - hasEitherOperand(ignoringParenImpCasts( - integerLiteral().bind("boundNum")))) +static internal::Matcher simpleCondition(StringRef BindName, + StringRef RefName) { + return binaryOperator( + anyOf(hasOperatorName("<"), hasOperatorName(">"), + hasOperatorName("<="), hasOperatorName(">="), + hasOperatorName("!=")), + hasEitherOperand(ignoringParenImpCasts( + declRefExpr(to(varDecl(hasType(isInteger())).bind(BindName))) + .bind(RefName))), + hasEitherOperand( + ignoringParenImpCasts(integerLiteral().bind("boundNum")))) .bind("conditionOperator"); } @@ -138,7 +141,7 @@ static internal::Matcher hasSuspiciousStmt(StringRef NodeName) { static internal::Matcher forLoopMatcher() { return forStmt( - hasCondition(simpleCondition("initVarName")), + hasCondition(simpleCondition("initVarName", "initVarRef")), // Initialization should match the form: 'int i = 6' or 'i = 42'. hasLoopInit( anyOf(declStmt(hasSingleDecl( @@ -156,17 +159,52 @@ static internal::Matcher forLoopMatcher() { hasUnaryOperand(declRefExpr( to(varDecl(allOf(equalsBoundNode("initVarName"), hasType(isInteger())))))))), - unless(hasBody(hasSuspiciousStmt("initVarName")))).bind("forLoop"); + unless(hasBody(hasSuspiciousStmt("initVarName")))) + .bind("forLoop"); } -static bool isPossiblyEscaped(const VarDecl *VD, ExplodedNode *N) { - // Global variables assumed as escaped variables. +static bool isCapturedByReference(ExplodedNode *N, const DeclRefExpr *DR) { + + // Get the lambda CXXRecordDecl + assert(DR->refersToEnclosingVariableOrCapture()); + const LocationContext *LocCtxt = N->getLocationContext(); + const Decl *D = LocCtxt->getDecl(); + const auto *MD = cast(D); + assert(MD && MD->getParent()->isLambda() && + "Captured variable should only be seen while evaluating a lambda"); + const CXXRecordDecl *LambdaCXXRec = MD->getParent(); + + // Lookup the fields of the lambda + llvm::DenseMap LambdaCaptureFields; + FieldDecl *LambdaThisCaptureField; + LambdaCXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); + + // Check if the counter is captured by reference + const VarDecl *VD = cast(DR->getDecl()->getCanonicalDecl()); + assert(VD); + const FieldDecl *FD = LambdaCaptureFields[VD]; + assert(FD && "Captured variable without a corresponding field"); + return FD->getType()->isReferenceType(); +} + +// A loop counter is considered escaped if: +// case 1: It is a global variable. +// case 2: It is a reference parameter or a reference capture. +// case 3: It is assigned to a non-const reference variable or parameter. +// case 4: Has its address taken. +static bool isPossiblyEscaped(ExplodedNode *N, const DeclRefExpr *DR) { + const VarDecl *VD = cast(DR->getDecl()->getCanonicalDecl()); + assert(VD); + // Case 1: if (VD->hasGlobalStorage()) return true; - const bool isParm = isa(VD); - // Reference parameters are assumed as escaped variables. - if (isParm && VD->getType()->isReferenceType()) + const bool IsRefParamOrCapture = + isa(VD) || DR->refersToEnclosingVariableOrCapture(); + // Case 2: + if ((DR->refersToEnclosingVariableOrCapture() && + isCapturedByReference(N, DR)) || + (IsRefParamOrCapture && VD->getType()->isReferenceType())) return true; while (!N->pred_empty()) { @@ -189,6 +227,7 @@ static bool isPossiblyEscaped(const VarDecl *VD, ExplodedNode *N) { // on VD and reference initialized by VD. ASTContext &ASTCtx = N->getLocationContext()->getAnalysisDeclContext()->getASTContext(); + // Case 3 and 4: auto Match = match(stmt(anyOf(callByRef(equalsNode(VD)), getAddrTo(equalsNode(VD)), assignedToRef(equalsNode(VD)))), @@ -199,8 +238,8 @@ static bool isPossiblyEscaped(const VarDecl *VD, ExplodedNode *N) { N = N->getFirstPred(); } - // Parameter declaration will not be found. - if (isParm) + // Reference parameter and reference capture will not be found. + if (IsRefParamOrCapture) return false; llvm_unreachable("Reached root without finding the declaration of VD"); @@ -218,7 +257,7 @@ bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx, if (Matches.empty()) return false; - auto CounterVar = Matches[0].getNodeAs("initVarName"); + const auto *CounterVarRef = Matches[0].getNodeAs("initVarRef"); llvm::APInt BoundNum = Matches[0].getNodeAs("boundNum")->getValue(); llvm::APInt InitNum = @@ -235,7 +274,7 @@ bool shouldCompletelyUnroll(const Stmt *LoopStmt, ASTContext &ASTCtx, maxStep = (BoundNum - InitNum).abs().getZExtValue(); // Check if the counter of the loop is not escaped before. - return !isPossiblyEscaped(CounterVar->getCanonicalDecl(), Pred); + return !isPossiblyEscaped(Pred, CounterVarRef); } bool madeNewBranch(ExplodedNode *N, const Stmt *LoopStmt) { diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index bc8c83132c5d7..f550aca808e56 100644 --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -592,6 +592,11 @@ class EquivalenceClass : public llvm::FoldingSetNode { RangeSet::Factory &F, ProgramStateRef State); + void dumpToStream(ProgramStateRef State, raw_ostream &os) const; + LLVM_DUMP_METHOD void dump(ProgramStateRef State) const { + dumpToStream(State, llvm::errs()); + } + /// Check equivalence data for consistency. LLVM_NODISCARD LLVM_ATTRIBUTE_UNUSED static bool isClassDataConsistent(ProgramStateRef State); @@ -669,62 +674,45 @@ LLVM_NODISCARD inline const RangeSet *getConstraint(ProgramStateRef State, return getConstraint(State, EquivalenceClass::find(State, Sym)); } +LLVM_NODISCARD ProgramStateRef setConstraint(ProgramStateRef State, + EquivalenceClass Class, + RangeSet Constraint) { + return State->set(Class, Constraint); +} + +LLVM_NODISCARD ProgramStateRef setConstraints(ProgramStateRef State, + ConstraintRangeTy Constraints) { + return State->set(Constraints); +} + //===----------------------------------------------------------------------===// // Equality/diseqiality abstraction //===----------------------------------------------------------------------===// -/// A small helper structure representing symbolic equality. +/// A small helper function for detecting symbolic (dis)equality. /// /// Equality check can have different forms (like a == b or a - b) and this /// class encapsulates those away if the only thing the user wants to check - -/// whether it's equality/diseqiality or not and have an easy access to the -/// compared symbols. -struct EqualityInfo { -public: - SymbolRef Left, Right; - // true for equality and false for disequality. - bool IsEquality = true; - - void invert() { IsEquality = !IsEquality; } - /// Extract equality information from the given symbol and the constants. - /// - /// This function assumes the following expression Sym + Adjustment != Int. - /// It is a default because the most widespread case of the equality check - /// is (A == B) + 0 != 0. - static Optional extract(SymbolRef Sym, const llvm::APSInt &Int, - const llvm::APSInt &Adjustment) { - // As of now, the only equality form supported is Sym + 0 != 0. - if (!Int.isNullValue() || !Adjustment.isNullValue()) - return llvm::None; - - return extract(Sym); - } - /// Extract equality information from the given symbol. - static Optional extract(SymbolRef Sym) { - return EqualityExtractor().Visit(Sym); +/// whether it's equality/diseqiality or not. +/// +/// \returns true if assuming this Sym to be true means equality of operands +/// false if it means disequality of operands +/// None otherwise +Optional meansEquality(const SymSymExpr *Sym) { + switch (Sym->getOpcode()) { + case BO_Sub: + // This case is: A - B != 0 -> disequality check. + return false; + case BO_EQ: + // This case is: A == B != 0 -> equality check. + return true; + case BO_NE: + // This case is: A != B != 0 -> diseqiality check. + return false; + default: + return llvm::None; } - -private: - class EqualityExtractor - : public SymExprVisitor> { - public: - Optional VisitSymSymExpr(const SymSymExpr *Sym) const { - switch (Sym->getOpcode()) { - case BO_Sub: - // This case is: A - B != 0 -> disequality check. - return EqualityInfo{Sym->getLHS(), Sym->getRHS(), false}; - case BO_EQ: - // This case is: A == B != 0 -> equality check. - return EqualityInfo{Sym->getLHS(), Sym->getRHS(), true}; - case BO_NE: - // This case is: A != B != 0 -> diseqiality check. - return EqualityInfo{Sym->getLHS(), Sym->getRHS(), false}; - default: - return llvm::None; - } - } - }; -}; +} //===----------------------------------------------------------------------===// // Intersection functions @@ -855,7 +843,13 @@ class SymbolicRangeInferrer } RangeSet VisitSymSymExpr(const SymSymExpr *Sym) { - return VisitBinaryOperator(Sym); + return intersect( + RangeFactory, + // If Sym is (dis)equality, we might have some information + // on that in our equality classes data structure. + getRangeForEqualities(Sym), + // And we should always check what we can get from the operands. + VisitBinaryOperator(Sym)); } private: @@ -896,9 +890,6 @@ class SymbolicRangeInferrer // calculate the effective range set by intersecting the range set // for A - B and the negated range set of B - A. getRangeForNegatedSub(Sym), - // If Sym is (dis)equality, we might have some information on that - // in our equality classes data structure. - getRangeForEqualities(Sym), // If Sym is a comparison expression (except <=>), // find any other comparisons with the same operands. // See function description. @@ -1177,17 +1168,21 @@ class SymbolicRangeInferrer return llvm::None; } - Optional getRangeForEqualities(SymbolRef Sym) { - Optional Equality = EqualityInfo::extract(Sym); + Optional getRangeForEqualities(const SymSymExpr *Sym) { + Optional Equality = meansEquality(Sym); if (!Equality) return llvm::None; - if (Optional AreEqual = EquivalenceClass::areEqual( - State, Equality->Left, Equality->Right)) { - if (*AreEqual == Equality->IsEquality) { + if (Optional AreEqual = + EquivalenceClass::areEqual(State, Sym->getLHS(), Sym->getRHS())) { + // Here we cover two cases at once: + // * if Sym is equality and its operands are known to be equal -> true + // * if Sym is disequality and its operands are disequal -> true + if (*AreEqual == *Equality) { return getTrueRange(Sym->getType()); } + // Opposite combinations result in false. return getFalseRange(Sym->getType()); } @@ -1373,6 +1368,208 @@ RangeSet SymbolicRangeInferrer::VisitBinaryOperator(Range LHS, return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)}; } +//===----------------------------------------------------------------------===// +// Constraint assignment logic +//===----------------------------------------------------------------------===// + +/// ConstraintAssignorBase is a small utility class that unifies visitor +/// for ranges with a visitor for constraints (rangeset/range/constant). +/// +/// It is designed to have one derived class, but generally it can have more. +/// Derived class can control which types we handle by defining methods of the +/// following form: +/// +/// bool handle${SYMBOL}To${CONSTRAINT}(const SYMBOL *Sym, +/// CONSTRAINT Constraint); +/// +/// where SYMBOL is the type of the symbol (e.g. SymSymExpr, SymbolCast, etc.) +/// CONSTRAINT is the type of constraint (RangeSet/Range/Const) +/// return value signifies whether we should try other handle methods +/// (i.e. false would mean to stop right after calling this method) +template class ConstraintAssignorBase { +public: + using Const = const llvm::APSInt &; + +#define DISPATCH(CLASS) return assign##CLASS##Impl(cast(Sym), Constraint) + +#define ASSIGN(CLASS, TO, SYM, CONSTRAINT) \ + if (!static_cast(this)->assign##CLASS##To##TO(SYM, CONSTRAINT)) \ + return false + + void assign(SymbolRef Sym, RangeSet Constraint) { + assignImpl(Sym, Constraint); + } + + bool assignImpl(SymbolRef Sym, RangeSet Constraint) { + switch (Sym->getKind()) { +#define SYMBOL(Id, Parent) \ + case SymExpr::Id##Kind: \ + DISPATCH(Id); +#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" + } + llvm_unreachable("Unknown SymExpr kind!"); + } + +#define DEFAULT_ASSIGN(Id) \ + bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) { \ + return true; \ + } \ + bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \ + bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; } + + // When we dispatch for constraint types, we first try to check + // if the new constraint is the constant and try the corresponding + // assignor methods. If it didn't interrupt, we can proceed to the + // range, and finally to the range set. +#define CONSTRAINT_DISPATCH(Id) \ + if (const llvm::APSInt *Const = Constraint.getConcreteValue()) { \ + ASSIGN(Id, Const, Sym, *Const); \ + } \ + if (Constraint.size() == 1) { \ + ASSIGN(Id, Range, Sym, *Constraint.begin()); \ + } \ + ASSIGN(Id, RangeSet, Sym, Constraint) + + // Our internal assign method first tries to call assignor methods for all + // constraint types that apply. And if not interrupted, continues with its + // parent class. +#define SYMBOL(Id, Parent) \ + bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) { \ + CONSTRAINT_DISPATCH(Id); \ + DISPATCH(Parent); \ + } \ + DEFAULT_ASSIGN(Id) +#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent) +#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" + + // Default implementations for the top class that doesn't have parents. + bool assignSymExprImpl(const SymExpr *Sym, RangeSet Constraint) { + CONSTRAINT_DISPATCH(SymExpr); + return true; + } + DEFAULT_ASSIGN(SymExpr); + +#undef DISPATCH +#undef CONSTRAINT_DISPATCH +#undef DEFAULT_ASSIGN +#undef ASSIGN +}; + +/// A little component aggregating all of the reasoning we have about +/// assigning new constraints to symbols. +/// +/// The main purpose of this class is to associate constraints to symbols, +/// and impose additional constraints on other symbols, when we can imply +/// them. +/// +/// It has a nice symmetry with SymbolicRangeInferrer. When the latter +/// can provide more precise ranges by looking into the operands of the +/// expression in question, ConstraintAssignor looks into the operands +/// to see if we can imply more from the new constraint. +class ConstraintAssignor : public ConstraintAssignorBase { +public: + template + LLVM_NODISCARD static ProgramStateRef + assign(ProgramStateRef State, SValBuilder &Builder, RangeSet::Factory &F, + ClassOrSymbol CoS, RangeSet NewConstraint) { + if (!State || NewConstraint.isEmpty()) + return nullptr; + + ConstraintAssignor Assignor{State, Builder, F}; + return Assignor.assign(CoS, NewConstraint); + } + + inline bool assignSymExprToConst(const SymExpr *Sym, Const Constraint); + inline bool assignSymSymExprToRangeSet(const SymSymExpr *Sym, + RangeSet Constraint); + +private: + ConstraintAssignor(ProgramStateRef State, SValBuilder &Builder, + RangeSet::Factory &F) + : State(State), Builder(Builder), RangeFactory(F) {} + using Base = ConstraintAssignorBase; + + /// Base method for handling new constraints for symbols. + LLVM_NODISCARD ProgramStateRef assign(SymbolRef Sym, RangeSet NewConstraint) { + // All constraints are actually associated with equivalence classes, and + // that's what we are going to do first. + State = assign(EquivalenceClass::find(State, Sym), NewConstraint); + if (!State) + return nullptr; + + // And after that we can check what other things we can get from this + // constraint. + Base::assign(Sym, NewConstraint); + return State; + } + + /// Base method for handling new constraints for classes. + LLVM_NODISCARD ProgramStateRef assign(EquivalenceClass Class, + RangeSet NewConstraint) { + // There is a chance that we might need to update constraints for the + // classes that are known to be disequal to Class. + // + // In order for this to be even possible, the new constraint should + // be simply a constant because we can't reason about range disequalities. + if (const llvm::APSInt *Point = NewConstraint.getConcreteValue()) { + + ConstraintRangeTy Constraints = State->get(); + ConstraintRangeTy::Factory &CF = State->get_context(); + + // Add new constraint. + Constraints = CF.add(Constraints, Class, NewConstraint); + + for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) { + RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange( + RangeFactory, State, DisequalClass); + + UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point); + + // If we end up with at least one of the disequal classes to be + // constrained with an empty range-set, the state is infeasible. + if (UpdatedConstraint.isEmpty()) + return nullptr; + + Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint); + } + assert(areFeasible(Constraints) && "Constraint manager shouldn't produce " + "a state with infeasible constraints"); + + return setConstraints(State, Constraints); + } + + return setConstraint(State, Class, NewConstraint); + } + + ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS, + SymbolRef RHS) { + return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS); + } + + ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS, + SymbolRef RHS) { + return EquivalenceClass::merge(RangeFactory, State, LHS, RHS); + } + + LLVM_NODISCARD Optional interpreteAsBool(RangeSet Constraint) { + assert(!Constraint.isEmpty() && "Empty ranges shouldn't get here"); + + if (Constraint.getConcreteValue()) + return !Constraint.getConcreteValue()->isNullValue(); + + APSIntType T{Constraint.getMinValue()}; + Const Zero = T.getZeroValue(); + if (!Constraint.contains(Zero)) + return true; + + return llvm::None; + } + + ProgramStateRef State; + SValBuilder &Builder; + RangeSet::Factory &RangeFactory; +}; + //===----------------------------------------------------------------------===// // Constraint manager implementation details //===----------------------------------------------------------------------===// @@ -1407,6 +1604,15 @@ class RangeConstraintManager : public RangedConstraintManager { void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n", unsigned int Space = 0, bool IsDot = false) const override; + void printConstraints(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", unsigned int Space = 0, + bool IsDot = false) const; + void printEquivalenceClasses(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", unsigned int Space = 0, + bool IsDot = false) const; + void printDisequalities(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", unsigned int Space = 0, + bool IsDot = false) const; //===------------------------------------------------------------------===// // Implementation for interface from RangedConstraintManager. @@ -1449,6 +1655,10 @@ class RangeConstraintManager : public RangedConstraintManager { RangeSet getRange(ProgramStateRef State, SymbolRef Sym); RangeSet getRange(ProgramStateRef State, EquivalenceClass Class); + ProgramStateRef setRange(ProgramStateRef State, SymbolRef Sym, + RangeSet Range); + ProgramStateRef setRange(ProgramStateRef State, EquivalenceClass Class, + RangeSet Range); RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, @@ -1465,140 +1675,63 @@ class RangeConstraintManager : public RangedConstraintManager { RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment); +}; - //===------------------------------------------------------------------===// - // Equality tracking implementation - //===------------------------------------------------------------------===// - - ProgramStateRef trackEQ(RangeSet NewConstraint, ProgramStateRef State, - SymbolRef Sym, const llvm::APSInt &Int, - const llvm::APSInt &Adjustment) { - return track(NewConstraint, State, Sym, Int, Adjustment); +bool ConstraintAssignor::assignSymExprToConst(const SymExpr *Sym, + const llvm::APSInt &Constraint) { + llvm::SmallSet SimplifiedClasses; + // Iterate over all equivalence classes and try to simplify them. + ClassMembersTy Members = State->get(); + for (std::pair ClassToSymbolSet : Members) { + EquivalenceClass Class = ClassToSymbolSet.first; + State = Class.simplify(Builder, RangeFactory, State); + if (!State) + return false; + SimplifiedClasses.insert(Class); } - ProgramStateRef trackNE(RangeSet NewConstraint, ProgramStateRef State, - SymbolRef Sym, const llvm::APSInt &Int, - const llvm::APSInt &Adjustment) { - return track(NewConstraint, State, Sym, Int, Adjustment); + // Trivial equivalence classes (those that have only one symbol member) are + // not stored in the State. Thus, we must skim through the constraints as + // well. And we try to simplify symbols in the constraints. + ConstraintRangeTy Constraints = State->get(); + for (std::pair ClassConstraint : Constraints) { + EquivalenceClass Class = ClassConstraint.first; + if (SimplifiedClasses.count(Class)) // Already simplified. + continue; + State = Class.simplify(Builder, RangeFactory, State); + if (!State) + return false; } - template - ProgramStateRef track(RangeSet NewConstraint, ProgramStateRef State, - SymbolRef Sym, const llvm::APSInt &Int, - const llvm::APSInt &Adjustment) { - if (NewConstraint.isEmpty()) - // This is an infeasible assumption. - return nullptr; - - if (ProgramStateRef NewState = setConstraint(State, Sym, NewConstraint)) { - if (auto Equality = EqualityInfo::extract(Sym, Int, Adjustment)) { - // If the original assumption is not Sym + Adjustment !=/ Int, - // we should invert IsEquality flag. - Equality->IsEquality = Equality->IsEquality != EQ; - return track(NewState, *Equality); - } + return true; +} - return NewState; - } +bool ConstraintAssignor::assignSymSymExprToRangeSet(const SymSymExpr *Sym, + RangeSet Constraint) { + Optional ConstraintAsBool = interpreteAsBool(Constraint); - return nullptr; - } + if (!ConstraintAsBool) + return true; - ProgramStateRef track(ProgramStateRef State, EqualityInfo ToTrack) { - if (ToTrack.IsEquality) { - return trackEquality(State, ToTrack.Left, ToTrack.Right); + if (Optional Equality = meansEquality(Sym)) { + // Here we cover two cases: + // * if Sym is equality and the new constraint is true -> Sym's operands + // should be marked as equal + // * if Sym is disequality and the new constraint is false -> Sym's + // operands should be also marked as equal + if (*Equality == *ConstraintAsBool) { + State = trackEquality(State, Sym->getLHS(), Sym->getRHS()); + } else { + // Other combinations leave as with disequal operands. + State = trackDisequality(State, Sym->getLHS(), Sym->getRHS()); } - return trackDisequality(State, ToTrack.Left, ToTrack.Right); - } - - ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS, - SymbolRef RHS) { - return EquivalenceClass::markDisequal(F, State, LHS, RHS); - } - ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS, - SymbolRef RHS) { - return EquivalenceClass::merge(F, State, LHS, RHS); - } - - LLVM_NODISCARD ProgramStateRef setConstraint(ProgramStateRef State, - EquivalenceClass Class, - RangeSet Constraint) { - ConstraintRangeTy Constraints = State->get(); - ConstraintRangeTy::Factory &CF = State->get_context(); - - assert(!Constraint.isEmpty() && "New constraint should not be empty"); - - // Add new constraint. - Constraints = CF.add(Constraints, Class, Constraint); - - // There is a chance that we might need to update constraints for the - // classes that are known to be disequal to Class. - // - // In order for this to be even possible, the new constraint should - // be simply a constant because we can't reason about range disequalities. - if (const llvm::APSInt *Point = Constraint.getConcreteValue()) - for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) { - RangeSet UpdatedConstraint = getRange(State, DisequalClass); - UpdatedConstraint = F.deletePoint(UpdatedConstraint, *Point); - - // If we end up with at least one of the disequal classes to be - // constrained with an empty range-set, the state is infeasible. - if (UpdatedConstraint.isEmpty()) - return nullptr; - - Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint); - } - - assert(areFeasible(Constraints) && "Constraint manager shouldn't produce " - "a state with infeasible constraints"); - - return State->set(Constraints); - } - - // Associate a constraint to a symbolic expression. First, we set the - // constraint in the State, then we try to simplify existing symbolic - // expressions based on the newly set constraint. - LLVM_NODISCARD inline ProgramStateRef - setConstraint(ProgramStateRef State, SymbolRef Sym, RangeSet Constraint) { - assert(State); - - State = setConstraint(State, EquivalenceClass::find(State, Sym), Constraint); if (!State) - return nullptr; - - // We have a chance to simplify existing symbolic values if the new - // constraint is a constant. - if (!Constraint.getConcreteValue()) - return State; - - llvm::SmallSet SimplifiedClasses; - // Iterate over all equivalence classes and try to simplify them. - ClassMembersTy Members = State->get(); - for (std::pair ClassToSymbolSet : Members) { - EquivalenceClass Class = ClassToSymbolSet.first; - State = Class.simplify(getSValBuilder(), F, State); - if (!State) - return nullptr; - SimplifiedClasses.insert(Class); - } - - // Trivial equivalence classes (those that have only one symbol member) are - // not stored in the State. Thus, we must skim through the constraints as - // well. And we try to simplify symbols in the constraints. - ConstraintRangeTy Constraints = State->get(); - for (std::pair ClassConstraint : Constraints) { - EquivalenceClass Class = ClassConstraint.first; - if (SimplifiedClasses.count(Class)) // Already simplified. - continue; - State = Class.simplify(getSValBuilder(), F, State); - if (!State) - return nullptr; - } - - return State; + return false; } -}; + + return true; +} } // end anonymous namespace @@ -1630,6 +1763,15 @@ ConstraintMap ento::getConstraintMap(ProgramStateRef State) { // EqualityClass implementation details //===----------------------------------------------------------------------===// +LLVM_DUMP_METHOD void EquivalenceClass::dumpToStream(ProgramStateRef State, + raw_ostream &os) const { + SymbolSet ClassMembers = getClassMembers(State); + for (const SymbolRef &MemberSym : ClassMembers) { + MemberSym->dump(); + os << "\n"; + } +} + inline EquivalenceClass EquivalenceClass::find(ProgramStateRef State, SymbolRef Sym) { assert(State && "State should not be null"); @@ -2239,9 +2381,10 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State, return SymbolicRangeInferrer::inferRange(F, State, Sym); } -RangeSet RangeConstraintManager::getRange(ProgramStateRef State, - EquivalenceClass Class) { - return SymbolicRangeInferrer::inferRange(F, State, Class); +ProgramStateRef RangeConstraintManager::setRange(ProgramStateRef State, + SymbolRef Sym, + RangeSet Range) { + return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym, Range); } //===------------------------------------------------------------------------=== @@ -2269,7 +2412,7 @@ RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, RangeSet New = getRange(St, Sym); New = F.deletePoint(New, Point); - return trackNE(New, St, Sym, Int, Adjustment); + return setRange(St, Sym, New); } ProgramStateRef @@ -2286,7 +2429,7 @@ RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, RangeSet New = getRange(St, Sym); New = F.intersect(New, AdjInt); - return trackEQ(New, St, Sym, Int, Adjustment); + return setRange(St, Sym, New); } RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St, @@ -2323,7 +2466,7 @@ RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { RangeSet New = getSymLTRange(St, Sym, Int, Adjustment); - return trackNE(New, St, Sym, Int, Adjustment); + return setRange(St, Sym, New); } RangeSet RangeConstraintManager::getSymGTRange(ProgramStateRef St, @@ -2360,7 +2503,7 @@ RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { RangeSet New = getSymGTRange(St, Sym, Int, Adjustment); - return trackNE(New, St, Sym, Int, Adjustment); + return setRange(St, Sym, New); } RangeSet RangeConstraintManager::getSymGERange(ProgramStateRef St, @@ -2397,7 +2540,7 @@ RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { RangeSet New = getSymGERange(St, Sym, Int, Adjustment); - return New.isEmpty() ? nullptr : setConstraint(St, Sym, New); + return setRange(St, Sym, New); } RangeSet @@ -2441,7 +2584,7 @@ RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, const llvm::APSInt &Int, const llvm::APSInt &Adjustment) { RangeSet New = getSymLERange(St, Sym, Int, Adjustment); - return New.isEmpty() ? nullptr : setConstraint(St, Sym, New); + return setRange(St, Sym, New); } ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange( @@ -2451,7 +2594,7 @@ ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange( if (New.isEmpty()) return nullptr; RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment); - return Out.isEmpty() ? nullptr : setConstraint(State, Sym, Out); + return setRange(State, Sym, Out); } ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange( @@ -2460,7 +2603,7 @@ ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange( RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment); RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment); RangeSet New(F.add(RangeLT, RangeGT)); - return New.isEmpty() ? nullptr : setConstraint(State, Sym, New); + return setRange(State, Sym, New); } //===----------------------------------------------------------------------===// @@ -2470,6 +2613,16 @@ ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange( void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State, const char *NL, unsigned int Space, bool IsDot) const { + printConstraints(Out, State, NL, Space, IsDot); + printEquivalenceClasses(Out, State, NL, Space, IsDot); + printDisequalities(Out, State, NL, Space, IsDot); +} + +void RangeConstraintManager::printConstraints(raw_ostream &Out, + ProgramStateRef State, + const char *NL, + unsigned int Space, + bool IsDot) const { ConstraintRangeTy Constraints = State->get(); Indent(Out, Space, IsDot) << "\"constraints\": "; @@ -2503,3 +2656,140 @@ void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State, --Space; Indent(Out, Space, IsDot) << "]," << NL; } + +static std::string toString(const SymbolRef &Sym) { + std::string S; + llvm::raw_string_ostream O(S); + Sym->dumpToStream(O); + return O.str(); +} + +static std::string toString(ProgramStateRef State, EquivalenceClass Class) { + SymbolSet ClassMembers = Class.getClassMembers(State); + llvm::SmallVector ClassMembersSorted(ClassMembers.begin(), + ClassMembers.end()); + llvm::sort(ClassMembersSorted, + [](const SymbolRef &LHS, const SymbolRef &RHS) { + return toString(LHS) < toString(RHS); + }); + + bool FirstMember = true; + + std::string Str; + llvm::raw_string_ostream Out(Str); + Out << "[ "; + for (SymbolRef ClassMember : ClassMembersSorted) { + if (FirstMember) + FirstMember = false; + else + Out << ", "; + Out << "\"" << ClassMember << "\""; + } + Out << " ]"; + return Out.str(); +} + +void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out, + ProgramStateRef State, + const char *NL, + unsigned int Space, + bool IsDot) const { + ClassMembersTy Members = State->get(); + + Indent(Out, Space, IsDot) << "\"equivalence_classes\": "; + if (Members.isEmpty()) { + Out << "null," << NL; + return; + } + + std::set MembersStr; + for (std::pair ClassToSymbolSet : Members) + MembersStr.insert(toString(State, ClassToSymbolSet.first)); + + ++Space; + Out << '[' << NL; + bool FirstClass = true; + for (const std::string &Str : MembersStr) { + if (FirstClass) { + FirstClass = false; + } else { + Out << ','; + Out << NL; + } + Indent(Out, Space, IsDot); + Out << Str; + } + Out << NL; + + --Space; + Indent(Out, Space, IsDot) << "]," << NL; +} + +void RangeConstraintManager::printDisequalities(raw_ostream &Out, + ProgramStateRef State, + const char *NL, + unsigned int Space, + bool IsDot) const { + DisequalityMapTy Disequalities = State->get(); + + Indent(Out, Space, IsDot) << "\"disequality_info\": "; + if (Disequalities.isEmpty()) { + Out << "null," << NL; + return; + } + + // Transform the disequality info to an ordered map of + // [string -> (ordered set of strings)] + using EqClassesStrTy = std::set; + using DisequalityInfoStrTy = std::map; + DisequalityInfoStrTy DisequalityInfoStr; + for (std::pair ClassToDisEqSet : Disequalities) { + EquivalenceClass Class = ClassToDisEqSet.first; + ClassSet DisequalClasses = ClassToDisEqSet.second; + EqClassesStrTy MembersStr; + for (EquivalenceClass DisEqClass : DisequalClasses) + MembersStr.insert(toString(State, DisEqClass)); + DisequalityInfoStr.insert({toString(State, Class), MembersStr}); + } + + ++Space; + Out << '[' << NL; + bool FirstClass = true; + for (std::pair ClassToDisEqSet : + DisequalityInfoStr) { + const std::string &Class = ClassToDisEqSet.first; + if (FirstClass) { + FirstClass = false; + } else { + Out << ','; + Out << NL; + } + Indent(Out, Space, IsDot) << "{" << NL; + unsigned int DisEqSpace = Space + 1; + Indent(Out, DisEqSpace, IsDot) << "\"class\": "; + Out << Class; + const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second; + if (!DisequalClasses.empty()) { + Out << "," << NL; + Indent(Out, DisEqSpace, IsDot) << "\"disequal_to\": [" << NL; + unsigned int DisEqClassSpace = DisEqSpace + 1; + Indent(Out, DisEqClassSpace, IsDot); + bool FirstDisEqClass = true; + for (const std::string &DisEqClass : DisequalClasses) { + if (FirstDisEqClass) { + FirstDisEqClass = false; + } else { + Out << ',' << NL; + Indent(Out, DisEqClassSpace, IsDot); + } + Out << DisEqClass; + } + Out << "]" << NL; + } + Indent(Out, Space, IsDot) << "}"; + } + Out << NL; + + --Space; + Indent(Out, Space, IsDot) << "]," << NL; +} diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index b7ca8e8ca9cd4..b459b5adb5110 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -192,12 +192,19 @@ SValBuilder::getConjuredHeapSymbolVal(const Expr *E, const LocationContext *LCtx, unsigned VisitCount) { QualType T = E->getType(); - assert(Loc::isLocType(T)); - assert(SymbolManager::canSymbolicate(T)); - if (T->isNullPtrType()) - return makeZeroVal(T); + return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount); +} + +DefinedOrUnknownSVal +SValBuilder::getConjuredHeapSymbolVal(const Expr *E, + const LocationContext *LCtx, + QualType type, unsigned VisitCount) { + assert(Loc::isLocType(type)); + assert(SymbolManager::canSymbolicate(type)); + if (type->isNullPtrType()) + return makeZeroVal(type); - SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount); + SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount); return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym)); } @@ -712,9 +719,23 @@ SVal SValBuilder::evalCastSubKind(loc::MemRegionVal V, QualType CastTy, // symbols to use, only content metadata. return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR)); - if (const SymbolicRegion *SymR = R->getSymbolicBase()) - return makeNonLoc(SymR->getSymbol(), BO_NE, - BasicVals.getZeroWithPtrWidth(), CastTy); + if (const SymbolicRegion *SymR = R->getSymbolicBase()) { + SymbolRef Sym = SymR->getSymbol(); + QualType Ty = Sym->getType(); + // This change is needed for architectures with varying + // pointer widths. See the amdgcn opencl reproducer with + // this change as an example: solver-sym-simplification-ptr-bool.cl + // FIXME: We could encounter a reference here, + // try returning a concrete 'true' since it might + // be easier on the solver. + // FIXME: Cleanup remainder of `getZeroWithPtrWidth ()` + // and `getIntWithPtrWidth()` functions to prevent future + // confusion + const llvm::APSInt &Zero = Ty->isReferenceType() + ? BasicVals.getZeroWithPtrWidth() + : BasicVals.getZeroWithTypeSize(Ty); + return makeNonLoc(Sym, BO_NE, Zero, CastTy); + } // Non-symbolic memory regions are always true. return makeTruthVal(true, CastTy); } diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 03b5c04f553f2..31de49033ac2b 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -128,7 +128,8 @@ class AnalysisConsumer : public AnalysisASTConsumer, Plugins(plugins), Injector(injector), CTU(CI), MacroExpansions(CI.getLangOpts()) { DigestAnalyzerOptions(); - if (Opts->PrintStats || Opts->ShouldSerializeStats) { + if (Opts->AnalyzerDisplayProgress || Opts->PrintStats || + Opts->ShouldSerializeStats) { AnalyzerTimers = std::make_unique( "analyzer", "Analyzer timers"); SyntaxCheckTimer = std::make_unique( @@ -138,6 +139,9 @@ class AnalysisConsumer : public AnalysisASTConsumer, BugReporterTimer = std::make_unique( "bugreporter", "Path-sensitive report post-processing time", *AnalyzerTimers); + } + + if (Opts->PrintStats || Opts->ShouldSerializeStats) { llvm::EnableStatistics(/* PrintOnExit= */ false); } @@ -183,6 +187,14 @@ class AnalysisConsumer : public AnalysisASTConsumer, } } + void DisplayTime(llvm::TimeRecord &Time) { + if (!Opts->AnalyzerDisplayProgress) { + return; + } + llvm::errs() << " : " << llvm::format("%1.1f", Time.getWallTime() * 1000) + << " ms\n"; + } + void DisplayFunction(const Decl *D, AnalysisMode Mode, ExprEngine::InliningModes IMode) { if (!Opts->AnalyzerDisplayProgress) @@ -210,7 +222,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!"); llvm::errs() << ": " << Loc.getFilename() << ' ' - << AnalysisDeclContext::getFunctionName(D) << '\n'; + << AnalysisDeclContext::getFunctionName(D); } } @@ -608,19 +620,26 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized()) return; - DisplayFunction(D, Mode, IMode); CFG *DeclCFG = Mgr->getCFG(D); if (DeclCFG) MaxCFGSize.updateMax(DeclCFG->size()); + DisplayFunction(D, Mode, IMode); BugReporter BR(*Mgr); if (Mode & AM_Syntax) { - if (SyntaxCheckTimer) + llvm::TimeRecord CheckerStartTime; + if (SyntaxCheckTimer) { + CheckerStartTime = SyntaxCheckTimer->getTotalTime(); SyntaxCheckTimer->startTimer(); + } checkerMgr->runCheckersOnASTBody(D, *Mgr, BR); - if (SyntaxCheckTimer) + if (SyntaxCheckTimer) { SyntaxCheckTimer->stopTimer(); + llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime(); + CheckerEndTime -= CheckerStartTime; + DisplayTime(CheckerEndTime); + } } BR.FlushReports(); @@ -651,12 +670,19 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D, ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode); // Execute the worklist algorithm. - if (ExprEngineTimer) + llvm::TimeRecord ExprEngineStartTime; + if (ExprEngineTimer) { + ExprEngineStartTime = ExprEngineTimer->getTotalTime(); ExprEngineTimer->startTimer(); + } Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D), Mgr->options.MaxNodesPerTopLevelFunction); - if (ExprEngineTimer) + if (ExprEngineTimer) { ExprEngineTimer->stopTimer(); + llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime(); + ExprEngineEndTime -= ExprEngineStartTime; + DisplayTime(ExprEngineEndTime); + } if (!Mgr->options.DumpExplodedGraphTo.empty()) Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo); diff --git a/clang/runtime/CMakeLists.txt b/clang/runtime/CMakeLists.txt index 1716c53b031ef..61b1c60bf590b 100644 --- a/clang/runtime/CMakeLists.txt +++ b/clang/runtime/CMakeLists.txt @@ -82,7 +82,7 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/) -DLLVM_LIT_ARGS=${LLVM_LIT_ARGS} -DCOMPILER_RT_OUTPUT_DIR=${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION} -DCOMPILER_RT_EXEC_OUTPUT_DIR=${LLVM_RUNTIME_OUTPUT_INTDIR} - -DCOMPILER_RT_INSTALL_PATH:STRING=lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION} + -DCOMPILER_RT_INSTALL_PATH:PATH=lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION} -DCOMPILER_RT_INCLUDE_TESTS=${LLVM_INCLUDE_TESTS} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DLLVM_LIBDIR_SUFFIX=${LLVM_LIBDIR_SUFFIX} diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index 87984d02c2f6e..ff64c5b63e3c8 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -978,9 +978,90 @@ template void swap(unique_ptr &x, unique_ptr &y) noexcept { x.swap(y); } + +template +bool operator==(const unique_ptr &x, const unique_ptr &y); + +template +bool operator!=(const unique_ptr &x, const unique_ptr &y); + +template +bool operator<(const unique_ptr &x, const unique_ptr &y); + +template +bool operator>(const unique_ptr &x, const unique_ptr &y); + +template +bool operator<=(const unique_ptr &x, const unique_ptr &y); + +template +bool operator>=(const unique_ptr &x, const unique_ptr &y); + +template +bool operator==(const unique_ptr &x, nullptr_t y); + +template +bool operator!=(const unique_ptr &x, nullptr_t y); + +template +bool operator<(const unique_ptr &x, nullptr_t y); + +template +bool operator>(const unique_ptr &x, nullptr_t y); + +template +bool operator<=(const unique_ptr &x, nullptr_t y); + +template +bool operator>=(const unique_ptr &x, nullptr_t y); + +template +bool operator==(nullptr_t x, const unique_ptr &y); + +template +bool operator!=(nullptr_t x, const unique_ptr &y); + +template +bool operator>(nullptr_t x, const unique_ptr &y); + +template +bool operator<(nullptr_t x, const unique_ptr &y); + +template +bool operator>=(nullptr_t x, const unique_ptr &y); + +template +bool operator<=(nullptr_t x, const unique_ptr &y); + +template +unique_ptr make_unique(Args &&...args); + +#if __cplusplus >= 202002L + +template +unique_ptr make_unique_for_overwrite(); + +#endif + } // namespace std #endif +namespace std { +template +class basic_ostream; + +using ostream = basic_ostream; + +extern std::ostream cout; + +ostream &operator<<(ostream &, const string &); + +#if __cplusplus >= 202002L +template +ostream &operator<<(ostream &, const std::unique_ptr &); +#endif +} // namespace std + #ifdef TEST_INLINABLE_ALLOCATORS namespace std { void *malloc(size_t); diff --git a/clang/test/Analysis/analyzer-display-progress.cpp b/clang/test/Analysis/analyzer-display-progress.cpp index b54044a0a3619..6767b3770abfc 100644 --- a/clang/test/Analysis/analyzer-display-progress.cpp +++ b/clang/test/Analysis/analyzer-display-progress.cpp @@ -20,11 +20,11 @@ namespace ns { }; } -// CHECK: analyzer-display-progress.cpp f() -// CHECK: analyzer-display-progress.cpp g() -// CHECK: analyzer-display-progress.cpp h() -// CHECK: analyzer-display-progress.cpp SomeStruct::f() -// CHECK: analyzer-display-progress.cpp SomeOtherStruct::f() -// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(int) -// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(float, ::SomeStruct) -// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(float, struct ns::SomeStruct) +// CHECK: analyzer-display-progress.cpp f() : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp g() : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp h() : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp SomeStruct::f() : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp SomeOtherStruct::f() : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(int) : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(float, ::SomeStruct) : {{[0-9]+}} +// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(float, struct ns::SomeStruct) : {{[0-9]+}} diff --git a/clang/test/Analysis/equality_tracking.c b/clang/test/Analysis/equality_tracking.c index 086db1070c641..bf84e51ce7023 100644 --- a/clang/test/Analysis/equality_tracking.c +++ b/clang/test/Analysis/equality_tracking.c @@ -219,3 +219,17 @@ void avoidInfeasibleConstraintforLT(int a, int b) { if (c < 0) ; } + +void implyDisequalityFromGT(int a, int b) { + if (a > b) { + clang_analyzer_eval(a == b); // expected-warning{{FALSE}} + clang_analyzer_eval(a != b); // expected-warning{{TRUE}} + } +} + +void implyDisequalityFromLT(int a, int b) { + if (a < b) { + clang_analyzer_eval(a == b); // expected-warning{{FALSE}} + clang_analyzer_eval(a != b); // expected-warning{{TRUE}} + } +} diff --git a/clang/test/Analysis/expr-inspection-printState-diseq-info.c b/clang/test/Analysis/expr-inspection-printState-diseq-info.c new file mode 100644 index 0000000000000..8db3722a8f263 --- /dev/null +++ b/clang/test/Analysis/expr-inspection-printState-diseq-info.c @@ -0,0 +1,34 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=debug.ExprInspection %s 2>&1 | FileCheck %s + +void clang_analyzer_printState(); + +void test_disequality_info(int e0, int b0, int b1, int c0) { + int e1 = e0 - b0; + if (b0 == 2) { + int e2 = e1 - b1; + if (e2 > 0) { + if (b1 != c0) + clang_analyzer_printState(); + } + } +} + + // CHECK: "disequality_info": [ + // CHECK-NEXT: { + // CHECK-NEXT: "class": [ "(reg_$0) - 2" ], + // CHECK-NEXT: "disequal_to": [ + // CHECK-NEXT: [ "reg_$2" ]] + // CHECK-NEXT: }, + // CHECK-NEXT: { + // CHECK-NEXT: "class": [ "reg_$2" ], + // CHECK-NEXT: "disequal_to": [ + // CHECK-NEXT: [ "(reg_$0) - 2" ], + // CHECK-NEXT: [ "reg_$3" ]] + // CHECK-NEXT: }, + // CHECK-NEXT: { + // CHECK-NEXT: "class": [ "reg_$3" ], + // CHECK-NEXT: "disequal_to": [ + // CHECK-NEXT: [ "reg_$2" ]] + // CHECK-NEXT: } + // CHECK-NEXT: ], diff --git a/clang/test/Analysis/expr-inspection-printState-eq-classes.c b/clang/test/Analysis/expr-inspection-printState-eq-classes.c new file mode 100644 index 0000000000000..34514335f9e80 --- /dev/null +++ b/clang/test/Analysis/expr-inspection-printState-eq-classes.c @@ -0,0 +1,21 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=debug.ExprInspection %s 2>&1 | FileCheck %s + +void clang_analyzer_printState(); + +void test_equivalence_classes(int a, int b, int c, int d) { + if (a + b != c) + return; + if (a != d) + return; + if (b != 0) + return; + clang_analyzer_printState(); + (void)(a * b * c * d); + return; +} + + // CHECK: "equivalence_classes": [ + // CHECK-NEXT: [ "((reg_$0) + (reg_$1)) != (reg_$2)", "(reg_$0) != (reg_$2)" ], + // CHECK-NEXT: [ "(reg_$0) + (reg_$1)", "reg_$0", "reg_$2", "reg_$3" ] + // CHECK-NEXT: ], diff --git a/clang/test/Analysis/expr-inspection.c b/clang/test/Analysis/expr-inspection.c index 283fa9bdb724a..76118a76e71ca 100644 --- a/clang/test/Analysis/expr-inspection.c +++ b/clang/test/Analysis/expr-inspection.c @@ -38,6 +38,8 @@ void foo(int x) { // CHECK-NEXT: "constraints": [ // CHECK-NEXT: { "symbol": "reg_$0", "range": "{ [-2147483648, 13] }" } // CHECK-NEXT: ], +// CHECK-NEXT: "equivalence_classes": null, +// CHECK-NEXT: "disequality_info": null, // CHECK-NEXT: "dynamic_types": null, // CHECK-NEXT: "dynamic_casts": null, // CHECK-NEXT: "constructing_objects": null, diff --git a/clang/test/Analysis/loop-unrolling.cpp b/clang/test/Analysis/loop-unrolling.cpp index e8ba8b9476ae8..fc1fb06cdc014 100644 --- a/clang/test/Analysis/loop-unrolling.cpp +++ b/clang/test/Analysis/loop-unrolling.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 -analyzer-config exploration_strategy=unexplored_first_queue %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true,exploration_strategy=dfs -verify -std=c++11 -DDFS=1 %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++14 -analyzer-config exploration_strategy=unexplored_first_queue %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true,exploration_strategy=dfs -verify -std=c++14 -DDFS=1 %s void clang_analyzer_numTimesReached(); void clang_analyzer_warnIfReached(); @@ -511,3 +511,39 @@ void parm_by_ref_as_loop_counter(int &i) { clang_analyzer_numTimesReached(); // expected-warning {{4}} } } + +void capture_by_value_as_loop_counter() { + int out = 0; + auto l = [i = out]() mutable { + for (i = 0; i < 10; ++i) { + clang_analyzer_numTimesReached(); // expected-warning {{10}} + } + }; +} + +void capture_by_ref_as_loop_counter() { + int out = 0; + auto l = [&i = out]() { + for (i = 0; i < 10; ++i) { + clang_analyzer_numTimesReached(); // expected-warning {{4}} + } + }; +} + +void capture_implicitly_by_value_as_loop_counter() { + int i = 0; + auto l = [=]() mutable { + for (i = 0; i < 10; ++i) { + clang_analyzer_numTimesReached(); // expected-warning {{10}} + } + }; +} + +void capture_implicitly_by_ref_as_loop_counter() { + int i = 0; + auto l = [&]() mutable { + for (i = 0; i < 10; ++i) { + clang_analyzer_numTimesReached(); // expected-warning {{4}} + } + }; +} diff --git a/clang/test/Analysis/smart-ptr-text-output.cpp b/clang/test/Analysis/smart-ptr-text-output.cpp index f8ecf9192c736..136b63545e55f 100644 --- a/clang/test/Analysis/smart-ptr-text-output.cpp +++ b/clang/test/Analysis/smart-ptr-text-output.cpp @@ -1,10 +1,17 @@ // RUN: %clang_analyze_cc1\ -// RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr\ +// RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\ +// RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ +// RUN: -analyzer-output=text -std=c++20 %s -verify=expected + +// RUN: %clang_analyze_cc1\ +// RUN: -analyzer-checker=core,cplusplus.Move,alpha.cplusplus.SmartPtr,debug.ExprInspection\ // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ // RUN: -analyzer-output=text -std=c++11 %s -verify=expected #include "Inputs/system-header-simulator-cxx.h" +void clang_analyzer_eval(bool); + class A { public: A(){}; @@ -69,20 +76,17 @@ void derefOnReleasedNullRawPtr() { void derefOnSwappedNullPtr() { std::unique_ptr P(new A()); // expected-note {{Smart pointer 'P' is constructed}} - std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} - P.swap(PNull); // expected-note {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} + std::unique_ptr PNull; + P.swap(PNull); PNull->foo(); // No warning. (*P).foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } -// FIXME: Fix this test when "std::swap" is modeled seperately. void derefOnStdSwappedNullPtr() { std::unique_ptr P; // expected-note {{Default constructed smart pointer 'P' is null}} - std::unique_ptr PNull; // expected-note {{Default constructed smart pointer 'PNull' is null}} - std::swap(P, PNull); // expected-note@Inputs/system-header-simulator-cxx.h:979 {{Swapped null smart pointer 'PNull' with smart pointer 'P'}} - // expected-note@-1 {{Calling 'swap'}} - // expected-note@-2 {{Returning from 'swap'}} + std::unique_ptr PNull; + std::swap(P, PNull); P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} // expected-note@-1{{Dereference of null smart pointer 'P'}} } @@ -313,3 +317,61 @@ void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr P) { // expected-note@-1{{Dereference of null smart pointer 'P'}} } } + +void makeUniqueReturnsNonNullUniquePtr() { + auto P = std::make_unique(); + if (!P) { // expected-note {{Taking false branch}} + P->foo(); // should have no warning here, path is impossible + } + P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} + // Now P is null + if (!P) { + // expected-note@-1 {{Taking true branch}} + P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} + // expected-note@-1{{Dereference of null smart pointer 'P'}} + } +} + +#if __cplusplus >= 202002L + +void makeUniqueForOverwriteReturnsNullUniquePtr() { + auto P = std::make_unique_for_overwrite(); + if (!P) { // expected-note {{Taking false branch}} + P->foo(); // should have no warning here, path is impossible + } + P.reset(); // expected-note {{Smart pointer 'P' reset using a null value}} + // Now P is null + if (!P) { + // expected-note@-1 {{Taking true branch}} + P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} + // expected-note@-1{{Dereference of null smart pointer 'P'}} + } +} + +#endif + +struct G { + int *p; + G(int *p): p(p) {} + ~G() { *p = 0; } +}; + +void foo() { + int x = 1; + { + auto P = std::make_unique(&x); + // FIXME: There should not be a state split here, it should take the true path. + clang_analyzer_eval(*P->p == 1); // expected-warning {{TRUE}} + // expected-warning@-1 {{FALSE}} + // expected-note@-2 {{Assuming the condition is true}} + // expected-note@-3 {{Assuming the condition is false}} + // expected-note@-4 {{TRUE}} + // expected-note@-5 {{FALSE}} + // expected-note@-6 {{Assuming the condition is false}} + } + // FIXME: Should be fixed when unique_ptr desctructors are + // properly modelled. This includes modelling the call to + // the destructor of the inner pointer type. + clang_analyzer_eval(x == 0); // expected-warning {{FALSE}} + // expected-note@-1 {{FALSE}} +} diff --git a/clang/test/Analysis/smart-ptr.cpp b/clang/test/Analysis/smart-ptr.cpp index 7761ac4cb4316..37d5eed1217b9 100644 --- a/clang/test/Analysis/smart-ptr.cpp +++ b/clang/test/Analysis/smart-ptr.cpp @@ -3,6 +3,11 @@ // RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ // RUN: -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection\ +// RUN: -analyzer-checker cplusplus.Move,alpha.cplusplus.SmartPtr\ +// RUN: -analyzer-config cplusplus.SmartPtrModeling:ModelSmartPtrDereference=true\ +// RUN: -std=c++20 -verify %s + #include "Inputs/system-header-simulator-cxx.h" void clang_analyzer_warnIfReached(); @@ -457,3 +462,77 @@ void derefAfterBranchingOnUnknownInnerPtr(std::unique_ptr P) { P->foo(); // expected-warning {{Dereference of null smart pointer 'P' [alpha.cplusplus.SmartPtr]}} } } + +// The following is a silly function, +// but serves to test if we are picking out +// standard comparision functions from custom ones. +template +bool operator<(std::unique_ptr &x, double d); + +void uniquePtrComparision(std::unique_ptr unknownPtr) { + auto ptr = std::unique_ptr(new int(13)); + auto nullPtr = std::unique_ptr(); + auto otherPtr = std::unique_ptr(new int(29)); + + clang_analyzer_eval(ptr == ptr); // expected-warning{{TRUE}} + clang_analyzer_eval(ptr > ptr); // expected-warning{{FALSE}} + clang_analyzer_eval(ptr <= ptr); // expected-warning{{TRUE}} + + clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}} + clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}} + + clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}} + clang_analyzer_eval(ptr > nullPtr); // expected-warning{{TRUE}} + + clang_analyzer_eval(ptr != nullptr); // expected-warning{{TRUE}} + clang_analyzer_eval(nullPtr != nullptr); // expected-warning{{FALSE}} + clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}} +} + +void uniquePtrComparisionStateSplitting(std::unique_ptr unknownPtr) { + auto ptr = std::unique_ptr(new int(13)); + + clang_analyzer_eval(ptr > unknownPtr); // expected-warning{{TRUE}} + // expected-warning@-1{{FALSE}} +} + +void uniquePtrComparisionDifferingTypes(std::unique_ptr unknownPtr) { + auto ptr = std::unique_ptr(new int(13)); + auto nullPtr = std::unique_ptr(); + auto otherPtr = std::unique_ptr(new double(3.14)); + + clang_analyzer_eval(nullPtr <= unknownPtr); // expected-warning{{TRUE}} + clang_analyzer_eval(unknownPtr >= nullPtr); // expected-warning{{TRUE}} + + clang_analyzer_eval(ptr != otherPtr); // expected-warning{{TRUE}} + clang_analyzer_eval(ptr > nullPtr); // expected-warning{{TRUE}} + + clang_analyzer_eval(ptr != nullptr); // expected-warning{{TRUE}} + clang_analyzer_eval(nullPtr != nullptr); // expected-warning{{FALSE}} + clang_analyzer_eval(nullptr <= unknownPtr); // expected-warning{{TRUE}} +} + +#if __cplusplus >= 202002L + +void testOstreamOverload(std::unique_ptr P) { + auto &Cout = std::cout; + auto &PtrCout = std::cout << P; + auto &StringCout = std::cout << "hello"; + // We are testing the fact that in our modelling of + // operator<<(basic_ostream &, const unique_ptr &) + // we set the return SVal to the SVal of the ostream arg. + clang_analyzer_eval(&Cout == &PtrCout); // expected-warning {{TRUE}} + // FIXME: Technically, they should be equal, + // that hasn't been modelled yet. + clang_analyzer_eval(&Cout == &StringCout); // expected-warning {{UNKNOWN}} +} + +int glob; +void testOstreamDoesntInvalidateGlobals(std::unique_ptr P) { + int x = glob; + std::cout << P; + int y = glob; + clang_analyzer_eval(x == y); // expected-warning {{TRUE}} +} + +#endif diff --git a/clang/test/Analysis/solver-sym-simplification-ptr-bool.cl b/clang/test/Analysis/solver-sym-simplification-ptr-bool.cl new file mode 100644 index 0000000000000..be8edbf51eba1 --- /dev/null +++ b/clang/test/Analysis/solver-sym-simplification-ptr-bool.cl @@ -0,0 +1,30 @@ +// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown -analyze -analyzer-checker=core %s + +// expected-no-diagnostics + +// This test case covers an issue found in the static analyzer +// solver where pointer sizes were assumed. Pointer sizes may vary on other +// architectures. This issue was originally discovered on a downstream, +// custom target, this assert occurs on the custom target and this one +// without the fix, and is fixed with this change. +// +// The assertion appears to be happening as a result of evaluating the +// SymIntExpr (reg_$0) != 0U in VisitSymIntExpr located in +// SimpleSValBuilder.cpp. The LHS is evaluated to 32b and the RHS is +// evaluated to 16b. This eventually leads to the assertion in APInt.h. +// +// APInt.h:1151: bool llvm::APInt::operator==(const llvm::APInt &) const: Assertion `BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"' +// +void test1(__attribute__((address_space(256))) int * p) { + __attribute__((address_space(256))) int * q = p-1; + if (q) {} + if (q) {} + (void)q; +} + +void test2(__attribute__((address_space(256))) int * p) { + __attribute__((address_space(256))) int * q = p-1; + q && q; + q && q; + (void)q; +} diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 3aed44af0cdfa..d130d4c2fe323 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -33,6 +33,7 @@ configure_lit_site_cfg( "LLVM_LIBS_DIR" "SHLIBDIR" "LLVM_LIT_TOOLS_DIR" + "LLVM_EXTERNAL_LIT" "CLANG_BINARY_DIR" "CLANG_SOURCE_DIR" "CLANG_TOOLS_DIR" diff --git a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp index a85475ece7bf5..cd981264c9b69 100644 --- a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp +++ b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp @@ -7,11 +7,11 @@ namespace test_delete_function { struct A1 { A1(); A1(const A1 &); - A1(A1 &&) = delete; // cxx11_2b-note {{'A1' has been explicitly marked deleted here}} + A1(A1 &&) = delete; // expected-note {{'A1' has been explicitly marked deleted here}} }; A1 test1() { A1 a; - return a; // cxx11_2b-error {{call to deleted constructor of 'test_delete_function::A1'}} + return a; // expected-error {{call to deleted constructor of 'test_delete_function::A1'}} } struct A2 { @@ -19,33 +19,33 @@ struct A2 { A2(const A2 &); private: - A2(A2 &&); // cxx11_2b-note {{declared private here}} + A2(A2 &&); // expected-note {{declared private here}} }; A2 test2() { A2 a; - return a; // cxx11_2b-error {{calling a private constructor of class 'test_delete_function::A2'}} + return a; // expected-error {{calling a private constructor of class 'test_delete_function::A2'}} } struct C {}; struct B1 { B1(C &); - B1(C &&) = delete; // cxx11_2b-note {{'B1' has been explicitly marked deleted here}} + B1(C &&) = delete; // expected-note {{'B1' has been explicitly marked deleted here}} }; B1 test3() { C c; - return c; // cxx11_2b-error {{conversion function from 'test_delete_function::C' to 'test_delete_function::B1' invokes a deleted function}} + return c; // expected-error {{conversion function from 'test_delete_function::C' to 'test_delete_function::B1' invokes a deleted function}} } struct B2 { B2(C &); private: - B2(C &&); // cxx11_2b-note {{declared private here}} + B2(C &&); // expected-note {{declared private here}} }; B2 test4() { C c; - return c; // cxx11_2b-error {{calling a private constructor of class 'test_delete_function::B2'}} + return c; // expected-error {{calling a private constructor of class 'test_delete_function::B2'}} } } // namespace test_delete_function @@ -54,38 +54,38 @@ B2 test4() { namespace test_implicitly_movable_rvalue_ref { struct A1 { A1(A1 &&); - A1(const A1 &) = delete; // cxx98-note {{marked deleted here}} + A1(const A1 &) = delete; }; A1 test1(A1 &&a) { - return a; // cxx98-error {{call to deleted constructor}} + return a; } struct A2 { A2(A2 &&); private: - A2(const A2 &); // cxx98-note {{declared private here}} + A2(const A2 &); }; A2 test2(A2 &&a) { - return a; // cxx98-error {{calling a private constructor}} + return a; } struct B1 { B1(const B1 &); - B1(B1 &&) = delete; // cxx11_2b-note {{'B1' has been explicitly marked deleted here}} + B1(B1 &&) = delete; // expected-note {{'B1' has been explicitly marked deleted here}} }; B1 test3(B1 &&b) { - return b; // cxx11_2b-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::B1'}} + return b; // expected-error {{call to deleted constructor of 'test_implicitly_movable_rvalue_ref::B1'}} } struct B2 { B2(const B2 &); private: - B2(B2 &&); // cxx11_2b-note {{declared private here}} + B2(B2 &&); // expected-note {{declared private here}} }; B2 test4(B2 &&b) { - return b; // cxx11_2b-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::B2'}} + return b; // expected-error {{calling a private constructor of class 'test_implicitly_movable_rvalue_ref::B2'}} } } // namespace test_implicitly_movable_rvalue_ref @@ -96,13 +96,13 @@ void func(); struct A1 { A1(const A1 &); - A1(A1 &&) = delete; // cxx11_2b-note 2{{'A1' has been explicitly marked deleted here}} + A1(A1 &&) = delete; // expected-note 2{{'A1' has been explicitly marked deleted here}} }; void test1() { try { func(); } catch (A1 a) { - throw a; // cxx11_2b-error {{call to deleted constructor of 'test_throw_parameter::A1'}} + throw a; // expected-error {{call to deleted constructor of 'test_throw_parameter::A1'}} } } @@ -110,20 +110,20 @@ struct A2 { A2(const A2 &); private: - A2(A2 &&); // cxx11_2b-note {{declared private here}} + A2(A2 &&); // expected-note {{declared private here}} }; void test2() { try { func(); } catch (A2 a) { - throw a; // cxx11_2b-error {{calling a private constructor of class 'test_throw_parameter::A2'}} + throw a; // expected-error {{calling a private constructor of class 'test_throw_parameter::A2'}} } } void test3(A1 a) try { func(); } catch (...) { - throw a; // cxx11_2b-error {{call to deleted constructor of 'test_throw_parameter::A1'}} + throw a; // expected-error {{call to deleted constructor of 'test_throw_parameter::A1'}} } } // namespace test_throw_parameter @@ -134,42 +134,42 @@ class C {}; struct A1 { operator C() &&; - operator C() const & = delete; // cxx98-note {{marked deleted here}} + operator C() const & = delete; }; C test1() { A1 a; - return a; // cxx98-error {{invokes a deleted function}} + return a; } struct A2 { operator C() &&; private: - operator C() const &; // cxx98-note {{declared private here}} + operator C() const &; }; C test2() { A2 a; - return a; // cxx98-error {{'operator C' is a private member}} + return a; } struct B1 { operator C() const &; - operator C() && = delete; // cxx11_2b-note {{'operator C' has been explicitly marked deleted here}} + operator C() && = delete; // expected-note {{'operator C' has been explicitly marked deleted here}} }; C test3() { B1 b; - return b; // cxx11_2b-error {{conversion function from 'test_non_ctor_conversion::B1' to 'test_non_ctor_conversion::C' invokes a deleted function}} + return b; // expected-error {{conversion function from 'test_non_ctor_conversion::B1' to 'test_non_ctor_conversion::C' invokes a deleted function}} } struct B2 { operator C() const &; private: - operator C() &&; // cxx11_2b-note {{declared private here}} + operator C() &&; // expected-note {{declared private here}} }; C test4() { B2 b; - return b; // cxx11_2b-error {{'operator C' is a private member of 'test_non_ctor_conversion::B2'}} + return b; // expected-error {{'operator C' is a private member of 'test_non_ctor_conversion::B2'}} } } // namespace test_non_ctor_conversion @@ -197,7 +197,7 @@ struct NeedValue { struct A1 { A1(); A1(A1 &&); - A1(const A1 &) = delete; // cxx98-note 3{{marked deleted here}} + A1(const A1 &) = delete; // cxx98-note 2 {{marked deleted here}} }; NeedValue test_1_1() { // not rvalue reference @@ -210,7 +210,7 @@ A1 test_1_2() { // rvalue reference // not same type DerivedA1 a; - return a; // cxx98-error {{call to deleted constructor}} + return a; } NeedValue test_1_3() { // not rvalue reference @@ -224,7 +224,7 @@ struct A2 { A2(A2 &&); private: - A2(const A2 &); // cxx98-note 3{{declared private here}} + A2(const A2 &); // cxx98-note 2 {{declared private here}} }; NeedValue test_2_1() { // not rvalue reference @@ -237,7 +237,7 @@ A2 test_2_2() { // rvalue reference // not same type DerivedA2 a; - return a; // cxx98-error {{calling a private constructor}} + return a; } NeedValue test_2_3() { // not rvalue reference @@ -250,6 +250,7 @@ struct B1 { B1(); B1(const B1 &); B1(B1 &&) = delete; // cxx11_2b-note 3 {{'B1' has been explicitly marked deleted here}} + // cxx98-note@-1 {{'B1' has been explicitly marked deleted here}} }; NeedValue test_3_1() { // not rvalue reference @@ -262,7 +263,7 @@ B1 test_3_2() { // rvalue reference // not same type DerivedB1 b; - return b; // cxx11_2b-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} + return b; // expected-error {{call to deleted constructor of 'test_ctor_param_rvalue_ref::B1'}} } NeedValue test_3_3() { // not rvalue reference @@ -277,6 +278,7 @@ struct B2 { private: B2(B2 &&); // cxx11_2b-note 3 {{declared private here}} + // cxx98-note@-1 {{declared private here}} }; NeedValue test_4_1() { // not rvalue reference @@ -289,7 +291,7 @@ B2 test_4_2() { // rvalue reference // not same type DerivedB2 b; - return b; // cxx11_2b-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} + return b; // expected-error {{calling a private constructor of class 'test_ctor_param_rvalue_ref::B2'}} } NeedValue test_4_3() { // not rvalue reference @@ -302,20 +304,19 @@ NeedValue test_4_3() { namespace test_lvalue_ref_is_not_moved_from { struct Target {}; -// cxx11_2b-note@-1 {{candidate constructor (the implicit copy constructor) not viable}} -// cxx98-note@-2 2{{candidate constructor (the implicit copy constructor) not viable}} -// cxx11_2b-note@-3 {{candidate constructor (the implicit move constructor) not viable}} +// expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable}} +// cxx11_2b-note@-2 {{candidate constructor (the implicit move constructor) not viable}} struct CopyOnly { - CopyOnly(CopyOnly &&) = delete; // cxx11_2b-note {{has been explicitly marked deleted here}} + CopyOnly(CopyOnly &&) = delete; // expected-note {{has been explicitly marked deleted here}} CopyOnly(CopyOnly&); - operator Target() && = delete; // cxx11_2b-note {{has been explicitly marked deleted here}} + operator Target() && = delete; // expected-note {{has been explicitly marked deleted here}} operator Target() &; }; struct MoveOnly { MoveOnly(MoveOnly &&); // cxx11_2b-note {{copy constructor is implicitly deleted because}} - operator Target() &&; // expected-note {{candidate function not viable}} cxx98-note {{candidate function not viable}} + operator Target() &&; // expected-note {{candidate function not viable}} }; extern CopyOnly copyonly; @@ -328,7 +329,7 @@ CopyOnly t1() { CopyOnly t2() { CopyOnly&& r = static_cast(copyonly); - return r; // cxx11_2b-error {{call to deleted constructor}} + return r; // expected-error {{call to deleted constructor}} } MoveOnly t3() { @@ -348,7 +349,7 @@ Target t5() { Target t6() { CopyOnly&& r = static_cast(copyonly); - return r; // cxx11_2b-error {{invokes a deleted function}} + return r; // expected-error {{invokes a deleted function}} } Target t7() { @@ -358,7 +359,7 @@ Target t7() { Target t8() { MoveOnly&& r = static_cast(moveonly); - return r; // cxx98-error {{no viable conversion}} + return r; } } // namespace test_lvalue_ref_is_not_moved_from @@ -400,6 +401,10 @@ Target t4() { } // namespace test_rvalue_ref_to_nonobject +// Both tests in test_constandnonconstcopy, and also test_conversion::test1, are +// "pure" C++98 tests (pretend 'delete' means 'private'). +// However we may extend implicit moves into C++98, we must make sure the +// results in these are not changed. namespace test_constandnonconstcopy { struct ConstCopyOnly { ConstCopyOnly(); @@ -437,9 +442,9 @@ A test1(B x) { return x; } // cxx98-error-re {{conversion {{.*}} is ambiguous}} struct C {}; struct D { operator C() &; - operator C() const & = delete; // cxx11_2b-note {{marked deleted here}} + operator C() const & = delete; // expected-note {{marked deleted here}} }; -C test2(D x) { return x; } // cxx11_2b-error {{invokes a deleted function}} +C test2(D x) { return x; } // expected-error {{invokes a deleted function}} } // namespace test_conversion diff --git a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp index c33bf0eba231b..ed61119dc252a 100644 --- a/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp @@ -38,18 +38,38 @@ namespace odr_use_in_selected_arm { } #else namespace ccce { + + struct S { + }; void f() { if (5) {} - if constexpr (5) {} // expected-error {{cannot be narrowed}} + if constexpr (5) { + } } template void g() { - if constexpr (N) {} // expected-error {{cannot be narrowed}} + if constexpr (N) { + } } - template void g<5>(); // expected-note {{instantiation of}} + template void g<5>(); void h() { - if constexpr (4.3) {} // expected-error{{conversion from 'double' to 'bool' is not allowed in a converted constant expression}} + if constexpr (4.3) { //expected-warning {{implicit conversion from 'double' to 'bool' changes value}} + } constexpr void *p = nullptr; - if constexpr (p) {} // expected-error{{conversion from 'void *const' to 'bool' is not allowed in a converted constant expression}} + if constexpr (p) { + } + } + + void not_constant(int b, S s) { // expected-note 2{{declared here}} + if constexpr (bool(b)) { // expected-error {{constexpr if condition is not a constant expression}} expected-note {{cannot be used in a constant expression}} + } + if constexpr (b) { // expected-error {{constexpr if condition is not a constant expression}} expected-note {{cannot be used in a constant expression}} + } + if constexpr (s) { // expected-error {{value of type 'ccce::S' is not contextually convertible to 'bool'}} + } + + constexpr S constexprS; + if constexpr (constexprS) { // expected-error {{value of type 'const ccce::S' is not contextually convertible to 'bool'}} + } } } diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index dea900f1afc0b..2303293876920 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -44,3 +44,9 @@ void test_A(int *p) { // CHECK: call void asm sideeffect "", "*A"(i32* %p) asm volatile("" :: "A"(*p)); } + +void test_S() { +// CHECK-LABEL: define{{.*}} void @test_S() +// CHECK: call void asm sideeffect "", "S"(float* nonnull @f) + asm volatile("" :: "S"(&f)); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vget.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vget.c new file mode 100644 index 0000000000000..bf8d1e46b0353 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vget.c @@ -0,0 +1,547 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-feature +experimental-v \ +// RUN: -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: @test_vget_v_i8m2_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv16i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vget_v_i8m2_i8m1(vint8m2_t src, size_t index) { + return vget_i8m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i8m4_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv32i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vget_v_i8m4_i8m1(vint8m4_t src, size_t index) { + return vget_i8m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i8m8_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv64i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vget_v_i8m8_i8m1(vint8m8_t src, size_t index) { + return vget_i8m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i8m4_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv32i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vget_v_i8m4_i8m2(vint8m4_t src, size_t index) { + return vget_i8m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i8m8_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv64i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vget_v_i8m8_i8m2(vint8m8_t src, size_t index) { + return vget_i8m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i8m8_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv32i8.nxv64i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vget_v_i8m8_i8m4(vint8m8_t src, size_t index) { + return vget_i8m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u8m2_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv16i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vget_v_u8m2_u8m1(vuint8m2_t src, size_t index) { + return vget_u8m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u8m4_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv32i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vget_v_u8m4_u8m1(vuint8m4_t src, size_t index) { + return vget_u8m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u8m8_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv64i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vget_v_u8m8_u8m1(vuint8m8_t src, size_t index) { + return vget_u8m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u8m4_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv32i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vget_v_u8m4_u8m2(vuint8m4_t src, size_t index) { + return vget_u8m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u8m8_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv64i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vget_v_u8m8_u8m2(vuint8m8_t src, size_t index) { + return vget_u8m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u8m8_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv32i8.nxv64i8( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vget_v_u8m8_u8m4(vuint8m8_t src, size_t index) { + return vget_u8m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i16m2_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv8i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vget_v_i16m2_i16m1(vint16m2_t src, size_t index) { + return vget_i16m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i16m4_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv16i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vget_v_i16m4_i16m1(vint16m4_t src, size_t index) { + return vget_i16m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i16m8_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv32i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vget_v_i16m8_i16m1(vint16m8_t src, size_t index) { + return vget_i16m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i16m4_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv16i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vget_v_i16m4_i16m2(vint16m4_t src, size_t index) { + return vget_i16m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i16m8_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv32i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vget_v_i16m8_i16m2(vint16m8_t src, size_t index) { + return vget_i16m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i16m8_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i16.nxv32i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vget_v_i16m8_i16m4(vint16m8_t src, size_t index) { + return vget_i16m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u16m2_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv8i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vget_v_u16m2_u16m1(vuint16m2_t src, size_t index) { + return vget_u16m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u16m4_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv16i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vget_v_u16m4_u16m1(vuint16m4_t src, size_t index) { + return vget_u16m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u16m8_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv32i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vget_v_u16m8_u16m1(vuint16m8_t src, size_t index) { + return vget_u16m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u16m4_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv16i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vget_v_u16m4_u16m2(vuint16m4_t src, size_t index) { + return vget_u16m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u16m8_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv32i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vget_v_u16m8_u16m2(vuint16m8_t src, size_t index) { + return vget_u16m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u16m8_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i16.nxv32i16( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vget_v_u16m8_u16m4(vuint16m8_t src, size_t index) { + return vget_u16m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i32m2_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv4i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vget_v_i32m2_i32m1(vint32m2_t src, size_t index) { + return vget_i32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i32m4_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv8i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vget_v_i32m4_i32m1(vint32m4_t src, size_t index) { + return vget_i32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i32m8_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv16i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vget_v_i32m8_i32m1(vint32m8_t src, size_t index) { + return vget_i32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i32m4_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv8i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vget_v_i32m4_i32m2(vint32m4_t src, size_t index) { + return vget_i32m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i32m8_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv16i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vget_v_i32m8_i32m2(vint32m8_t src, size_t index) { + return vget_i32m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i32m8_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i32.nxv16i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vget_v_i32m8_i32m4(vint32m8_t src, size_t index) { + return vget_i32m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u32m2_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv4i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vget_v_u32m2_u32m1(vuint32m2_t src, size_t index) { + return vget_u32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u32m4_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv8i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vget_v_u32m4_u32m1(vuint32m4_t src, size_t index) { + return vget_u32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u32m8_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv16i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vget_v_u32m8_u32m1(vuint32m8_t src, size_t index) { + return vget_u32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u32m4_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv8i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vget_v_u32m4_u32m2(vuint32m4_t src, size_t index) { + return vget_u32m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u32m8_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv16i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vget_v_u32m8_u32m2(vuint32m8_t src, size_t index) { + return vget_u32m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u32m8_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i32.nxv16i32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vget_v_u32m8_u32m4(vuint32m8_t src, size_t index) { + return vget_u32m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f32m2_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f32.nxv4f32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vget_v_f32m2_f32m1(vfloat32m2_t src, size_t index) { + return vget_f32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f32m4_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f32.nxv8f32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vget_v_f32m4_f32m1(vfloat32m4_t src, size_t index) { + return vget_f32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f32m8_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f32.nxv16f32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vget_v_f32m8_f32m1(vfloat32m8_t src, size_t index) { + return vget_f32m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f32m4_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4f32.nxv8f32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vget_v_f32m4_f32m2(vfloat32m4_t src, size_t index) { + return vget_f32m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f32m8_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4f32.nxv16f32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vget_v_f32m8_f32m2(vfloat32m8_t src, size_t index) { + return vget_f32m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f32m8_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8f32.nxv16f32( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vget_v_f32m8_f32m4(vfloat32m8_t src, size_t index) { + return vget_f32m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i64m2_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv2i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vget_v_i64m2_i64m1(vint64m2_t src, size_t index) { + return vget_i64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i64m4_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv4i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vget_v_i64m4_i64m1(vint64m4_t src, size_t index) { + return vget_i64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i64m8_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv8i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vget_v_i64m8_i64m1(vint64m8_t src, size_t index) { + return vget_i64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i64m4_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv4i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vget_v_i64m4_i64m2(vint64m4_t src, size_t index) { + return vget_i64m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i64m8_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv8i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vget_v_i64m8_i64m2(vint64m8_t src, size_t index) { + return vget_i64m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_i64m8_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i64.nxv8i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vget_v_i64m8_i64m4(vint64m8_t src, size_t index) { + return vget_i64m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u64m2_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv2i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vget_v_u64m2_u64m1(vuint64m2_t src, size_t index) { + return vget_u64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u64m4_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv4i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vget_v_u64m4_u64m1(vuint64m4_t src, size_t index) { + return vget_u64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u64m8_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv8i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vget_v_u64m8_u64m1(vuint64m8_t src, size_t index) { + return vget_u64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u64m4_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv4i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vget_v_u64m4_u64m2(vuint64m4_t src, size_t index) { + return vget_u64m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u64m8_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv8i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vget_v_u64m8_u64m2(vuint64m8_t src, size_t index) { + return vget_u64m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_u64m8_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i64.nxv8i64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vget_v_u64m8_u64m4(vuint64m8_t src, size_t index) { + return vget_u64m4(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f64m2_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f64.nxv2f64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vget_v_f64m2_f64m1(vfloat64m2_t src, size_t index) { + return vget_f64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f64m4_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f64.nxv4f64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vget_v_f64m4_f64m1(vfloat64m4_t src, size_t index) { + return vget_f64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f64m8_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f64.nxv8f64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vget_v_f64m8_f64m1(vfloat64m8_t src, size_t index) { + return vget_f64m1(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f64m4_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f64.nxv4f64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vget_v_f64m4_f64m2(vfloat64m4_t src, size_t index) { + return vget_f64m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f64m8_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f64.nxv8f64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vget_v_f64m8_f64m2(vfloat64m8_t src, size_t index) { + return vget_f64m2(src, 0); +} + +// CHECK-RV64-LABEL: @test_vget_v_f64m8_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4f64.nxv8f64( [[SRC:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vget_v_f64m8_f64m4(vfloat64m8_t src, size_t index) { + return vget_f64m4(src, 0); +} + diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlmul.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlmul.c new file mode 100644 index 0000000000000..3d27463efbfa4 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlmul.c @@ -0,0 +1,2166 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-feature +experimental-v \ +// RUN: -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf8_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vlmul_ext_v_i8mf8_i8mf4(vint8mf8_t op1) { + return vlmul_ext_i8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf8_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vlmul_ext_v_i8mf8_i8mf2(vint8mf8_t op1) { + return vlmul_ext_i8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf8_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vlmul_ext_v_i8mf8_i8m1(vint8mf8_t op1) { + return vlmul_ext_i8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf8_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vlmul_ext_v_i8mf8_i8m2(vint8mf8_t op1) { + return vlmul_ext_i8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf8_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vlmul_ext_v_i8mf8_i8m4(vint8mf8_t op1) { + return vlmul_ext_i8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf8_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vlmul_ext_v_i8mf8_i8m8(vint8mf8_t op1) { + return vlmul_ext_i8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf4_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vlmul_ext_v_i8mf4_i8mf2(vint8mf4_t op1) { + return vlmul_ext_i8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf4_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vlmul_ext_v_i8mf4_i8m1(vint8mf4_t op1) { + return vlmul_ext_i8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf4_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vlmul_ext_v_i8mf4_i8m2(vint8mf4_t op1) { + return vlmul_ext_i8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf4_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vlmul_ext_v_i8mf4_i8m4(vint8mf4_t op1) { + return vlmul_ext_i8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf4_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vlmul_ext_v_i8mf4_i8m8(vint8mf4_t op1) { + return vlmul_ext_i8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf2_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vlmul_ext_v_i8mf2_i8m1(vint8mf2_t op1) { + return vlmul_ext_i8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf2_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vlmul_ext_v_i8mf2_i8m2(vint8mf2_t op1) { + return vlmul_ext_i8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf2_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vlmul_ext_v_i8mf2_i8m4(vint8mf2_t op1) { + return vlmul_ext_i8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8mf2_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vlmul_ext_v_i8mf2_i8m8(vint8mf2_t op1) { + return vlmul_ext_i8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8m1_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv8i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vlmul_ext_v_i8m1_i8m2(vint8m1_t op1) { + return vlmul_ext_i8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8m1_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv8i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vlmul_ext_v_i8m1_i8m4(vint8m1_t op1) { + return vlmul_ext_i8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8m1_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv8i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vlmul_ext_v_i8m1_i8m8(vint8m1_t op1) { + return vlmul_ext_i8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8m2_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv16i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vlmul_ext_v_i8m2_i8m4(vint8m2_t op1) { + return vlmul_ext_i8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8m2_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv16i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vlmul_ext_v_i8m2_i8m8(vint8m2_t op1) { + return vlmul_ext_i8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i8m4_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv32i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vlmul_ext_v_i8m4_i8m8(vint8m4_t op1) { + return vlmul_ext_i8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf4_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vlmul_ext_v_i16mf4_i16mf2(vint16mf4_t op1) { + return vlmul_ext_i16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf4_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vlmul_ext_v_i16mf4_i16m1(vint16mf4_t op1) { + return vlmul_ext_i16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf4_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vlmul_ext_v_i16mf4_i16m2(vint16mf4_t op1) { + return vlmul_ext_i16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf4_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vlmul_ext_v_i16mf4_i16m4(vint16mf4_t op1) { + return vlmul_ext_i16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf4_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vlmul_ext_v_i16mf4_i16m8(vint16mf4_t op1) { + return vlmul_ext_i16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf2_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vlmul_ext_v_i16mf2_i16m1(vint16mf2_t op1) { + return vlmul_ext_i16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf2_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vlmul_ext_v_i16mf2_i16m2(vint16mf2_t op1) { + return vlmul_ext_i16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf2_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vlmul_ext_v_i16mf2_i16m4(vint16mf2_t op1) { + return vlmul_ext_i16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16mf2_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vlmul_ext_v_i16mf2_i16m8(vint16mf2_t op1) { + return vlmul_ext_i16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16m1_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv4i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vlmul_ext_v_i16m1_i16m2(vint16m1_t op1) { + return vlmul_ext_i16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16m1_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv4i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vlmul_ext_v_i16m1_i16m4(vint16m1_t op1) { + return vlmul_ext_i16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16m1_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv4i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vlmul_ext_v_i16m1_i16m8(vint16m1_t op1) { + return vlmul_ext_i16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16m2_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv8i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vlmul_ext_v_i16m2_i16m4(vint16m2_t op1) { + return vlmul_ext_i16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16m2_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv8i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vlmul_ext_v_i16m2_i16m8(vint16m2_t op1) { + return vlmul_ext_i16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i16m4_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv16i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vlmul_ext_v_i16m4_i16m8(vint16m4_t op1) { + return vlmul_ext_i16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32mf2_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vlmul_ext_v_i32mf2_i32m1(vint32mf2_t op1) { + return vlmul_ext_i32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32mf2_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vlmul_ext_v_i32mf2_i32m2(vint32mf2_t op1) { + return vlmul_ext_i32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32mf2_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vlmul_ext_v_i32mf2_i32m4(vint32mf2_t op1) { + return vlmul_ext_i32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32mf2_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vlmul_ext_v_i32mf2_i32m8(vint32mf2_t op1) { + return vlmul_ext_i32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32m1_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.nxv2i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vlmul_ext_v_i32m1_i32m2(vint32m1_t op1) { + return vlmul_ext_i32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32m1_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv2i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vlmul_ext_v_i32m1_i32m4(vint32m1_t op1) { + return vlmul_ext_i32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32m1_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv2i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vlmul_ext_v_i32m1_i32m8(vint32m1_t op1) { + return vlmul_ext_i32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32m2_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv4i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vlmul_ext_v_i32m2_i32m4(vint32m2_t op1) { + return vlmul_ext_i32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32m2_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv4i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vlmul_ext_v_i32m2_i32m8(vint32m2_t op1) { + return vlmul_ext_i32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i32m4_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv8i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vlmul_ext_v_i32m4_i32m8(vint32m4_t op1) { + return vlmul_ext_i32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i64m1_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.nxv1i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vlmul_ext_v_i64m1_i64m2(vint64m1_t op1) { + return vlmul_ext_i64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i64m1_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv1i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vlmul_ext_v_i64m1_i64m4(vint64m1_t op1) { + return vlmul_ext_i64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i64m1_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv1i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vlmul_ext_v_i64m1_i64m8(vint64m1_t op1) { + return vlmul_ext_i64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i64m2_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv2i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vlmul_ext_v_i64m2_i64m4(vint64m2_t op1) { + return vlmul_ext_i64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i64m2_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv2i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vlmul_ext_v_i64m2_i64m8(vint64m2_t op1) { + return vlmul_ext_i64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_i64m4_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv4i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vlmul_ext_v_i64m4_i64m8(vint64m4_t op1) { + return vlmul_ext_i64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf8_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vlmul_ext_v_u8mf8_u8mf4(vuint8mf8_t op1) { + return vlmul_ext_u8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf8_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vlmul_ext_v_u8mf8_u8mf2(vuint8mf8_t op1) { + return vlmul_ext_u8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf8_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vlmul_ext_v_u8mf8_u8m1(vuint8mf8_t op1) { + return vlmul_ext_u8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf8_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vlmul_ext_v_u8mf8_u8m2(vuint8mf8_t op1) { + return vlmul_ext_u8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf8_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vlmul_ext_v_u8mf8_u8m4(vuint8mf8_t op1) { + return vlmul_ext_u8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf8_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv1i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vlmul_ext_v_u8mf8_u8m8(vuint8mf8_t op1) { + return vlmul_ext_u8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf4_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vlmul_ext_v_u8mf4_u8mf2(vuint8mf4_t op1) { + return vlmul_ext_u8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf4_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vlmul_ext_v_u8mf4_u8m1(vuint8mf4_t op1) { + return vlmul_ext_u8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf4_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vlmul_ext_v_u8mf4_u8m2(vuint8mf4_t op1) { + return vlmul_ext_u8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf4_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vlmul_ext_v_u8mf4_u8m4(vuint8mf4_t op1) { + return vlmul_ext_u8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf4_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv2i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vlmul_ext_v_u8mf4_u8m8(vuint8mf4_t op1) { + return vlmul_ext_u8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf2_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vlmul_ext_v_u8mf2_u8m1(vuint8mf2_t op1) { + return vlmul_ext_u8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf2_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vlmul_ext_v_u8mf2_u8m2(vuint8mf2_t op1) { + return vlmul_ext_u8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf2_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vlmul_ext_v_u8mf2_u8m4(vuint8mf2_t op1) { + return vlmul_ext_u8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8mf2_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv4i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vlmul_ext_v_u8mf2_u8m8(vuint8mf2_t op1) { + return vlmul_ext_u8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8m1_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv8i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vlmul_ext_v_u8m1_u8m2(vuint8m1_t op1) { + return vlmul_ext_u8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8m1_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv8i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vlmul_ext_v_u8m1_u8m4(vuint8m1_t op1) { + return vlmul_ext_u8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8m1_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv8i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vlmul_ext_v_u8m1_u8m8(vuint8m1_t op1) { + return vlmul_ext_u8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8m2_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv16i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vlmul_ext_v_u8m2_u8m4(vuint8m2_t op1) { + return vlmul_ext_u8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8m2_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv16i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vlmul_ext_v_u8m2_u8m8(vuint8m2_t op1) { + return vlmul_ext_u8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u8m4_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv32i8( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vlmul_ext_v_u8m4_u8m8(vuint8m4_t op1) { + return vlmul_ext_u8m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf4_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vlmul_ext_v_u16mf4_u16mf2(vuint16mf4_t op1) { + return vlmul_ext_u16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf4_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vlmul_ext_v_u16mf4_u16m1(vuint16mf4_t op1) { + return vlmul_ext_u16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf4_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vlmul_ext_v_u16mf4_u16m2(vuint16mf4_t op1) { + return vlmul_ext_u16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf4_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vlmul_ext_v_u16mf4_u16m4(vuint16mf4_t op1) { + return vlmul_ext_u16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf4_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv1i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vlmul_ext_v_u16mf4_u16m8(vuint16mf4_t op1) { + return vlmul_ext_u16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf2_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vlmul_ext_v_u16mf2_u16m1(vuint16mf2_t op1) { + return vlmul_ext_u16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf2_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vlmul_ext_v_u16mf2_u16m2(vuint16mf2_t op1) { + return vlmul_ext_u16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf2_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vlmul_ext_v_u16mf2_u16m4(vuint16mf2_t op1) { + return vlmul_ext_u16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16mf2_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv2i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vlmul_ext_v_u16mf2_u16m8(vuint16mf2_t op1) { + return vlmul_ext_u16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16m1_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv4i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vlmul_ext_v_u16m1_u16m2(vuint16m1_t op1) { + return vlmul_ext_u16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16m1_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv4i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vlmul_ext_v_u16m1_u16m4(vuint16m1_t op1) { + return vlmul_ext_u16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16m1_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv4i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vlmul_ext_v_u16m1_u16m8(vuint16m1_t op1) { + return vlmul_ext_u16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16m2_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv8i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vlmul_ext_v_u16m2_u16m4(vuint16m2_t op1) { + return vlmul_ext_u16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16m2_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv8i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vlmul_ext_v_u16m2_u16m8(vuint16m2_t op1) { + return vlmul_ext_u16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u16m4_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv16i16( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vlmul_ext_v_u16m4_u16m8(vuint16m4_t op1) { + return vlmul_ext_u16m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32mf2_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vlmul_ext_v_u32mf2_u32m1(vuint32mf2_t op1) { + return vlmul_ext_u32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32mf2_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vlmul_ext_v_u32mf2_u32m2(vuint32mf2_t op1) { + return vlmul_ext_u32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32mf2_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vlmul_ext_v_u32mf2_u32m4(vuint32mf2_t op1) { + return vlmul_ext_u32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32mf2_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv1i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vlmul_ext_v_u32mf2_u32m8(vuint32mf2_t op1) { + return vlmul_ext_u32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32m1_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.nxv2i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vlmul_ext_v_u32m1_u32m2(vuint32m1_t op1) { + return vlmul_ext_u32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32m1_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv2i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vlmul_ext_v_u32m1_u32m4(vuint32m1_t op1) { + return vlmul_ext_u32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32m1_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv2i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vlmul_ext_v_u32m1_u32m8(vuint32m1_t op1) { + return vlmul_ext_u32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32m2_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv4i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vlmul_ext_v_u32m2_u32m4(vuint32m2_t op1) { + return vlmul_ext_u32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32m2_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv4i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vlmul_ext_v_u32m2_u32m8(vuint32m2_t op1) { + return vlmul_ext_u32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u32m4_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv8i32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vlmul_ext_v_u32m4_u32m8(vuint32m4_t op1) { + return vlmul_ext_u32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u64m1_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.nxv1i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vlmul_ext_v_u64m1_u64m2(vuint64m1_t op1) { + return vlmul_ext_u64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u64m1_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv1i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vlmul_ext_v_u64m1_u64m4(vuint64m1_t op1) { + return vlmul_ext_u64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u64m1_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv1i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vlmul_ext_v_u64m1_u64m8(vuint64m1_t op1) { + return vlmul_ext_u64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u64m2_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv2i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vlmul_ext_v_u64m2_u64m4(vuint64m2_t op1) { + return vlmul_ext_u64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u64m2_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv2i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vlmul_ext_v_u64m2_u64m8(vuint64m2_t op1) { + return vlmul_ext_u64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_u64m4_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv4i64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vlmul_ext_v_u64m4_u64m8(vuint64m4_t op1) { + return vlmul_ext_u64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32mf2_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2f32.nxv1f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vlmul_ext_v_f32mf2_f32m1(vfloat32mf2_t op1) { + return vlmul_ext_f32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32mf2_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.nxv1f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vlmul_ext_v_f32mf2_f32m2(vfloat32mf2_t op1) { + return vlmul_ext_f32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32mf2_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f32.nxv1f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vlmul_ext_v_f32mf2_f32m4(vfloat32mf2_t op1) { + return vlmul_ext_f32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32mf2_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv1f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vlmul_ext_v_f32mf2_f32m8(vfloat32mf2_t op1) { + return vlmul_ext_f32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32m1_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.nxv2f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vlmul_ext_v_f32m1_f32m2(vfloat32m1_t op1) { + return vlmul_ext_f32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32m1_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f32.nxv2f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vlmul_ext_v_f32m1_f32m4(vfloat32m1_t op1) { + return vlmul_ext_f32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32m1_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv2f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vlmul_ext_v_f32m1_f32m8(vfloat32m1_t op1) { + return vlmul_ext_f32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32m2_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f32.nxv4f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vlmul_ext_v_f32m2_f32m4(vfloat32m2_t op1) { + return vlmul_ext_f32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32m2_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv4f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vlmul_ext_v_f32m2_f32m8(vfloat32m2_t op1) { + return vlmul_ext_f32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f32m4_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv8f32( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vlmul_ext_v_f32m4_f32m8(vfloat32m4_t op1) { + return vlmul_ext_f32m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f64m1_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.nxv1f64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vlmul_ext_v_f64m1_f64m2(vfloat64m1_t op1) { + return vlmul_ext_f64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f64m1_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f64.nxv1f64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vlmul_ext_v_f64m1_f64m4(vfloat64m1_t op1) { + return vlmul_ext_f64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f64m1_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f64.nxv1f64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vlmul_ext_v_f64m1_f64m8(vfloat64m1_t op1) { + return vlmul_ext_f64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f64m2_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f64.nxv2f64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vlmul_ext_v_f64m2_f64m4(vfloat64m2_t op1) { + return vlmul_ext_f64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f64m2_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f64.nxv2f64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vlmul_ext_v_f64m2_f64m8(vfloat64m2_t op1) { + return vlmul_ext_f64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_ext_v_f64m4_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f64.nxv4f64( undef, [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vlmul_ext_v_f64m4_f64m8(vfloat64m4_t op1) { + return vlmul_ext_f64m8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8mf4_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv2i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf8_t test_vlmul_trunc_v_i8mf4_i8mf8(vint8mf4_t op1) { + return vlmul_trunc_i8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8mf2_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv4i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf8_t test_vlmul_trunc_v_i8mf2_i8mf8(vint8mf2_t op1) { + return vlmul_trunc_i8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8mf2_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv4i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vlmul_trunc_v_i8mf2_i8mf4(vint8mf2_t op1) { + return vlmul_trunc_i8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m1_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv8i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf8_t test_vlmul_trunc_v_i8m1_i8mf8(vint8m1_t op1) { + return vlmul_trunc_i8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m1_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv8i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vlmul_trunc_v_i8m1_i8mf4(vint8m1_t op1) { + return vlmul_trunc_i8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m1_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv8i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vlmul_trunc_v_i8m1_i8mf2(vint8m1_t op1) { + return vlmul_trunc_i8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m2_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf8_t test_vlmul_trunc_v_i8m2_i8mf8(vint8m2_t op1) { + return vlmul_trunc_i8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m2_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vlmul_trunc_v_i8m2_i8mf4(vint8m2_t op1) { + return vlmul_trunc_i8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m2_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vlmul_trunc_v_i8m2_i8mf2(vint8m2_t op1) { + return vlmul_trunc_i8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m2_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vlmul_trunc_v_i8m2_i8m1(vint8m2_t op1) { + return vlmul_trunc_i8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m4_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf8_t test_vlmul_trunc_v_i8m4_i8mf8(vint8m4_t op1) { + return vlmul_trunc_i8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m4_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vlmul_trunc_v_i8m4_i8mf4(vint8m4_t op1) { + return vlmul_trunc_i8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m4_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vlmul_trunc_v_i8m4_i8mf2(vint8m4_t op1) { + return vlmul_trunc_i8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m4_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vlmul_trunc_v_i8m4_i8m1(vint8m4_t op1) { + return vlmul_trunc_i8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m4_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vlmul_trunc_v_i8m4_i8m2(vint8m4_t op1) { + return vlmul_trunc_i8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m8_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf8_t test_vlmul_trunc_v_i8m8_i8mf8(vint8m8_t op1) { + return vlmul_trunc_i8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m8_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vlmul_trunc_v_i8m8_i8mf4(vint8m8_t op1) { + return vlmul_trunc_i8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m8_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vlmul_trunc_v_i8m8_i8mf2(vint8m8_t op1) { + return vlmul_trunc_i8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m8_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vlmul_trunc_v_i8m8_i8m1(vint8m8_t op1) { + return vlmul_trunc_i8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m8_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vlmul_trunc_v_i8m8_i8m2(vint8m8_t op1) { + return vlmul_trunc_i8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i8m8_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv32i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vlmul_trunc_v_i8m8_i8m4(vint8m8_t op1) { + return vlmul_trunc_i8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16mf2_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv2i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf4_t test_vlmul_trunc_v_i16mf2_i16mf4(vint16mf2_t op1) { + return vlmul_trunc_i16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m1_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv4i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf4_t test_vlmul_trunc_v_i16m1_i16mf4(vint16m1_t op1) { + return vlmul_trunc_i16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m1_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv4i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vlmul_trunc_v_i16m1_i16mf2(vint16m1_t op1) { + return vlmul_trunc_i16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m2_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv8i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf4_t test_vlmul_trunc_v_i16m2_i16mf4(vint16m2_t op1) { + return vlmul_trunc_i16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m2_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv8i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vlmul_trunc_v_i16m2_i16mf2(vint16m2_t op1) { + return vlmul_trunc_i16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m2_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv8i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vlmul_trunc_v_i16m2_i16m1(vint16m2_t op1) { + return vlmul_trunc_i16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m4_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf4_t test_vlmul_trunc_v_i16m4_i16mf4(vint16m4_t op1) { + return vlmul_trunc_i16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m4_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vlmul_trunc_v_i16m4_i16mf2(vint16m4_t op1) { + return vlmul_trunc_i16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m4_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vlmul_trunc_v_i16m4_i16m1(vint16m4_t op1) { + return vlmul_trunc_i16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m4_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vlmul_trunc_v_i16m4_i16m2(vint16m4_t op1) { + return vlmul_trunc_i16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m8_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf4_t test_vlmul_trunc_v_i16m8_i16mf4(vint16m8_t op1) { + return vlmul_trunc_i16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m8_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vlmul_trunc_v_i16m8_i16mf2(vint16m8_t op1) { + return vlmul_trunc_i16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m8_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vlmul_trunc_v_i16m8_i16m1(vint16m8_t op1) { + return vlmul_trunc_i16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m8_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vlmul_trunc_v_i16m8_i16m2(vint16m8_t op1) { + return vlmul_trunc_i16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i16m8_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vlmul_trunc_v_i16m8_i16m4(vint16m8_t op1) { + return vlmul_trunc_i16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m1_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv2i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vlmul_trunc_v_i32m1_i32mf2(vint32m1_t op1) { + return vlmul_trunc_i32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m2_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv4i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vlmul_trunc_v_i32m2_i32mf2(vint32m2_t op1) { + return vlmul_trunc_i32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m2_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv4i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vlmul_trunc_v_i32m2_i32m1(vint32m2_t op1) { + return vlmul_trunc_i32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m4_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv8i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vlmul_trunc_v_i32m4_i32mf2(vint32m4_t op1) { + return vlmul_trunc_i32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m4_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv8i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vlmul_trunc_v_i32m4_i32m1(vint32m4_t op1) { + return vlmul_trunc_i32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m4_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv8i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vlmul_trunc_v_i32m4_i32m2(vint32m4_t op1) { + return vlmul_trunc_i32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m8_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vlmul_trunc_v_i32m8_i32mf2(vint32m8_t op1) { + return vlmul_trunc_i32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m8_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vlmul_trunc_v_i32m8_i32m1(vint32m8_t op1) { + return vlmul_trunc_i32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m8_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vlmul_trunc_v_i32m8_i32m2(vint32m8_t op1) { + return vlmul_trunc_i32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i32m8_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vlmul_trunc_v_i32m8_i32m4(vint32m8_t op1) { + return vlmul_trunc_i32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i64m2_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv2i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vlmul_trunc_v_i64m2_i64m1(vint64m2_t op1) { + return vlmul_trunc_i64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i64m4_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv4i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vlmul_trunc_v_i64m4_i64m1(vint64m4_t op1) { + return vlmul_trunc_i64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i64m4_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv4i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vlmul_trunc_v_i64m4_i64m2(vint64m4_t op1) { + return vlmul_trunc_i64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i64m8_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv8i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vlmul_trunc_v_i64m8_i64m1(vint64m8_t op1) { + return vlmul_trunc_i64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i64m8_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv8i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vlmul_trunc_v_i64m8_i64m2(vint64m8_t op1) { + return vlmul_trunc_i64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_i64m8_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i64.nxv8i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vlmul_trunc_v_i64m8_i64m4(vint64m8_t op1) { + return vlmul_trunc_i64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8mf4_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv2i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf8_t test_vlmul_trunc_v_u8mf4_u8mf8(vuint8mf4_t op1) { + return vlmul_trunc_u8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8mf2_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv4i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf8_t test_vlmul_trunc_v_u8mf2_u8mf8(vuint8mf2_t op1) { + return vlmul_trunc_u8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8mf2_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv4i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vlmul_trunc_v_u8mf2_u8mf4(vuint8mf2_t op1) { + return vlmul_trunc_u8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m1_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv8i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf8_t test_vlmul_trunc_v_u8m1_u8mf8(vuint8m1_t op1) { + return vlmul_trunc_u8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m1_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv8i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vlmul_trunc_v_u8m1_u8mf4(vuint8m1_t op1) { + return vlmul_trunc_u8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m1_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv8i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vlmul_trunc_v_u8m1_u8mf2(vuint8m1_t op1) { + return vlmul_trunc_u8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m2_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf8_t test_vlmul_trunc_v_u8m2_u8mf8(vuint8m2_t op1) { + return vlmul_trunc_u8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m2_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vlmul_trunc_v_u8m2_u8mf4(vuint8m2_t op1) { + return vlmul_trunc_u8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m2_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vlmul_trunc_v_u8m2_u8mf2(vuint8m2_t op1) { + return vlmul_trunc_u8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m2_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv16i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vlmul_trunc_v_u8m2_u8m1(vuint8m2_t op1) { + return vlmul_trunc_u8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m4_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf8_t test_vlmul_trunc_v_u8m4_u8mf8(vuint8m4_t op1) { + return vlmul_trunc_u8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m4_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vlmul_trunc_v_u8m4_u8mf4(vuint8m4_t op1) { + return vlmul_trunc_u8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m4_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vlmul_trunc_v_u8m4_u8mf2(vuint8m4_t op1) { + return vlmul_trunc_u8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m4_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vlmul_trunc_v_u8m4_u8m1(vuint8m4_t op1) { + return vlmul_trunc_u8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m4_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv32i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vlmul_trunc_v_u8m4_u8m2(vuint8m4_t op1) { + return vlmul_trunc_u8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m8_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf8_t test_vlmul_trunc_v_u8m8_u8mf8(vuint8m8_t op1) { + return vlmul_trunc_u8mf8(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m8_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vlmul_trunc_v_u8m8_u8mf4(vuint8m8_t op1) { + return vlmul_trunc_u8mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m8_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vlmul_trunc_v_u8m8_u8mf2(vuint8m8_t op1) { + return vlmul_trunc_u8mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m8_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vlmul_trunc_v_u8m8_u8m1(vuint8m8_t op1) { + return vlmul_trunc_u8m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m8_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vlmul_trunc_v_u8m8_u8m2(vuint8m8_t op1) { + return vlmul_trunc_u8m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u8m8_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv32i8.nxv64i8( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vlmul_trunc_v_u8m8_u8m4(vuint8m8_t op1) { + return vlmul_trunc_u8m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16mf2_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv2i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf4_t test_vlmul_trunc_v_u16mf2_u16mf4(vuint16mf2_t op1) { + return vlmul_trunc_u16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m1_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv4i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf4_t test_vlmul_trunc_v_u16m1_u16mf4(vuint16m1_t op1) { + return vlmul_trunc_u16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m1_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv4i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vlmul_trunc_v_u16m1_u16mf2(vuint16m1_t op1) { + return vlmul_trunc_u16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m2_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv8i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf4_t test_vlmul_trunc_v_u16m2_u16mf4(vuint16m2_t op1) { + return vlmul_trunc_u16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m2_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv8i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vlmul_trunc_v_u16m2_u16mf2(vuint16m2_t op1) { + return vlmul_trunc_u16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m2_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv8i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vlmul_trunc_v_u16m2_u16m1(vuint16m2_t op1) { + return vlmul_trunc_u16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m4_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf4_t test_vlmul_trunc_v_u16m4_u16mf4(vuint16m4_t op1) { + return vlmul_trunc_u16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m4_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vlmul_trunc_v_u16m4_u16mf2(vuint16m4_t op1) { + return vlmul_trunc_u16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m4_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vlmul_trunc_v_u16m4_u16m1(vuint16m4_t op1) { + return vlmul_trunc_u16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m4_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv16i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vlmul_trunc_v_u16m4_u16m2(vuint16m4_t op1) { + return vlmul_trunc_u16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m8_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf4_t test_vlmul_trunc_v_u16m8_u16mf4(vuint16m8_t op1) { + return vlmul_trunc_u16mf4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m8_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vlmul_trunc_v_u16m8_u16mf2(vuint16m8_t op1) { + return vlmul_trunc_u16mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m8_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vlmul_trunc_v_u16m8_u16m1(vuint16m8_t op1) { + return vlmul_trunc_u16m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m8_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vlmul_trunc_v_u16m8_u16m2(vuint16m8_t op1) { + return vlmul_trunc_u16m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u16m8_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv16i16.nxv32i16( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vlmul_trunc_v_u16m8_u16m4(vuint16m8_t op1) { + return vlmul_trunc_u16m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m1_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv2i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vlmul_trunc_v_u32m1_u32mf2(vuint32m1_t op1) { + return vlmul_trunc_u32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m2_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv4i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vlmul_trunc_v_u32m2_u32mf2(vuint32m2_t op1) { + return vlmul_trunc_u32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m2_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv4i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vlmul_trunc_v_u32m2_u32m1(vuint32m2_t op1) { + return vlmul_trunc_u32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m4_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv8i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vlmul_trunc_v_u32m4_u32mf2(vuint32m4_t op1) { + return vlmul_trunc_u32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m4_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv8i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vlmul_trunc_v_u32m4_u32m1(vuint32m4_t op1) { + return vlmul_trunc_u32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m4_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv8i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vlmul_trunc_v_u32m4_u32m2(vuint32m4_t op1) { + return vlmul_trunc_u32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m8_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vlmul_trunc_v_u32m8_u32mf2(vuint32m8_t op1) { + return vlmul_trunc_u32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m8_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vlmul_trunc_v_u32m8_u32m1(vuint32m8_t op1) { + return vlmul_trunc_u32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m8_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vlmul_trunc_v_u32m8_u32m2(vuint32m8_t op1) { + return vlmul_trunc_u32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u32m8_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8i32.nxv16i32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vlmul_trunc_v_u32m8_u32m4(vuint32m8_t op1) { + return vlmul_trunc_u32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u64m2_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv2i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vlmul_trunc_v_u64m2_u64m1(vuint64m2_t op1) { + return vlmul_trunc_u64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u64m4_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv4i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vlmul_trunc_v_u64m4_u64m1(vuint64m4_t op1) { + return vlmul_trunc_u64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u64m4_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv4i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vlmul_trunc_v_u64m4_u64m2(vuint64m4_t op1) { + return vlmul_trunc_u64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u64m8_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1i64.nxv8i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vlmul_trunc_v_u64m8_u64m1(vuint64m8_t op1) { + return vlmul_trunc_u64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u64m8_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2i64.nxv8i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vlmul_trunc_v_u64m8_u64m2(vuint64m8_t op1) { + return vlmul_trunc_u64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_u64m8_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4i64.nxv8i64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vlmul_trunc_v_u64m8_u64m4(vuint64m8_t op1) { + return vlmul_trunc_u64m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m1_f32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f32.nxv2f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32mf2_t test_vlmul_trunc_v_f32m1_f32mf2(vfloat32m1_t op1) { + return vlmul_trunc_f32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m2_f32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f32.nxv4f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32mf2_t test_vlmul_trunc_v_f32m2_f32mf2(vfloat32m2_t op1) { + return vlmul_trunc_f32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m2_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f32.nxv4f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vlmul_trunc_v_f32m2_f32m1(vfloat32m2_t op1) { + return vlmul_trunc_f32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m4_f32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f32.nxv8f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32mf2_t test_vlmul_trunc_v_f32m4_f32mf2(vfloat32m4_t op1) { + return vlmul_trunc_f32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m4_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f32.nxv8f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vlmul_trunc_v_f32m4_f32m1(vfloat32m4_t op1) { + return vlmul_trunc_f32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m4_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4f32.nxv8f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vlmul_trunc_v_f32m4_f32m2(vfloat32m4_t op1) { + return vlmul_trunc_f32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m8_f32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f32.nxv16f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32mf2_t test_vlmul_trunc_v_f32m8_f32mf2(vfloat32m8_t op1) { + return vlmul_trunc_f32mf2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m8_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f32.nxv16f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vlmul_trunc_v_f32m8_f32m1(vfloat32m8_t op1) { + return vlmul_trunc_f32m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m8_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4f32.nxv16f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vlmul_trunc_v_f32m8_f32m2(vfloat32m8_t op1) { + return vlmul_trunc_f32m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f32m8_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv8f32.nxv16f32( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vlmul_trunc_v_f32m8_f32m4(vfloat32m8_t op1) { + return vlmul_trunc_f32m4(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f64m2_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f64.nxv2f64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vlmul_trunc_v_f64m2_f64m1(vfloat64m2_t op1) { + return vlmul_trunc_f64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f64m4_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f64.nxv4f64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vlmul_trunc_v_f64m4_f64m1(vfloat64m4_t op1) { + return vlmul_trunc_f64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f64m4_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f64.nxv4f64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vlmul_trunc_v_f64m4_f64m2(vfloat64m4_t op1) { + return vlmul_trunc_f64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f64m8_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv1f64.nxv8f64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vlmul_trunc_v_f64m8_f64m1(vfloat64m8_t op1) { + return vlmul_trunc_f64m1(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f64m8_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv2f64.nxv8f64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vlmul_trunc_v_f64m8_f64m2(vfloat64m8_t op1) { + return vlmul_trunc_f64m2(op1); +} + +// CHECK-RV64-LABEL: @test_vlmul_trunc_v_f64m8_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.extract.nxv4f64.nxv8f64( [[OP1:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vlmul_trunc_v_f64m8_f64m4(vfloat64m8_t op1) { + return vlmul_trunc_f64m4(op1); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vreinterpret.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vreinterpret.c new file mode 100644 index 0000000000000..760e697d9398a --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vreinterpret.c @@ -0,0 +1,1690 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-feature +experimental-v \ +// RUN: -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8mf8_u8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8mf8_t test_vreinterpret_v_i8mf8_u8mf8(vint8mf8_t src) { + return vreinterpret_u8mf8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8mf4_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8mf4_t test_vreinterpret_v_i8mf4_u8mf4(vint8mf4_t src) { + return vreinterpret_u8mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8mf2_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8mf2_t test_vreinterpret_v_i8mf2_u8mf2(vint8mf2_t src) { + return vreinterpret_u8mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m1_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8m1_t test_vreinterpret_v_i8m1_u8m1(vint8m1_t src) { + return vreinterpret_u8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m2_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8m2_t test_vreinterpret_v_i8m2_u8m2(vint8m2_t src) { + return vreinterpret_u8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m4_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8m4_t test_vreinterpret_v_i8m4_u8m4(vint8m4_t src) { + return vreinterpret_u8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m8_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint8m8_t test_vreinterpret_v_i8m8_u8m8(vint8m8_t src) { + return vreinterpret_u8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8mf8_i8mf8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8mf8_t test_vreinterpret_v_u8mf8_i8mf8(vuint8mf8_t src) { + return vreinterpret_i8mf8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8mf4_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8mf4_t test_vreinterpret_v_u8mf4_i8mf4(vuint8mf4_t src) { + return vreinterpret_i8mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8mf2_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8mf2_t test_vreinterpret_v_u8mf2_i8mf2(vuint8mf2_t src) { + return vreinterpret_i8mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m1_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8m1_t test_vreinterpret_v_u8m1_i8m1(vuint8m1_t src) { + return vreinterpret_i8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m2_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8m2_t test_vreinterpret_v_u8m2_i8m2(vuint8m2_t src) { + return vreinterpret_i8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m4_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8m4_t test_vreinterpret_v_u8m4_i8m4(vuint8m4_t src) { + return vreinterpret_i8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m8_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint8m8_t test_vreinterpret_v_u8m8_i8m8(vuint8m8_t src) { + return vreinterpret_i8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16mf4_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint16mf4_t test_vreinterpret_v_i16mf4_u16mf4(vint16mf4_t src) { + return vreinterpret_u16mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16mf2_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint16mf2_t test_vreinterpret_v_i16mf2_u16mf2(vint16mf2_t src) { + return vreinterpret_u16mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m1_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint16m1_t test_vreinterpret_v_i16m1_u16m1(vint16m1_t src) { + return vreinterpret_u16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m2_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint16m2_t test_vreinterpret_v_i16m2_u16m2(vint16m2_t src) { + return vreinterpret_u16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m4_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint16m4_t test_vreinterpret_v_i16m4_u16m4(vint16m4_t src) { + return vreinterpret_u16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m8_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint16m8_t test_vreinterpret_v_i16m8_u16m8(vint16m8_t src) { + return vreinterpret_u16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16mf4_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint16mf4_t test_vreinterpret_v_u16mf4_i16mf4(vuint16mf4_t src) { + return vreinterpret_i16mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16mf2_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint16mf2_t test_vreinterpret_v_u16mf2_i16mf2(vuint16mf2_t src) { + return vreinterpret_i16mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m1_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint16m1_t test_vreinterpret_v_u16m1_i16m1(vuint16m1_t src) { + return vreinterpret_i16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m2_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint16m2_t test_vreinterpret_v_u16m2_i16m2(vuint16m2_t src) { + return vreinterpret_i16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m4_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint16m4_t test_vreinterpret_v_u16m4_i16m4(vuint16m4_t src) { + return vreinterpret_i16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m8_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint16m8_t test_vreinterpret_v_u16m8_i16m8(vuint16m8_t src) { + return vreinterpret_i16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32mf2_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint32mf2_t test_vreinterpret_v_i32mf2_u32mf2(vint32mf2_t src) { + return vreinterpret_u32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m1_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint32m1_t test_vreinterpret_v_i32m1_u32m1(vint32m1_t src) { + return vreinterpret_u32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m2_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint32m2_t test_vreinterpret_v_i32m2_u32m2(vint32m2_t src) { + return vreinterpret_u32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m4_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint32m4_t test_vreinterpret_v_i32m4_u32m4(vint32m4_t src) { + return vreinterpret_u32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m8_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint32m8_t test_vreinterpret_v_i32m8_u32m8(vint32m8_t src) { + return vreinterpret_u32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32mf2_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint32mf2_t test_vreinterpret_v_u32mf2_i32mf2(vuint32mf2_t src) { + return vreinterpret_i32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m1_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint32m1_t test_vreinterpret_v_u32m1_i32m1(vuint32m1_t src) { + return vreinterpret_i32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m2_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint32m2_t test_vreinterpret_v_u32m2_i32m2(vuint32m2_t src) { + return vreinterpret_i32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m4_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint32m4_t test_vreinterpret_v_u32m4_i32m4(vuint32m4_t src) { + return vreinterpret_i32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m8_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint32m8_t test_vreinterpret_v_u32m8_i32m8(vuint32m8_t src) { + return vreinterpret_i32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32mf2_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vreinterpret_v_f32mf2_i32mf2(vfloat32mf2_t src) { + return vreinterpret_i32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m1_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vreinterpret_v_f32m1_i32m1(vfloat32m1_t src) { + return vreinterpret_i32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m2_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vreinterpret_v_f32m2_i32m2(vfloat32m2_t src) { + return vreinterpret_i32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m4_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vreinterpret_v_f32m4_i32m4(vfloat32m4_t src) { + return vreinterpret_i32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m8_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vreinterpret_v_f32m8_i32m8(vfloat32m8_t src) { + return vreinterpret_i32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32mf2_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vreinterpret_v_f32mf2_u32mf2(vfloat32mf2_t src) { + return vreinterpret_u32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m1_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vreinterpret_v_f32m1_u32m1(vfloat32m1_t src) { + return vreinterpret_u32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m2_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vreinterpret_v_f32m2_u32m2(vfloat32m2_t src) { + return vreinterpret_u32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m4_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vreinterpret_v_f32m4_u32m4(vfloat32m4_t src) { + return vreinterpret_u32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f32m8_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vreinterpret_v_f32m8_u32m8(vfloat32m8_t src) { + return vreinterpret_u32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32mf2_f32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32mf2_t test_vreinterpret_v_i32mf2_f32mf2(vint32mf2_t src) { + return vreinterpret_f32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m1_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vreinterpret_v_i32m1_f32m1(vint32m1_t src) { + return vreinterpret_f32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m2_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vreinterpret_v_i32m2_f32m2(vint32m2_t src) { + return vreinterpret_f32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m4_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vreinterpret_v_i32m4_f32m4(vint32m4_t src) { + return vreinterpret_f32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m8_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vreinterpret_v_i32m8_f32m8(vint32m8_t src) { + return vreinterpret_f32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32mf2_f32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32mf2_t test_vreinterpret_v_u32mf2_f32mf2(vuint32mf2_t src) { + return vreinterpret_f32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m1_f32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m1_t test_vreinterpret_v_u32m1_f32m1(vuint32m1_t src) { + return vreinterpret_f32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m2_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vreinterpret_v_u32m2_f32m2(vuint32m2_t src) { + return vreinterpret_f32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m4_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vreinterpret_v_u32m4_f32m4(vuint32m4_t src) { + return vreinterpret_f32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m8_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vreinterpret_v_u32m8_f32m8(vuint32m8_t src) { + return vreinterpret_f32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m1_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint64m1_t test_vreinterpret_v_i64m1_u64m1(vint64m1_t src) { + return vreinterpret_u64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m2_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint64m2_t test_vreinterpret_v_i64m2_u64m2(vint64m2_t src) { + return vreinterpret_u64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m4_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint64m4_t test_vreinterpret_v_i64m4_u64m4(vint64m4_t src) { + return vreinterpret_u64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m8_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vuint64m8_t test_vreinterpret_v_i64m8_u64m8(vint64m8_t src) { + return vreinterpret_u64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m1_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint64m1_t test_vreinterpret_v_u64m1_i64m1(vuint64m1_t src) { + return vreinterpret_i64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m2_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint64m2_t test_vreinterpret_v_u64m2_i64m2(vuint64m2_t src) { + return vreinterpret_i64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m4_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint64m4_t test_vreinterpret_v_u64m4_i64m4(vuint64m4_t src) { + return vreinterpret_i64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m8_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: ret [[SRC:%.*]] +// +vint64m8_t test_vreinterpret_v_u64m8_i64m8(vuint64m8_t src) { + return vreinterpret_i64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m1_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vreinterpret_v_f64m1_i64m1(vfloat64m1_t src) { + return vreinterpret_i64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m2_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vreinterpret_v_f64m2_i64m2(vfloat64m2_t src) { + return vreinterpret_i64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m4_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vreinterpret_v_f64m4_i64m4(vfloat64m4_t src) { + return vreinterpret_i64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m8_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vreinterpret_v_f64m8_i64m8(vfloat64m8_t src) { + return vreinterpret_i64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m1_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vreinterpret_v_f64m1_u64m1(vfloat64m1_t src) { + return vreinterpret_u64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m2_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vreinterpret_v_f64m2_u64m2(vfloat64m2_t src) { + return vreinterpret_u64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m4_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vreinterpret_v_f64m4_u64m4(vfloat64m4_t src) { + return vreinterpret_u64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_f64m8_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vreinterpret_v_f64m8_u64m8(vfloat64m8_t src) { + return vreinterpret_u64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m1_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vreinterpret_v_i64m1_f64m1(vint64m1_t src) { + return vreinterpret_f64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m2_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vreinterpret_v_i64m2_f64m2(vint64m2_t src) { + return vreinterpret_f64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m4_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vreinterpret_v_i64m4_f64m4(vint64m4_t src) { + return vreinterpret_f64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m8_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vreinterpret_v_i64m8_f64m8(vint64m8_t src) { + return vreinterpret_f64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m1_f64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m1_t test_vreinterpret_v_u64m1_f64m1(vuint64m1_t src) { + return vreinterpret_f64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m2_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vreinterpret_v_u64m2_f64m2(vuint64m2_t src) { + return vreinterpret_f64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m4_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vreinterpret_v_u64m4_f64m4(vuint64m4_t src) { + return vreinterpret_f64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m8_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vreinterpret_v_u64m8_f64m8(vuint64m8_t src) { + return vreinterpret_f64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8mf4_i16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf4_t test_vreinterpret_v_i8mf4_i16mf4(vint8mf4_t src) { + return vreinterpret_i16mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8mf2_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vreinterpret_v_i8mf2_i16mf2(vint8mf2_t src) { + return vreinterpret_i16mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m1_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vreinterpret_v_i8m1_i16m1(vint8m1_t src) { + return vreinterpret_i16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m2_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vreinterpret_v_i8m2_i16m2(vint8m2_t src) { + return vreinterpret_i16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m4_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vreinterpret_v_i8m4_i16m4(vint8m4_t src) { + return vreinterpret_i16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m8_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vreinterpret_v_i8m8_i16m8(vint8m8_t src) { + return vreinterpret_i16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8mf4_u16mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf4_t test_vreinterpret_v_u8mf4_u16mf4(vuint8mf4_t src) { + return vreinterpret_u16mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8mf2_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vreinterpret_v_u8mf2_u16mf2(vuint8mf2_t src) { + return vreinterpret_u16mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m1_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vreinterpret_v_u8m1_u16m1(vuint8m1_t src) { + return vreinterpret_u16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m2_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vreinterpret_v_u8m2_u16m2(vuint8m2_t src) { + return vreinterpret_u16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m4_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vreinterpret_v_u8m4_u16m4(vuint8m4_t src) { + return vreinterpret_u16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m8_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vreinterpret_v_u8m8_u16m8(vuint8m8_t src) { + return vreinterpret_u16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8mf2_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vreinterpret_v_i8mf2_i32mf2(vint8mf2_t src) { + return vreinterpret_i32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m1_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vreinterpret_v_i8m1_i32m1(vint8m1_t src) { + return vreinterpret_i32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m2_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vreinterpret_v_i8m2_i32m2(vint8m2_t src) { + return vreinterpret_i32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m4_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vreinterpret_v_i8m4_i32m4(vint8m4_t src) { + return vreinterpret_i32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m8_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vreinterpret_v_i8m8_i32m8(vint8m8_t src) { + return vreinterpret_i32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8mf2_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vreinterpret_v_u8mf2_u32mf2(vuint8mf2_t src) { + return vreinterpret_u32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m1_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vreinterpret_v_u8m1_u32m1(vuint8m1_t src) { + return vreinterpret_u32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m2_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vreinterpret_v_u8m2_u32m2(vuint8m2_t src) { + return vreinterpret_u32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m4_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vreinterpret_v_u8m4_u32m4(vuint8m4_t src) { + return vreinterpret_u32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m8_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vreinterpret_v_u8m8_u32m8(vuint8m8_t src) { + return vreinterpret_u32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m1_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vreinterpret_v_i8m1_i64m1(vint8m1_t src) { + return vreinterpret_i64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m2_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vreinterpret_v_i8m2_i64m2(vint8m2_t src) { + return vreinterpret_i64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m4_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vreinterpret_v_i8m4_i64m4(vint8m4_t src) { + return vreinterpret_i64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i8m8_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vreinterpret_v_i8m8_i64m8(vint8m8_t src) { + return vreinterpret_i64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m1_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vreinterpret_v_u8m1_u64m1(vuint8m1_t src) { + return vreinterpret_u64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m2_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vreinterpret_v_u8m2_u64m2(vuint8m2_t src) { + return vreinterpret_u64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m4_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vreinterpret_v_u8m4_u64m4(vuint8m4_t src) { + return vreinterpret_u64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u8m8_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vreinterpret_v_u8m8_u64m8(vuint8m8_t src) { + return vreinterpret_u64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16mf4_i8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf4_t test_vreinterpret_v_i16mf4_i8mf4(vint16mf4_t src) { + return vreinterpret_i8mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16mf2_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vreinterpret_v_i16mf2_i8mf2(vint16mf2_t src) { + return vreinterpret_i8mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m1_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vreinterpret_v_i16m1_i8m1(vint16m1_t src) { + return vreinterpret_i8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m2_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vreinterpret_v_i16m2_i8m2(vint16m2_t src) { + return vreinterpret_i8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m4_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vreinterpret_v_i16m4_i8m4(vint16m4_t src) { + return vreinterpret_i8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m8_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vreinterpret_v_i16m8_i8m8(vint16m8_t src) { + return vreinterpret_i8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16mf4_u8mf4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf4_t test_vreinterpret_v_u16mf4_u8mf4(vuint16mf4_t src) { + return vreinterpret_u8mf4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16mf2_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vreinterpret_v_u16mf2_u8mf2(vuint16mf2_t src) { + return vreinterpret_u8mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m1_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vreinterpret_v_u16m1_u8m1(vuint16m1_t src) { + return vreinterpret_u8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m2_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vreinterpret_v_u16m2_u8m2(vuint16m2_t src) { + return vreinterpret_u8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m4_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vreinterpret_v_u16m4_u8m4(vuint16m4_t src) { + return vreinterpret_u8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m8_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vreinterpret_v_u16m8_u8m8(vuint16m8_t src) { + return vreinterpret_u8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16mf2_i32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32mf2_t test_vreinterpret_v_i16mf2_i32mf2(vint16mf2_t src) { + return vreinterpret_i32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m1_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vreinterpret_v_i16m1_i32m1(vint16m1_t src) { + return vreinterpret_i32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m2_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vreinterpret_v_i16m2_i32m2(vint16m2_t src) { + return vreinterpret_i32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m4_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vreinterpret_v_i16m4_i32m4(vint16m4_t src) { + return vreinterpret_i32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m8_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vreinterpret_v_i16m8_i32m8(vint16m8_t src) { + return vreinterpret_i32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16mf2_u32mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32mf2_t test_vreinterpret_v_u16mf2_u32mf2(vuint16mf2_t src) { + return vreinterpret_u32mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m1_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vreinterpret_v_u16m1_u32m1(vuint16m1_t src) { + return vreinterpret_u32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m2_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vreinterpret_v_u16m2_u32m2(vuint16m2_t src) { + return vreinterpret_u32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m4_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vreinterpret_v_u16m4_u32m4(vuint16m4_t src) { + return vreinterpret_u32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m8_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vreinterpret_v_u16m8_u32m8(vuint16m8_t src) { + return vreinterpret_u32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m1_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vreinterpret_v_i16m1_i64m1(vint16m1_t src) { + return vreinterpret_i64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m2_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vreinterpret_v_i16m2_i64m2(vint16m2_t src) { + return vreinterpret_i64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m4_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vreinterpret_v_i16m4_i64m4(vint16m4_t src) { + return vreinterpret_i64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i16m8_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vreinterpret_v_i16m8_i64m8(vint16m8_t src) { + return vreinterpret_i64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m1_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vreinterpret_v_u16m1_u64m1(vuint16m1_t src) { + return vreinterpret_u64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m2_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vreinterpret_v_u16m2_u64m2(vuint16m2_t src) { + return vreinterpret_u64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m4_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vreinterpret_v_u16m4_u64m4(vuint16m4_t src) { + return vreinterpret_u64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u16m8_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vreinterpret_v_u16m8_u64m8(vuint16m8_t src) { + return vreinterpret_u64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32mf2_i8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8mf2_t test_vreinterpret_v_i32mf2_i8mf2(vint32mf2_t src) { + return vreinterpret_i8mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m1_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vreinterpret_v_i32m1_i8m1(vint32m1_t src) { + return vreinterpret_i8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m2_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vreinterpret_v_i32m2_i8m2(vint32m2_t src) { + return vreinterpret_i8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m4_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vreinterpret_v_i32m4_i8m4(vint32m4_t src) { + return vreinterpret_i8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m8_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vreinterpret_v_i32m8_i8m8(vint32m8_t src) { + return vreinterpret_i8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32mf2_u8mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8mf2_t test_vreinterpret_v_u32mf2_u8mf2(vuint32mf2_t src) { + return vreinterpret_u8mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m1_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vreinterpret_v_u32m1_u8m1(vuint32m1_t src) { + return vreinterpret_u8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m2_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vreinterpret_v_u32m2_u8m2(vuint32m2_t src) { + return vreinterpret_u8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m4_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vreinterpret_v_u32m4_u8m4(vuint32m4_t src) { + return vreinterpret_u8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m8_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vreinterpret_v_u32m8_u8m8(vuint32m8_t src) { + return vreinterpret_u8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32mf2_i16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16mf2_t test_vreinterpret_v_i32mf2_i16mf2(vint32mf2_t src) { + return vreinterpret_i16mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m1_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vreinterpret_v_i32m1_i16m1(vint32m1_t src) { + return vreinterpret_i16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m2_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vreinterpret_v_i32m2_i16m2(vint32m2_t src) { + return vreinterpret_i16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m4_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vreinterpret_v_i32m4_i16m4(vint32m4_t src) { + return vreinterpret_i16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m8_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vreinterpret_v_i32m8_i16m8(vint32m8_t src) { + return vreinterpret_i16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32mf2_u16mf2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16mf2_t test_vreinterpret_v_u32mf2_u16mf2(vuint32mf2_t src) { + return vreinterpret_u16mf2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m1_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vreinterpret_v_u32m1_u16m1(vuint32m1_t src) { + return vreinterpret_u16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m2_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vreinterpret_v_u32m2_u16m2(vuint32m2_t src) { + return vreinterpret_u16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m4_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vreinterpret_v_u32m4_u16m4(vuint32m4_t src) { + return vreinterpret_u16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m8_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vreinterpret_v_u32m8_u16m8(vuint32m8_t src) { + return vreinterpret_u16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m1_i64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m1_t test_vreinterpret_v_i32m1_i64m1(vint32m1_t src) { + return vreinterpret_i64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m2_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vreinterpret_v_i32m2_i64m2(vint32m2_t src) { + return vreinterpret_i64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m4_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vreinterpret_v_i32m4_i64m4(vint32m4_t src) { + return vreinterpret_i64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i32m8_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vreinterpret_v_i32m8_i64m8(vint32m8_t src) { + return vreinterpret_i64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m1_u64m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m1_t test_vreinterpret_v_u32m1_u64m1(vuint32m1_t src) { + return vreinterpret_u64m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m2_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vreinterpret_v_u32m2_u64m2(vuint32m2_t src) { + return vreinterpret_u64m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m4_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vreinterpret_v_u32m4_u64m4(vuint32m4_t src) { + return vreinterpret_u64m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u32m8_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vreinterpret_v_u32m8_u64m8(vuint32m8_t src) { + return vreinterpret_u64m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m1_i8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m1_t test_vreinterpret_v_i64m1_i8m1(vint64m1_t src) { + return vreinterpret_i8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m2_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vreinterpret_v_i64m2_i8m2(vint64m2_t src) { + return vreinterpret_i8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m4_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vreinterpret_v_i64m4_i8m4(vint64m4_t src) { + return vreinterpret_i8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m8_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vreinterpret_v_i64m8_i8m8(vint64m8_t src) { + return vreinterpret_i8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m1_u8m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m1_t test_vreinterpret_v_u64m1_u8m1(vuint64m1_t src) { + return vreinterpret_u8m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m2_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vreinterpret_v_u64m2_u8m2(vuint64m2_t src) { + return vreinterpret_u8m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m4_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vreinterpret_v_u64m4_u8m4(vuint64m4_t src) { + return vreinterpret_u8m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m8_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vreinterpret_v_u64m8_u8m8(vuint64m8_t src) { + return vreinterpret_u8m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m1_i16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m1_t test_vreinterpret_v_i64m1_i16m1(vint64m1_t src) { + return vreinterpret_i16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m2_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vreinterpret_v_i64m2_i16m2(vint64m2_t src) { + return vreinterpret_i16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m4_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vreinterpret_v_i64m4_i16m4(vint64m4_t src) { + return vreinterpret_i16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m8_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vreinterpret_v_i64m8_i16m8(vint64m8_t src) { + return vreinterpret_i16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m1_u16m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m1_t test_vreinterpret_v_u64m1_u16m1(vuint64m1_t src) { + return vreinterpret_u16m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m2_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vreinterpret_v_u64m2_u16m2(vuint64m2_t src) { + return vreinterpret_u16m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m4_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vreinterpret_v_u64m4_u16m4(vuint64m4_t src) { + return vreinterpret_u16m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m8_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vreinterpret_v_u64m8_u16m8(vuint64m8_t src) { + return vreinterpret_u16m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m1_i32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m1_t test_vreinterpret_v_i64m1_i32m1(vint64m1_t src) { + return vreinterpret_i32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m2_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vreinterpret_v_i64m2_i32m2(vint64m2_t src) { + return vreinterpret_i32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m4_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vreinterpret_v_i64m4_i32m4(vint64m4_t src) { + return vreinterpret_i32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_i64m8_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vreinterpret_v_i64m8_i32m8(vint64m8_t src) { + return vreinterpret_i32m8(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m1_u32m1( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m1_t test_vreinterpret_v_u64m1_u32m1(vuint64m1_t src) { + return vreinterpret_u32m1(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m2_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vreinterpret_v_u64m2_u32m2(vuint64m2_t src) { + return vreinterpret_u32m2(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m4_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vreinterpret_v_u64m4_u32m4(vuint64m4_t src) { + return vreinterpret_u32m4(src); +} + +// CHECK-RV64-LABEL: @test_vreinterpret_v_u64m8_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = bitcast [[SRC:%.*]] to +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vreinterpret_v_u64m8_u32m8(vuint64m8_t src) { + return vreinterpret_u32m8(src); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vset.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vset.c new file mode 100644 index 0000000000000..5db2ff82f5984 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vset.c @@ -0,0 +1,546 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-feature +experimental-v \ +// RUN: -disable-O0-optnone -emit-llvm %s -o - | opt -S -mem2reg | FileCheck --check-prefix=CHECK-RV64 %s + +#include + +// CHECK-RV64-LABEL: @test_vset_v_i8m1_i8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv8i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m2_t test_vset_v_i8m1_i8m2(vint8m2_t dest, size_t index, vint8m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i8m1_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv8i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vset_v_i8m1_i8m4(vint8m4_t dest, size_t index, vint8m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i8m2_i8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv16i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m4_t test_vset_v_i8m2_i8m4(vint8m4_t dest, size_t index, vint8m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i8m1_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv8i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vset_v_i8m1_i8m8(vint8m8_t dest, size_t index, vint8m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i8m2_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv16i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vset_v_i8m2_i8m8(vint8m8_t dest, size_t index, vint8m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i8m4_i8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv32i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint8m8_t test_vset_v_i8m4_i8m8(vint8m8_t dest, size_t index, vint8m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u8m1_u8m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i8.nxv8i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m2_t test_vset_v_u8m1_u8m2(vuint8m2_t dest, size_t index, vuint8m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u8m1_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv8i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vset_v_u8m1_u8m4(vuint8m4_t dest, size_t index, vuint8m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u8m2_u8m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i8.nxv16i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m4_t test_vset_v_u8m2_u8m4(vuint8m4_t dest, size_t index, vuint8m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u8m1_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv8i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vset_v_u8m1_u8m8(vuint8m8_t dest, size_t index, vuint8m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u8m2_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv16i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vset_v_u8m2_u8m8(vuint8m8_t dest, size_t index, vuint8m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u8m4_u8m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv64i8.nxv32i8( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint8m8_t test_vset_v_u8m4_u8m8(vuint8m8_t dest, size_t index, vuint8m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i16m1_i16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv4i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m2_t test_vset_v_i16m1_i16m2(vint16m2_t dest, size_t index, vint16m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i16m1_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv4i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vset_v_i16m1_i16m4(vint16m4_t dest, size_t index, vint16m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i16m2_i16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv8i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m4_t test_vset_v_i16m2_i16m4(vint16m4_t dest, size_t index, vint16m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i16m1_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv4i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vset_v_i16m1_i16m8(vint16m8_t dest, size_t index, vint16m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i16m2_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv8i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vset_v_i16m2_i16m8(vint16m8_t dest, size_t index, vint16m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i16m4_i16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv16i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint16m8_t test_vset_v_i16m4_i16m8(vint16m8_t dest, size_t index, vint16m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u16m1_u16m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i16.nxv4i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m2_t test_vset_v_u16m1_u16m2(vuint16m2_t dest, size_t index, vuint16m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u16m1_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv4i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vset_v_u16m1_u16m4(vuint16m4_t dest, size_t index, vuint16m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u16m2_u16m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i16.nxv8i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m4_t test_vset_v_u16m2_u16m4(vuint16m4_t dest, size_t index, vuint16m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u16m1_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv4i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vset_v_u16m1_u16m8(vuint16m8_t dest, size_t index, vuint16m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u16m2_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv8i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vset_v_u16m2_u16m8(vuint16m8_t dest, size_t index, vuint16m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u16m4_u16m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv32i16.nxv16i16( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint16m8_t test_vset_v_u16m4_u16m8(vuint16m8_t dest, size_t index, vuint16m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i32m1_i32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.nxv2i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m2_t test_vset_v_i32m1_i32m2(vint32m2_t dest, size_t index, vint32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i32m1_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv2i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vset_v_i32m1_i32m4(vint32m4_t dest, size_t index, vint32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i32m2_i32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv4i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m4_t test_vset_v_i32m2_i32m4(vint32m4_t dest, size_t index, vint32m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i32m1_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv2i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vset_v_i32m1_i32m8(vint32m8_t dest, size_t index, vint32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i32m2_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv4i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vset_v_i32m2_i32m8(vint32m8_t dest, size_t index, vint32m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i32m4_i32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv8i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint32m8_t test_vset_v_i32m4_i32m8(vint32m8_t dest, size_t index, vint32m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u32m1_u32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i32.nxv2i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m2_t test_vset_v_u32m1_u32m2(vuint32m2_t dest, size_t index, vuint32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u32m1_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv2i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vset_v_u32m1_u32m4(vuint32m4_t dest, size_t index, vuint32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u32m2_u32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i32.nxv4i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m4_t test_vset_v_u32m2_u32m4(vuint32m4_t dest, size_t index, vuint32m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u32m1_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv2i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vset_v_u32m1_u32m8(vuint32m8_t dest, size_t index, vuint32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u32m2_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv4i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vset_v_u32m2_u32m8(vuint32m8_t dest, size_t index, vuint32m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u32m4_u32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16i32.nxv8i32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint32m8_t test_vset_v_u32m4_u32m8(vuint32m8_t dest, size_t index, vuint32m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f32m1_f32m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f32.nxv2f32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m2_t test_vset_v_f32m1_f32m2(vfloat32m2_t dest, size_t index, vfloat32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f32m1_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f32.nxv2f32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vset_v_f32m1_f32m4(vfloat32m4_t dest, size_t index, vfloat32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f32m2_f32m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f32.nxv4f32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m4_t test_vset_v_f32m2_f32m4(vfloat32m4_t dest, size_t index, vfloat32m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f32m1_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv2f32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vset_v_f32m1_f32m8(vfloat32m8_t dest, size_t index, vfloat32m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f32m2_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv4f32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vset_v_f32m2_f32m8(vfloat32m8_t dest, size_t index, vfloat32m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f32m4_f32m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv16f32.nxv8f32( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat32m8_t test_vset_v_f32m4_f32m8(vfloat32m8_t dest, size_t index, vfloat32m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i64m1_i64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.nxv1i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m2_t test_vset_v_i64m1_i64m2(vint64m2_t dest, size_t index, vint64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i64m1_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv1i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vset_v_i64m1_i64m4(vint64m4_t dest, size_t index, vint64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i64m2_i64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv2i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m4_t test_vset_v_i64m2_i64m4(vint64m4_t dest, size_t index, vint64m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i64m1_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv1i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vset_v_i64m1_i64m8(vint64m8_t dest, size_t index, vint64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i64m2_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv2i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vset_v_i64m2_i64m8(vint64m8_t dest, size_t index, vint64m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_i64m4_i64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv4i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vint64m8_t test_vset_v_i64m4_i64m8(vint64m8_t dest, size_t index, vint64m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u64m1_u64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2i64.nxv1i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m2_t test_vset_v_u64m1_u64m2(vuint64m2_t dest, size_t index, vuint64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u64m1_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv1i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vset_v_u64m1_u64m4(vuint64m4_t dest, size_t index, vuint64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u64m2_u64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4i64.nxv2i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m4_t test_vset_v_u64m2_u64m4(vuint64m4_t dest, size_t index, vuint64m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u64m1_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv1i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vset_v_u64m1_u64m8(vuint64m8_t dest, size_t index, vuint64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u64m2_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv2i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vset_v_u64m2_u64m8(vuint64m8_t dest, size_t index, vuint64m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_u64m4_u64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8i64.nxv4i64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vuint64m8_t test_vset_v_u64m4_u64m8(vuint64m8_t dest, size_t index, vuint64m4_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f64m1_f64m2( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv2f64.nxv1f64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m2_t test_vset_v_f64m1_f64m2(vfloat64m2_t dest, size_t index, vfloat64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f64m1_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f64.nxv1f64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vset_v_f64m1_f64m4(vfloat64m4_t dest, size_t index, vfloat64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f64m2_f64m4( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv4f64.nxv2f64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m4_t test_vset_v_f64m2_f64m4(vfloat64m4_t dest, size_t index, vfloat64m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f64m1_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f64.nxv1f64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vset_v_f64m1_f64m8(vfloat64m8_t dest, size_t index, vfloat64m1_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f64m2_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f64.nxv2f64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vset_v_f64m2_f64m8(vfloat64m8_t dest, size_t index, vfloat64m2_t val) { + return vset(dest, 0, val); +} + +// CHECK-RV64-LABEL: @test_vset_v_f64m4_f64m8( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call @llvm.experimental.vector.insert.nxv8f64.nxv4f64( [[DEST:%.*]], [[VAL:%.*]], i64 0) +// CHECK-RV64-NEXT: ret [[TMP0]] +// +vfloat64m8_t test_vset_v_f64m4_f64m8(vfloat64m8_t dest, size_t index, vfloat64m4_t val) { + return vset(dest, 0, val); +} diff --git a/clang/test/CodeGen/asan-use-callbacks.cpp b/clang/test/CodeGen/asan-use-callbacks.cpp new file mode 100644 index 0000000000000..280b51701e075 --- /dev/null +++ b/clang/test/CodeGen/asan-use-callbacks.cpp @@ -0,0 +1,12 @@ +// RUN: %clang -S -fsanitize=address -emit-llvm -o - -fsanitize=address %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-NO-OUTLINE +// RUN: %clang -S -fsanitize=address -emit-llvm -o - -fsanitize=address %s \ +// RUN: -fsanitize-address-outline-instrumentation \ +// RUN: | FileCheck %s --check-prefixes=CHECK-OUTLINE + +// CHECK-NO-OUTLINE-NOT: call{{.*}}@__asan_load4 +// CHECK-OUTLINE: call{{.*}}@__asan_load4 + +int deref(int *p) { + return *p; +} diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-1.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-1.c index 59516b9057ce4..956b333f81520 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-1.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-1.c @@ -17,7 +17,7 @@ int test(__s1 *arg) { return arg->a + arg[1].b; } -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 1) -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 1) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-2.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-2.c index 3aa48fc43d599..8fe11e08c833f 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-2.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-2.c @@ -17,8 +17,8 @@ int test(__s1 *arg) { return arg->a[2] + arg->c[2]; } -// CHECK: call [3 x i32]* @llvm.preserve.struct.access.index.p0a3i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a3i32([3 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1) +// CHECK: call [3 x i32]* @llvm.preserve.struct.access.index.p0a3i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a3i32([3 x i32]* elementtype([3 x i32]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 1) -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* elementtype([4 x i32]) %{{[0-9a-z]+}}, i32 1, i32 2) diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-3.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-3.c index 2660b6cbb58ce..f78e0b35c0b51 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-3.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-3.c @@ -25,8 +25,8 @@ int test(__s3 *arg) { return arg->a.b[2].c; } -// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 0, i32 0) -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* %{{[0-9a-z]+}}, i32 1, i32 2) -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-4.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-4.c index 68f4b44a5e07d..6d3c44328c6ef 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-4.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-4.c @@ -27,7 +27,7 @@ int test(__s3 *arg) { // CHECK: define dso_local i32 @test // CHECK-NOT: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) // CHECK-NOT: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-5.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-5.c index 1224487914c4b..286916a990e63 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-5.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-5.c @@ -25,8 +25,8 @@ int test(__s3 *arg) { return arg->a.b[2].c; } -// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 0, i32 0) // CHECK-NOT: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* %{{[0-9a-z]+}}, i32 1, i32 2) -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-6.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-6.c index a9931a4129c2f..93be91b03e469 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-6.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-6.c @@ -25,8 +25,8 @@ int test(__s3 *arg) { return arg->a.b[2].c; } -// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 0, i32 0) -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* %{{[0-9a-z]+}}, i32 1, i32 2) -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-7.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-7.c index 5dd84948f6809..59af3ad4bfaa8 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-7.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-7.c @@ -29,8 +29,8 @@ int test(__s3 *arg) { return arg->a.b[2].c; } -// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 0, i32 0) -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* %{{[0-9a-z]+}}, i32 1, i32 2) -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) diff --git a/clang/test/CodeGen/bpf-attr-preserve-access-index-8.c b/clang/test/CodeGen/bpf-attr-preserve-access-index-8.c index 60f4825fdf7ed..7b6cb68bcf5aa 100644 --- a/clang/test/CodeGen/bpf-attr-preserve-access-index-8.c +++ b/clang/test/CodeGen/bpf-attr-preserve-access-index-8.c @@ -29,8 +29,8 @@ int test(__s3 *arg) { return arg->a.b[2].c; } -// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 0, i32 0) -// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s2* @llvm.preserve.struct.access.index.p0s_struct.s2s.p0s_struct.s3s(%struct.s3* elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0) // CHECK: call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %{{[0-9a-z]+}}, i32 0) -// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* %{{[0-9a-z]+}}, i32 1, i32 2) -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0) +// CHECK: call %struct.s1* @llvm.preserve.array.access.index.p0s_struct.s1s.p0a3s_struct.s1s([3 x %struct.s1]* elementtype([3 x %struct.s1]) %{{[0-9a-z]+}}, i32 1, i32 2) +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0) diff --git a/clang/test/CodeGen/builtin-preserve-access-index-array.c b/clang/test/CodeGen/builtin-preserve-access-index-array.c index a449b2845d4bf..9648c4d665221 100644 --- a/clang/test/CodeGen/builtin-preserve-access-index-array.c +++ b/clang/test/CodeGen/builtin-preserve-access-index-array.c @@ -11,8 +11,8 @@ const void *unit1(struct s1 *arg) { return _(&arg->b[2]); } // CHECK: define dso_local i8* @unit1 -// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]] +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* elementtype([4 x i32]) %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]] // // CHECK: ![[ARRAY]] = !DICompositeType(tag: DW_TAG_array_type // CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" diff --git a/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c b/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c index bb8caf4921bef..1d79d039298d8 100644 --- a/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c +++ b/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c @@ -11,8 +11,8 @@ int unit1(struct s1 *arg) { return _(arg->b[2]); } // CHECK: define dso_local i32 @unit1 -// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]] +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* elementtype([4 x i32]) %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]] // // CHECK: ![[ARRAY]] = !DICompositeType(tag: DW_TAG_array_type // CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" diff --git a/clang/test/CodeGen/builtin-preserve-access-index-typedef.c b/clang/test/CodeGen/builtin-preserve-access-index-typedef.c index f8ada8ac3760d..bf0fc0261c042 100644 --- a/clang/test/CodeGen/builtin-preserve-access-index-typedef.c +++ b/clang/test/CodeGen/builtin-preserve-access-index-typedef.c @@ -15,7 +15,7 @@ int test2(const __u *arg) { return arg->b; } // CHECK: define dso_local i32 @test1 -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ts(%struct.__t* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_STRUCT:[0-9]+]] +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ts(%struct.__t* elementtype(%struct.__t) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[TYPEDEF_STRUCT:[0-9]+]] // CHECK: define dso_local i32 @test2 // CHECK: call %union.__u* @llvm.preserve.union.access.index.p0s_union.__us.p0s_union.__us(%union.__u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[CONST_TYPEDEF:[0-9]+]] // diff --git a/clang/test/CodeGen/builtin-preserve-access-index.c b/clang/test/CodeGen/builtin-preserve-access-index.c index 10844166a6f0a..64f8835d777d2 100644 --- a/clang/test/CodeGen/builtin-preserve-access-index.c +++ b/clang/test/CodeGen/builtin-preserve-access-index.c @@ -31,16 +31,16 @@ const void *unit4(const int *arg) { } // CHECK: define dso_local i8* @unit4 // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* elementtype(i32) %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]] const void *unit5(const int *arg[5]) { return _(&arg[1][2]); } // CHECK: define dso_local i8* @unit5 // CHECK-NOT: getelementptr -// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} +// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** elementtype(i32*) %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* elementtype(i32) %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[POINTER:[0-9]+]] struct s1 { char a; @@ -65,28 +65,28 @@ const void *unit6(struct s1 *arg) { } // CHECK: define dso_local i8* @unit6 // CHECK-NOT: getelementptr -// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] const void *unit7(struct s1 *arg) { return _(&arg->b); } // CHECK: define dso_local i8* @unit7 // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1]] +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1]] const void *unit8(struct s2 *arg) { return _(&arg->b); } // CHECK: define dso_local i8* @unit8 // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] const void *unit9(struct s3 *arg) { return _(&arg->b); } // CHECK: define dso_local i8* @unit9 // CHECK-NOT: getelementptr -// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S3:[0-9]+]] +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s3s(%struct.s3* elementtype(%struct.s3) %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S3:[0-9]+]] union u1 { char a; @@ -139,31 +139,31 @@ const void *unit13(struct s4 *arg) { return _(&arg->c.b[2]); } // CHECK: define dso_local i8* @unit13 -// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]] +// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* elementtype(%struct.s4) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]] // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U:[0-9]+]] -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* elementtype([4 x i32]) %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} const void *unit14(union u3 *arg) { return _(&arg->c.b[2]); } // CHECK: define dso_local i8* @unit14 // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3:[0-9]+]] -// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]] -// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* elementtype(%struct.s) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* elementtype([4 x i32]) %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} const void *unit15(struct s4 *arg) { return _(&arg[2].c.a); } // CHECK: define dso_local i8* @unit15 -// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} -// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4]] +// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* elementtype(%struct.s4) %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} +// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* elementtype(%struct.s4) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4]] // CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U]] const void *unit16(union u3 *arg) { return _(&arg[2].a); } // CHECK: define dso_local i8* @unit16 -// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} +// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* elementtype(%union.u3) %{{[0-9a-z]+}}, i32 0, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}} // CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3]] // CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type diff --git a/clang/test/CodeGen/builtins-bpf-preserve-field-info-1.c b/clang/test/CodeGen/builtins-bpf-preserve-field-info-1.c index 0ec57f5c94d2c..20a69b1e72218 100644 --- a/clang/test/CodeGen/builtins-bpf-preserve-field-info-1.c +++ b/clang/test/CodeGen/builtins-bpf-preserve-field-info-1.c @@ -17,9 +17,9 @@ unsigned unit1(struct s1 *arg) { return _(arg->a, 10) + _(arg->b, 10); } // CHECK: define dso_local i32 @unit1 -// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] // CHECK: call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %{{[0-9a-z]+}}, i64 10), !dbg !{{[0-9]+}} -// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] // CHECK: call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %{{[0-9a-z]+}}, i64 10), !dbg !{{[0-9]+}} unsigned unit2(union u1 *arg) { @@ -28,7 +28,7 @@ unsigned unit2(union u1 *arg) { // CHECK: define dso_local i32 @unit2 // CHECK: call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1:[0-9]+]] // CHECK: call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %{{[0-9a-z]+}}, i64 10), !dbg !{{[0-9]+}} -// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_union.u1s(%union.u1* %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1:[0-9]+]] +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_union.u1s(%union.u1* elementtype(%union.u1) %{{[0-9a-z]+}}, i32 0, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1:[0-9]+]] // CHECK: call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %{{[0-9a-z]+}}, i64 10), !dbg !{{[0-9]+}} // CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" diff --git a/clang/test/CodeGen/builtins-bpf-preserve-field-info-2.c b/clang/test/CodeGen/builtins-bpf-preserve-field-info-2.c index 81168d5c9eb42..a285e9e292f13 100644 --- a/clang/test/CodeGen/builtins-bpf-preserve-field-info-2.c +++ b/clang/test/CodeGen/builtins-bpf-preserve-field-info-2.c @@ -15,11 +15,11 @@ unsigned unit1(struct s2 *arg) { return _(arg->s.a, 10) + _(arg->s.b, 10); } // CHECK: define dso_local i32 @unit1 -// CHECK: call %struct.s1* @llvm.preserve.struct.access.index.p0s_struct.s1s.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] -// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call %struct.s1* @llvm.preserve.struct.access.index.p0s_struct.s1s.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] // CHECK: call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %{{[0-9a-z]+}}, i64 10), !dbg !{{[0-9]+}} -// CHECK: call %struct.s1* @llvm.preserve.struct.access.index.p0s_struct.s1s.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] -// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call %struct.s1* @llvm.preserve.struct.access.index.p0s_struct.s1s.p0s_struct.s2s(%struct.s2* elementtype(%struct.s2) %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* elementtype(%struct.s1) %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] // CHECK: call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %{{[0-9a-z]+}}, i64 10), !dbg !{{[0-9]+}} // CHECK: ![[STRUCT_S2]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s2" diff --git a/clang/test/CodeGen/builtins-nvptx-mma.cu b/clang/test/CodeGen/builtins-nvptx-mma.cu index 7e9bac86792d2..aaa44bcaa7e22 100644 --- a/clang/test/CodeGen/builtins-nvptx-mma.cu +++ b/clang/test/CodeGen/builtins-nvptx-mma.cu @@ -3,20 +3,21 @@ // *** DO NOT EDIT *** // // This test has been automatically generated by -// builtins-nvtx-mma.py --ptx=70 --gpu-arch=80 +// builtins-nvtx-mma.py --ptx=71 --gpu-arch=80 // -// Make sure we can handle all builtins available on sm_80 with PTX70 +// Make sure we can handle all builtins available on sm_80 with PTX71 // RUN: %clang_cc1 -triple nvptx64-unknown-unknown -target-cpu sm_80 \ -// RUN: -fcuda-is-device -target-feature +ptx70 \ -// RUN: -DPTX=70 -DSM=80 \ +// RUN: -fcuda-is-device -target-feature +ptx71 \ +// RUN: -DPTX=71 -DSM=80 \ // RUN: -S -emit-llvm -o - -x cuda %s \ -// RUN: | FileCheck -check-prefixes=CHECK_PTX70_SM80,CHECK_PTX60_SM70,CHECK_PTX63_SM72,CHECK_PTX61_SM70,CHECK_PTX63_SM75 %s +// RUN: | FileCheck -check-prefixes=CHECK_PTX70_SM80,CHECK_PTX60_SM70,CHECK_PTX63_SM72,CHECK_PTX61_SM70,CHECK_PTX63_SM75,CHECK_PTX71_SM75 %s // Verify that all builtins have correct constraints. // RUN: %clang_cc1 -triple nvptx-unknown-unknown \ // RUN: -target-cpu sm_60 -target-feature +ptx42 \ -// RUN: -DPTX=70 -DSM=80 -fcuda-is-device -S -o /dev/null -x cuda \ +// RUN: -DPTX=71 -DSM=80 -fcuda-is-device -S -o /dev/null -x cuda \ // RUN: -verify %s + #if !defined(CUDA_VERSION) #define __device__ __attribute__((device)) #define __global__ __attribute__((global)) @@ -31,6 +32,7 @@ __device__ void test_wmma_buitins(int *src, int *dst, float *fsrc, float *fdst, double *dsrc, double *ddst, int ldm) { + #if (PTX >= 60) && (SM >= 70) // CHECK_PTX60_SM70: call {{.*}} @llvm.nvvm.wmma.m16n16k16.load.a.col.stride.f16 @@ -735,7 +737,7 @@ __device__ void test_wmma_buitins(int *src, int *dst, // CHECK_PTX63_SM75: call {{.*}} @llvm.nvvm.wmma.m8n8k32.store.d.row.stride.s32 // expected-error-re@+1 {{'__imma_m8n8k32_st_c_i32' needs target feature (sm_75{{.*}},(ptx63{{.*}}}} __imma_m8n8k32_st_c_i32(dst, src, ldm, 0); - // CHECK_PTX63_SM75: call {{.*}} @llvm.nvvm.wmma.m8n8k128.mma.row.col.b1 + // CHECK_PTX63_SM75: call {{.*}} @llvm.nvvm.wmma.m8n8k128.mma.xor.popc.row.col.b1 // expected-error-re@+1 {{'__bmma_m8n8k128_mma_xor_popc_b1' needs target feature (sm_75{{.*}},(ptx63{{.*}}}} __bmma_m8n8k128_mma_xor_popc_b1(dst, src, src, src, 1); // CHECK_PTX63_SM75: call {{.*}} @llvm.nvvm.wmma.m8n8k32.mma.row.col.s4 @@ -750,7 +752,7 @@ __device__ void test_wmma_buitins(int *src, int *dst, // CHECK_PTX63_SM75: call {{.*}} @llvm.nvvm.wmma.m8n8k32.mma.row.col.u4.satfinite // expected-error-re@+1 {{'__imma_m8n8k32_mma_u4' needs target feature (sm_75{{.*}},(ptx63{{.*}}}} __imma_m8n8k32_mma_u4(dst, src, src, src, 1, 1); -#endif // (PTX >= 63) && (SM >= 75) +#endif // (PTX >= 63) && (SM >= 75) #if (PTX >= 70) && (SM >= 80) @@ -898,5 +900,12 @@ __device__ void test_wmma_buitins(int *src, int *dst, // CHECK_PTX70_SM80: call {{.*}} @llvm.nvvm.wmma.m8n8k4.mma.row.row.f64 // expected-error-re@+1 {{'__dmma_m8n8k4_mma_f64' needs target feature (sm_80{{.*}},(ptx70{{.*}}}} __dmma_m8n8k4_mma_f64(ddst, dsrc, dsrc, dsrc, 0, 0); -#endif // (PTX >= 70) && (SM >= 80) +#endif // (PTX >= 70) && (SM >= 80) + +#if (PTX >= 71) && (SM >= 75) + + // CHECK_PTX71_SM75: call {{.*}} @llvm.nvvm.wmma.m8n8k128.mma.and.popc.row.col.b1 + // expected-error-re@+1 {{'__bmma_m8n8k128_mma_and_popc_b1' needs target feature (sm_75{{.*}},(ptx71{{.*}}}} + __bmma_m8n8k128_mma_and_popc_b1(dst, src, src, src, 1); +#endif // (PTX >= 71) && (SM >= 75) } diff --git a/clang/test/CodeGen/builtins-nvptx-mma.py b/clang/test/CodeGen/builtins-nvptx-mma.py index 2ffc21b12fb06..dc40f04c11ce6 100644 --- a/clang/test/CodeGen/builtins-nvptx-mma.py +++ b/clang/test/CodeGen/builtins-nvptx-mma.py @@ -22,24 +22,29 @@ def __repr__(self): return "%s:%s:%s" % (self.geom, self.frag, self.ptx_type) class MMAOp: - def __init__(self, a, b, c, d): + def __init__(self, a, b, c, d, b1op=""): self.a = a self.b = b self.c = c self.d = d + self.b1op = b1op def __repr__(self): return ("{A:%s, B:%s, C:%s, D:%s}" % (self.a, self.b, self.c, self.d )) -def make_mma_ops(geoms, types_a, types_b, types_c, types_d): +def make_mma_ops(geoms, types_a, types_b, types_c, types_d, b1ops=None): ops = [] + if b1ops is None: + b1ops = [""] for geom, type_a, type_c in product( geoms, types_a, types_c): for type_b, type_d in product(types_b if types_b else [type_a], types_d if types_d else [type_c]): - ops.append(MMAOp(MMAFrag(geom, "a", type_a), - MMAFrag(geom, "b", type_b), - MMAFrag(geom, "c", type_c), - MMAFrag(geom, "d", type_d))) + ops += [ + MMAOp(MMAFrag(geom, "a", type_a), + MMAFrag(geom, "b", type_b), + MMAFrag(geom, "c", type_c), + MMAFrag(geom, "d", type_d), b1op) + for b1op in b1ops] return ops def make_ldst_ops(geoms, frags, types): @@ -60,9 +65,12 @@ def get_mma_ops(): make_mma_ops(["m8n8k32"], ["s4", "u4"], [], ["s32"], []) + make_mma_ops(["m8n8k128"], - ["b1"], [], ["s32"], [])) + ["b1"], [], ["s32"], [], + [".xor.popc", ".and.popc"])) def get_ldst_ops(): + # NOTE: fragemts are from the point of view of PTX. + # fragment `d` is only for store ops, others for both loads and stores. return (make_ldst_ops(["m16n16k16", "m32n8k16", "m8n32k16"], ["a", "b"], ["f16", "u8", "s8", "bf16"]) + make_ldst_ops(["m16n16k16", "m32n8k16", "m8n32k16"], @@ -71,8 +79,11 @@ def get_ldst_ops(): make_ldst_ops(["m8n8k128"], ["a", "b"], ["b1"]) + make_ldst_ops(["m8n8k32", "m8n8k128"], ["c", "d"], ["s32"]) + make_ldst_ops(["m8n8k4"], ["a", "b", "c", "d"], ["f64"]) + - make_ldst_ops(["m16n16k8"], ["a", "b"], ["tf32"]) + - make_ldst_ops(["m16n16k8"], ["c", "d"], ["f32"])) + # TF32 m16n16k8 is odd. + # For fragment 'C' it uses __mma_*tf32*_m16n16k8_ld_c + # but 'D' calls __mma_m16n16k8_st_c_*f32*. + make_ldst_ops(["m16n16k8"], ["a", "b", "c"], ["tf32"]) + + make_ldst_ops(["m16n16k8"], ["d"], ["f32"])) def is_geom_supported(geom): # geometries for FP and ints. @@ -180,15 +191,19 @@ def get_mma_builtin_name(op): else: suffix = op.a.ptx_type - name = "%s_%s_mma%s_%s" % (prefix, op.a.geom, - "_xor_popc" if op.a.ptx_type == "b1" else "", - suffix) + name = "{prefix}_{geom}_mma{b1op}_{suffix}".format( + prefix = prefix, + geom = op.a.geom, + b1op = op.b1op.replace(".","_"), + suffix = suffix) return name -def get_required_sm(frag): +def get_required_sm(frag, b1op=""): if frag.ptx_type in ["f64", "bf16", "tf32"]: return 80 if frag.ptx_type in ["u4", "s4", "b1"]: + if b1op == "_and_popc": + return 80 return 75 if frag.ptx_type in ["s8", "u8"]: return 72 @@ -204,7 +219,9 @@ def get_required_sm(frag): return 70 assert(False) -def get_required_ptx(frag): +def get_required_ptx(frag, b1op=""): + if frag.ptx_type == "b1" and b1op == ".and.popc": + return 71 if frag.ptx_type in ["f64", "bf16", "tf32"]: return 70 if frag.ptx_type in ["f16", "f32"]: @@ -215,11 +232,13 @@ def get_required_ptx(frag): return 61 return 63 -def get_src_dst_prefix(ptx_type): - if ptx_type == "f32": +def get_src_dst_prefix(frag): + if frag.ptx_type == "f32": return "f" - if ptx_type == "f64": + if frag.ptx_type == "f64": return "d" + if frag.ptx_type == "tf32" and frag.frag in ["c", "d"]: + return "f" return "" def gen_wmma_ldst_tests(results): @@ -235,9 +254,17 @@ def gen_wmma_ldst_tests(results): if not is_ldst_variant_supported(frag, layout): continue - src_dst_prefix = get_src_dst_prefix(frag.ptx_type) + src_dst_prefix = get_src_dst_prefix(frag) + min_sm = get_required_sm(frag) min_ptx = get_required_ptx(frag) + # TF32 uses f32 for accumulator loads. + if frag.geom == "m16n16k8" and frag.frag =="c": + assert frag.ptx_type == "tf32" + itype = "f32" + else: + itype = frag.ptx_type + params = { "check_suffix" : "_PTX%d_SM%d" % (min_ptx, min_sm), "builtin" : get_ldst_builtin_name(frag), @@ -250,7 +277,7 @@ def gen_wmma_ldst_tests(results): "frag" : frag.frag, "geom" : frag.geom, "ilayout" : layout, - "itype" : frag.ptx_type, + "itype" : itype, "op" : "store" if frag.frag == "d" else "load", }) } @@ -283,7 +310,7 @@ def gen_wmma_mma_tests(results): // expected-error-re@+1 {{'${builtin}' needs target feature (sm_${min_sm}{{.*}},(ptx${min_ptx}{{.*}}}} ${builtin}(${dst}, ${asrc}, ${asrc}, ${csrc}, ${ilayout}${maybe_satf}); """.rstrip() - intrinsic_template = "llvm.nvvm.wmma.${geom}.mma.${alayout}.${blayout}.${intrinsic_signature}${satf}" + intrinsic_template = "llvm.nvvm.wmma.${geom}.mma${b1op}.${alayout}.${blayout}.${intrinsic_signature}${satf}" for op, alayout, blayout, satf in sorted(product( get_mma_ops(), ["row","col"], @@ -294,15 +321,15 @@ def gen_wmma_mma_tests(results): if not is_mma_variant_supported(op, alayout, blayout, satf): continue - asrc_prefix = get_src_dst_prefix(op.a.ptx_type) - csrc_prefix = get_src_dst_prefix(op.c.ptx_type) - ddst_prefix = get_src_dst_prefix(op.d.ptx_type) - min_sm = get_required_sm(op.a) - min_ptx = get_required_ptx(op.a) + asrc_prefix = get_src_dst_prefix(op.a) + csrc_prefix = get_src_dst_prefix(op.c) + ddst_prefix = get_src_dst_prefix(op.d) if op.a.ptx_type == "b1": # .b1 MMA has no satf argument. isatf_arg = "" else: isatf_arg = ", 1" if satf else ", 0" + min_sm = get_required_sm(op.a, op.b1op) + min_ptx = get_required_ptx(op.a, op.b1op) params = { "check_suffix" : "_PTX%d_SM%d" % (min_ptx, min_sm), "builtin" : get_mma_builtin_name(op), @@ -319,6 +346,7 @@ def gen_wmma_mma_tests(results): "blayout" : blayout, "intrinsic_signature" : mma_signature(op), "satf" : satf, + "b1op" : op.b1op }) } results[(min_ptx, min_sm)] += Template(mma_template).substitute(params) diff --git a/clang/test/CodeGen/builtins-ppc-altivec.c b/clang/test/CodeGen/builtins-ppc-altivec.c index 8edef9806af22..8aefafb61993c 100644 --- a/clang/test/CodeGen/builtins-ppc-altivec.c +++ b/clang/test/CodeGen/builtins-ppc-altivec.c @@ -8097,8 +8097,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_ge(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_ge(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8125,8 +8125,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_ge(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_ge(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8153,8 +8153,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_ge(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_ge(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8186,8 +8186,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_gt(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_gt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8214,8 +8214,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_gt(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_gt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8242,8 +8242,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_gt(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_gt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8280,8 +8280,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_le(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_le(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8308,8 +8308,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_le(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_le(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8336,8 +8336,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_le(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_le(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8369,8 +8369,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_all_lt(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_all_lt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8397,8 +8397,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_all_lt(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_all_lt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8425,8 +8425,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_all_lt(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_all_lt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8674,8 +8674,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_ge(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_ge(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8702,8 +8702,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_ge(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_ge(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8730,8 +8730,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_ge(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_ge(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8763,8 +8763,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_gt(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_gt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8791,8 +8791,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_gt(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_gt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8819,8 +8819,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_gt(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_gt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8852,8 +8852,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_le(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_le(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8880,8 +8880,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_le(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_le(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8908,8 +8908,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_le(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_le(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p @@ -8941,8 +8941,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p res_i = vec_any_lt(vbc, vsc); -// CHECK: @llvm.ppc.altivec.vcmpgtub.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtub.p +// CHECK: @llvm.ppc.altivec.vcmpgtsb.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsb.p res_i = vec_any_lt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p @@ -8969,8 +8969,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p res_i = vec_any_lt(vbs, vs); -// CHECK: @llvm.ppc.altivec.vcmpgtuh.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuh.p +// CHECK: @llvm.ppc.altivec.vcmpgtsh.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsh.p res_i = vec_any_lt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p @@ -8997,8 +8997,8 @@ void test6() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p res_i = vec_any_lt(vbi, vi); -// CHECK: @llvm.ppc.altivec.vcmpgtuw.p -// CHECK-LE: @llvm.ppc.altivec.vcmpgtuw.p +// CHECK: @llvm.ppc.altivec.vcmpgtsw.p +// CHECK-LE: @llvm.ppc.altivec.vcmpgtsw.p res_i = vec_any_lt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p diff --git a/clang/test/CodeGen/builtins-ppc-vsx.c b/clang/test/CodeGen/builtins-ppc-vsx.c index b5ddd03722ad0..0cbcdae504c91 100644 --- a/clang/test/CodeGen/builtins-ppc-vsx.c +++ b/clang/test/CodeGen/builtins-ppc-vsx.c @@ -407,8 +407,8 @@ void test1() { // CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> [[T1]], <4 x i32> [[T2]], <16 x i8> res_vf = vec_round(vf); -// CHECK: call <4 x float> @llvm.round.v4f32(<4 x float> -// CHECK-LE: call <4 x float> @llvm.round.v4f32(<4 x float> +// CHECK: call <4 x float> @llvm.ppc.altivec.vrfin(<4 x float> +// CHECK-LE: call <4 x float> @llvm.ppc.altivec.vrfin(<4 x float> res_vd = vec_round(vd); // CHECK: call <2 x double> @llvm.round.v2f64(<2 x double> @@ -2724,8 +2724,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_all_ge(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_all_ge(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2753,8 +2753,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_all_gt(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_all_gt(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2782,8 +2782,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_all_le(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_all_le(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2811,8 +2811,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_all_lt(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_all_lt(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2840,8 +2840,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_any_ge(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_any_ge(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2869,8 +2869,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_any_gt(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_any_gt(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2898,8 +2898,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_any_le(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_any_le(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p @@ -2927,8 +2927,8 @@ void test_p8overloads_backwards_compat() { // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p res_i = vec_any_lt(vbll, vsll); - // CHECK: @llvm.ppc.altivec.vcmpgtud.p - // CHECK-LE: @llvm.ppc.altivec.vcmpgtud.p + // CHECK: @llvm.ppc.altivec.vcmpgtsd.p + // CHECK-LE: @llvm.ppc.altivec.vcmpgtsd.p res_i = vec_any_lt(vbll, vull); // CHECK: @llvm.ppc.altivec.vcmpgtud.p diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c index 80bb4de424a13..f305166f2b088 100644 --- a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c @@ -1,27 +1,24 @@ +// REQUIRES: powerpc-registered-target // RUN: not %clang_cc1 -triple=powerpc-unknown-aix -emit-llvm %s -o - 2>&1 |\ // RUN: FileCheck %s --check-prefix=CHECK32-ERROR -// RUN: %clang_cc1 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=CHECK64 -// RUN: %clang_cc1 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s --check-prefix=CHECK64 -// RUN: %clang_cc1 -triple=powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s --check-prefix=CHECK64 long test_ldarx(volatile long* a) { // CHECK64-LABEL: @test_ldarx - // CHECK64: %0 = load i64*, i64** %a.addr, align 8 - // CHECK64: %1 = bitcast i64* %0 to i8* - // CHECK64: %2 = call i64 @llvm.ppc.ldarx(i8* %1) + // CHECK64: %0 = tail call i64 asm sideeffect "ldarx $0, ${1:y}", "=r,*Z,~{memory}"(i64* %a) // CHECK32-ERROR: error: this builtin is only available on 64-bit targets return __ldarx(a); } int test_stdcx(volatile long* addr, long val) { // CHECK64-LABEL: @test_stdcx - // CHECK64: %0 = load i64*, i64** %addr.addr, align 8 - // CHECK64: %1 = bitcast i64* %0 to i8* - // CHECK64: %2 = load i64, i64* %val.addr, align 8 - // CHECK64: %3 = call i32 @llvm.ppc.stdcx(i8* %1, i64 %2) + // CHECK64: %0 = bitcast i64* %addr to i8* + // CHECK64: %1 = tail call i32 @llvm.ppc.stdcx(i8* %0, i64 %val) // CHECK32-ERROR: error: this builtin is only available on 64-bit targets return __stdcx(addr, val); } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c index 5b807973894e0..2ae031cbeca88 100644 --- a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c @@ -1,22 +1,21 @@ -// RUN: %clang_cc1 -triple=powerpc-unknown-aix -emit-llvm %s -o - | \ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -O2 -triple=powerpc-unknown-aix -emit-llvm %s -o - | \ // RUN: FileCheck %s -// RUN: %clang_cc1 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ // RUN: FileCheck %s -// RUN: %clang_cc1 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s -// RUN: %clang_cc1 -triple=powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s int test_lwarx(volatile int* a) { // CHECK: @test_lwarx - // CHECK: %1 = bitcast i32* %0 to i8* - // CHECK: %2 = call i32 @llvm.ppc.lwarx(i8* %1) + // CHECK: %0 = tail call i32 asm sideeffect "lwarx $0, ${1:y}", "=r,*Z,~{memory}"(i32* %a) return __lwarx(a); } int test_stwcx(volatile int* a, int val) { // CHECK: @test_stwcx - // CHECK: %1 = bitcast i32* %0 to i8* - // CHECK: %2 = load i32, i32* %val.addr, align 4 - // CHECK: %3 = call i32 @llvm.ppc.stwcx(i8* %1, i32 %2) + // CHECK: %0 = bitcast i32* %a to i8* + // CHECK: %1 = tail call i32 @llvm.ppc.stwcx(i8* %0, i32 %val) return __stwcx(a, val); } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-conversionfunc.c b/clang/test/CodeGen/builtins-ppc-xlcompat-conversionfunc.c new file mode 100644 index 0000000000000..c2a5d77343e65 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-conversionfunc.c @@ -0,0 +1,122 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -O2 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -O2 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -O2 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -O2 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s + +extern double da; +double test_fcfid() { + // CHECK-LABEL: test_fcfid + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fcfid(double %0) + return __builtin_ppc_fcfid(da); +} + +double test_xl_fcfid() { + // CHECK-LABEL: test_xl_fcfid + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fcfid(double %0) + return __fcfid(da); +} + +double test_fcfud() { + // CHECK-LABEL: test_fcfud + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fcfud(double %0) + return __builtin_ppc_fcfud(da); +} + +double test_xl_fcfud() { + // CHECK-LABEL: test_xl_fcfud + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fcfud(double %0) + return __fcfud(da); +} + +double test_fctid() { + // CHECK-LABEL: test_fctid + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctid(double %0) + return __builtin_ppc_fctid(da); +} + +double test_xl_fctid() { + // CHECK-LABEL: test_xl_fctid + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctid(double %0) + return __fctid(da); +} + +double test_fctidz() { + // CHECK-LABEL: test_fctidz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctidz(double %0) + return __builtin_ppc_fctidz(da); +} + +double test_xl_fctidz() { + // CHECK-LABEL: test_xl_fctidz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctidz(double %0) + return __fctidz(da); +} + +double test_fctiw() { + // CHECK-LABEL: test_fctiw + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctiw(double %0) + return __builtin_ppc_fctiw(da); +} + +double test_xl_fctiw() { + // CHECK-LABEL: test_xl_fctiw + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctiw(double %0) + return __fctiw(da); +} + +double test_fctiwz() { + // CHECK-LABEL: test_fctiwz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctiwz(double %0) + return __builtin_ppc_fctiwz(da); +} + +double test_xl_fctiwz() { + // CHECK-LABEL: test_xl_fctiwz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctiwz(double %0) + return __fctiwz(da); +} + +double test_fctudz() { + // CHECK-LABEL: test_fctudz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctudz(double %0) + return __builtin_ppc_fctudz(da); +} + +double test_xl_fctudz() { + // CHECK-LABEL: test_xl_fctudz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctudz(double %0) + return __fctudz(da); +} + +double test_fctuwz() { + // CHECK-LABEL: test_fctuwz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctuwz(double %0) + return __builtin_ppc_fctuwz(da); +} + +double test_xl_fctuwz() { + // CHECK-LABEL: test_xl_fctuwz + // CHECK-NEXT: entry: + // CHECK: double @llvm.ppc.fctuwz(double %0) + return __fctuwz(da); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-error.c b/clang/test/CodeGen/builtins-ppc-xlcompat-error.c new file mode 100644 index 0000000000000..24430edd8cf7c --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-error.c @@ -0,0 +1,62 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -fsyntax-only \ +// RUN: -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -fsyntax-only \ +// RUN: -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -fsyntax-only \ +// RUN: -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix -fsyntax-only \ +// RUN: -Wall -Werror -verify %s + +extern long long lla, llb; +extern int ia, ib; +extern unsigned int ui; +extern unsigned long long ull; + +void test_trap(void) { +#ifdef __PPC64__ + __tdw(lla, llb, 50); //expected-error {{argument value 50 is outside the valid range [0, 31]}} +#endif + __tw(ia, ib, 50); //expected-error {{argument value 50 is outside the valid range [0, 31]}} +} + +void test_builtin_ppc_rldimi() { + unsigned int shift; + unsigned long long mask; + unsigned long long res = __builtin_ppc_rldimi(ull, ull, shift, 7); // expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}} + res = __builtin_ppc_rldimi(ull, ull, 63, mask); // expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}} + res = __builtin_ppc_rldimi(ull, ull, 63, 0xFFFF000000000F00); // expected-error {{argument 3 value should represent a contiguous bit field}} +} + +void test_builtin_ppc_rlwimi() { + unsigned int shift; + unsigned int mask; + unsigned int res = __builtin_ppc_rlwimi(ui, ui, shift, 7); // expected-error {{argument to '__builtin_ppc_rlwimi' must be a constant integer}} + res = __builtin_ppc_rlwimi(ui, ui, 31, mask); // expected-error {{argument to '__builtin_ppc_rlwimi' must be a constant integer}} + res = __builtin_ppc_rlwimi(ui, ui, 31, 0xFFFF0F00); // expected-error {{argument 3 value should represent a contiguous bit field}} +} + +void test_builtin_ppc_rlwnm() { + unsigned int shift; + unsigned int mask; + unsigned int res = __builtin_ppc_rlwnm(ui, shift, 7); // expected-error {{argument to '__builtin_ppc_rlwnm' must be a constant integer}} + res = __builtin_ppc_rlwnm(ui, 31, mask); // expected-error {{argument to '__builtin_ppc_rlwnm' must be a constant integer}} + res = __builtin_ppc_rlwnm(ui, 31, 0xFF0F0F00); // expected-error {{argument 2 value should represent a contiguous bit field}} +} + +extern unsigned int usi; +extern double d; +extern float f; + +void testMathBuiltin(void) { + __mtfsb0(usi); //expected-error {{argument to '__builtin_ppc_mtfsb0' must be a constant integer}} + __mtfsb0(32); //expected-error {{argument value 32 is outside the valid range [0, 31]}} + __mtfsb1(usi); //expected-error {{argument to '__builtin_ppc_mtfsb1' must be a constant integer}} + __mtfsb1(45); //expected-error {{argument value 45 is outside the valid range [0, 31]}} + __mtfsf(usi, usi); //expected-error {{argument to '__builtin_ppc_mtfsf' must be a constant integer}} + __mtfsf(350, usi); //expected-error {{argument value 350 is outside the valid range [0, 255]}} + __mtfsfi(usi, 0); //expected-error {{argument to '__builtin_ppc_mtfsfi' must be a constant integer}} + __mtfsfi(0, usi); //expected-error {{argument to '__builtin_ppc_mtfsfi' must be a constant integer}} + __mtfsfi(8, 0); //expected-error {{argument value 8 is outside the valid range [0, 7]}} + __mtfsfi(5, 24); //expected-error {{argument value 24 is outside the valid range [0, 15]}} +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-load-store-reversed-64bit-only.c b/clang/test/CodeGen/builtins-ppc-xlcompat-load-store-reversed-64bit-only.c new file mode 100644 index 0000000000000..367abec603577 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-load-store-reversed-64bit-only.c @@ -0,0 +1,35 @@ +// REQUIRES: powerpc-registered-target. +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: not %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 2>&1 | FileCheck %s --check-prefix=CHECK-32-ERROR + +extern unsigned long long ull; +extern unsigned long long *ull_addr; + +// CHECK-LABEL: @test_builtin_ppc_store8r( +// CHECK: [[TMP0:%.*]] = load i64, i64* @ull, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64*, i64** @ull_addr, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[TMP1]] to i8* +// CHECK-NEXT: call void @llvm.ppc.store8r(i64 [[TMP0]], i8* [[TMP2]]) +// CHECK-NEXT: ret void + +// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets +void test_builtin_ppc_store8r() { + __builtin_ppc_store8r(ull, ull_addr); +} + +// CHECK-LABEL: @test_builtin_ppc_load8r( +// CHECK: [[TMP0:%.*]] = load i64*, i64** @ull_addr, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i64* [[TMP0]] to i8* +// CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ppc.load8r(i8* [[TMP1]]) +// CHECK-NEXT: ret i64 [[TMP2]] + +// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets +unsigned long long test_builtin_ppc_load8r() { + return __builtin_ppc_load8r(ull_addr); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-load-store-reversed.c b/clang/test/CodeGen/builtins-ppc-xlcompat-load-store-reversed.c new file mode 100644 index 0000000000000..c8b987838d10a --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-load-store-reversed.c @@ -0,0 +1,86 @@ +// REQUIRES: powerpc-registered-target. +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefixes=CHECK-32B +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s + +extern unsigned short us; +extern unsigned int ui; +extern unsigned short *us_addr; +extern unsigned int *ui_addr; + +// CHECK-LABEL: @test_builtin_ppc_store2r( +// CHECK: [[TMP0:%.*]] = load i16, i16* @us, align 2 +// CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP0]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = load i16*, i16** @us_addr, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast i16* [[TMP1]] to i8* +// CHECK-NEXT: call void @llvm.ppc.store2r(i32 [[CONV]], i8* [[TMP2]]) +// CHECK-NEXT: ret void +// +// CHECK-32B-LABEL: @test_builtin_ppc_store2r( +// CHECK-32B: [[TMP0:%.*]] = load i16, i16* @us, align 2 +// CHECK-32B-NEXT: [[CONV:%.*]] = zext i16 [[TMP0]] to i32 +// CHECK-32B-NEXT: [[TMP1:%.*]] = load i16*, i16** @us_addr, align 4 +// CHECK-32B-NEXT: [[TMP2:%.*]] = bitcast i16* [[TMP1]] to i8* +// CHECK-32B-NEXT: call void @llvm.ppc.store2r(i32 [[CONV]], i8* [[TMP2]]) +// CHECK-32B-NEXT: ret void +// +void test_builtin_ppc_store2r() { + __builtin_ppc_store2r(us, us_addr); +} + +// CHECK-LABEL: @test_builtin_ppc_store4r( +// CHECK: [[TMP0:%.*]] = load i32, i32* @ui, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** @ui_addr, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* +// CHECK-NEXT: call void @llvm.ppc.store4r(i32 [[TMP0]], i8* [[TMP2]]) +// CHECK-NEXT: ret void +// +// CHECK-32B-LABEL: @test_builtin_ppc_store4r( +// CHECK-32B: [[TMP0:%.*]] = load i32, i32* @ui, align 4 +// CHECK-32B-NEXT: [[TMP1:%.*]] = load i32*, i32** @ui_addr, align 4 +// CHECK-32B-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* +// CHECK-32B-NEXT: call void @llvm.ppc.store4r(i32 [[TMP0]], i8* [[TMP2]]) +// CHECK-32B-NEXT: ret void +// +void test_builtin_ppc_store4r() { + __builtin_ppc_store4r(ui, ui_addr); +} + +// CHECK-LABEL: @test_builtin_ppc_load2r( +// CHECK: [[TMP0:%.*]] = load i16*, i16** @us_addr, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i16* [[TMP0]] to i8* +// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ppc.load2r(i8* [[TMP1]]) +// CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[TMP2]] to i16 +// CHECK-NEXT: ret i16 [[CONV]] +// +// CHECK-32B-LABEL: @test_builtin_ppc_load2r( +// CHECK-32B: [[TMP0:%.*]] = load i16*, i16** @us_addr, align 4 +// CHECK-32B-NEXT: [[TMP1:%.*]] = bitcast i16* [[TMP0]] to i8* +// CHECK-32B-NEXT: [[TMP2:%.*]] = call i32 @llvm.ppc.load2r(i8* [[TMP1]]) +// CHECK-32B-NEXT: [[CONV:%.*]] = trunc i32 [[TMP2]] to i16 +// CHECK-32B-NEXT: ret i16 [[CONV]] +// +unsigned short test_builtin_ppc_load2r() { + return __builtin_ppc_load2r(us_addr); +} + +// CHECK-LABEL: @test_builtin_ppc_load4r( +// CHECK: [[TMP0:%.*]] = load i32*, i32** @ui_addr, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* +// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ppc.load4r(i8* [[TMP1]]) +// CHECK-NEXT: ret i32 [[TMP2]] +// +// CHECK-32B-LABEL: @test_builtin_ppc_load4r( +// CHECK-32B: [[TMP0:%.*]] = load i32*, i32** @ui_addr, align 4 +// CHECK-32B-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* +// CHECK-32B-NEXT: [[TMP2:%.*]] = call i32 @llvm.ppc.load4r(i8* [[TMP1]]) +// CHECK-32B-NEXT: ret i32 [[TMP2]] +// +unsigned int test_builtin_ppc_load4r() { + return __builtin_ppc_load4r(ui_addr); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-math.c b/clang/test/CodeGen/builtins-ppc-xlcompat-math.c new file mode 100644 index 0000000000000..4895353686afe --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-math.c @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: -target-cpu pwr7 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: -target-cpu pwr8 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \ +// RUN: -target-cpu pwr7 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s \ +// RUN: -target-cpu pwr7 -o - | FileCheck %s + +// CHECK-LABEL: @mtfsb0( +// CHECK: call void @llvm.ppc.mtfsb0(i32 10) +// CHECK-NEXT: ret void +// +void mtfsb0 () { + __mtfsb0 (10); +} + +// CHECK-LABEL: @mtfsb1( +// CHECK: call void @llvm.ppc.mtfsb1(i32 0) +// CHECK-NEXT: ret void +// +void mtfsb1 () { + __mtfsb1 (0); +} + +// CHECK-LABEL: @mtfsf( +// CHECK: [[TMP0:%.*]] = uitofp i32 %{{.*}} to double +// CHECK-NEXT: call void @llvm.ppc.mtfsf(i32 8, double [[TMP0]]) +// CHECK-NEXT: ret void +// +void mtfsf (unsigned int ui) { + __mtfsf (8, ui); +} + +// CHECK-LABEL: @mtfsfi( +// CHECK: call void @llvm.ppc.mtfsfi(i32 7, i32 15) +// CHECK-NEXT: ret void +// +void mtfsfi () { + __mtfsfi (7, 15); +} + +// CHECK-LABEL: @fmsub( +// CHECK: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fmsub(double [[TMP0]], double [[TMP1]], double [[TMP2]]) +// CHECK-NEXT: ret double [[TMP3]] +// +double fmsub (double d) { + return __fmsub (d, d, d); +} + +// CHECK-LABEL: @fmsubs( +// CHECK: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fmsubs(float [[TMP0]], float [[TMP1]], float [[TMP2]]) +// CHECK-NEXT: ret float [[TMP3]] +// +float fmsubs (float f) { + return __fmsubs (f, f, f); +} + +// CHECK-LABEL: @fnmadd( +// CHECK: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fnmadd(double [[TMP0]], double [[TMP1]], double [[TMP2]]) +// CHECK-NEXT: ret double [[TMP3]] +// +double fnmadd (double d) { + return __fnmadd (d, d, d); +} + +// CHECK-LABEL: @fnmadds( +// CHECK: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fnmadds(float [[TMP0]], float [[TMP1]], float [[TMP2]]) +// CHECK-NEXT: ret float [[TMP3]] +// +float fnmadds (float f) { + return __fnmadds (f, f, f); +} + +// CHECK-LABEL: @fnmsub( +// CHECK: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fnmsub(double [[TMP0]], double [[TMP1]], double [[TMP2]]) +// CHECK-NEXT: ret double [[TMP3]] +// +double fnmsub (double d) { + return __fnmsub (d, d, d); +} + +// CHECK-LABEL: @fnmsubs( +// CHECK: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fnmsubs(float [[TMP0]], float [[TMP1]], float [[TMP2]]) +// CHECK-NEXT: ret float [[TMP3]] +// +float fnmsubs (float f) { + return __fnmsubs (f, f, f); +} + +// CHECK-LABEL: @fre( +// CHECK: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ppc.fre(double [[TMP0]]) +// CHECK-NEXT: ret double [[TMP1]] +// +double fre (double d) { + return __fre (d); +} + +// CHECK-LABEL: @fres( +// CHECK: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ppc.fres(float [[TMP0]]) +// CHECK-NEXT: ret float [[TMP1]] +// +float fres (float f) { + return __fres (f); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-multiply-64bit-only.c b/clang/test/CodeGen/builtins-ppc-xlcompat-multiply-64bit-only.c new file mode 100644 index 0000000000000..073a5d1e2d257 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-multiply-64bit-only.c @@ -0,0 +1,26 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: not %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 2>&1 | FileCheck %s --check-prefix=CHECK-32-ERROR + +extern long int sli; +extern unsigned long int uli; + +long long test_builtin_ppc_mulhd() { + // CHECK-LABEL: @test_builtin_ppc_mulhd( + // CHECK: %2 = call i64 @llvm.ppc.mulhd(i64 %0, i64 %1) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + return __builtin_ppc_mulhd(sli, sli); +} + +unsigned long long test_builtin_ppc_mulhdu() { + // CHECK-LABEL: @test_builtin_ppc_mulhdu( + // CHECK: %2 = call i64 @llvm.ppc.mulhdu(i64 %0, i64 %1) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + return __builtin_ppc_mulhdu(uli, uli); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-multiply.c b/clang/test/CodeGen/builtins-ppc-xlcompat-multiply.c new file mode 100644 index 0000000000000..739248db78133 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-multiply.c @@ -0,0 +1,24 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s + +extern int si; +extern unsigned int ui; + +int test_builtin_ppc_mulhw() { + // CHECK-LABEL: @test_builtin_ppc_mulhw( + // CHECK: %2 = call i32 @llvm.ppc.mulhw(i32 %0, i32 %1) + return __builtin_ppc_mulhw(si, si); +} + +unsigned int test_builtin_ppc_mulhwu() { + // CHECK-LABEL: @test_builtin_ppc_mulhwu( + // CHECK: %2 = call i32 @llvm.ppc.mulhwu(i32 %0, i32 %1) + return __builtin_ppc_mulhwu(ui, ui); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-popcnt.c b/clang/test/CodeGen/builtins-ppc-xlcompat-popcnt.c new file mode 100644 index 0000000000000..92a4e4af002e2 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-popcnt.c @@ -0,0 +1,35 @@ +// REQUIRES: powerpc-registered-target. +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s + +extern unsigned int ui; +extern unsigned long long ull; + +// CHECK-LABEL: @test_builtin_ppc_poppar4( +// CHECK: [[TMP0:%.*]] = load i32, i32* @ui, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1 +// CHECK-NEXT: ret i32 [[TMP3]] +// +int test_builtin_ppc_poppar4() { + return __builtin_ppc_poppar4(ui); +} + +// CHECK-LABEL: @test_builtin_ppc_poppar8( +// CHECK: [[TMP0:%.*]] = load i64, i64* @ull, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* @ull, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]]) +// CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 1 +// CHECK-NEXT: [[CAST:%.*]] = trunc i64 [[TMP3]] to i32 +// CHECK-NEXT: ret i32 [[CAST]] +// +int test_builtin_ppc_poppar8() { + return __builtin_ppc_poppar8(ull); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-64bit.c b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-64bit.c new file mode 100644 index 0000000000000..741e87194a7d4 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-64bit.c @@ -0,0 +1,82 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: not %clang_cc1 -triple powerpc-unknown-aix -emit-llvm-only %s \ +// RUN: -target-cpu pwr9 2>&1 | FileCheck %s --check-prefix=CHECK-32-ERROR +// RUN: not %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm-only %s \ +// RUN: -target-cpu pwr8 2>&1 | FileCheck %s --check-prefix=CHECK-NONPWR9-ERR + +extern signed long long sll; +extern unsigned long long ull; + +signed long long test_builtin_ppc_cmpeqb() { + // CHECK-LABEL: @test_builtin_ppc_cmpeqb( + // CHECK: %2 = call i64 @llvm.ppc.cmpeqb(i64 %0, i64 %1) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_cmpeqb(sll, sll); +} + +long long test_builtin_ppc_setb() { + // CHECK-LABEL: @test_builtin_ppc_setb( + // CHECK: %2 = call i64 @llvm.ppc.setb(i64 %0, i64 %1) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_setb(sll, sll); +} + +signed long long test_builtin_ppc_maddhd() { + // CHECK-LABEL: @test_builtin_ppc_maddhd( + // CHECK: %3 = call i64 @llvm.ppc.maddhd(i64 %0, i64 %1, i64 %2) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_maddhd(sll, sll, sll); +} + +unsigned long long test_builtin_ppc_maddhdu() { + // CHECK-LABEL: @test_builtin_ppc_maddhdu( + // CHECK: %3 = call i64 @llvm.ppc.maddhdu(i64 %0, i64 %1, i64 %2) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_maddhdu(ull, ull, ull); +} + +signed long long test_builtin_ppc_maddld() { + // CHECK-LABEL: @test_builtin_ppc_maddld( + // CHECK: %3 = call i64 @llvm.ppc.maddld(i64 %0, i64 %1, i64 %2) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_maddld(sll, sll, sll); +} + +unsigned long long test_builtin_ppc_maddld_unsigned() { + // CHECK-LABEL: @test_builtin_ppc_maddld_unsigned( + // CHECK: %3 = call i64 @llvm.ppc.maddld(i64 %0, i64 %1, i64 %2) + // CHECK-32-ERROR: error: this builtin is only available on 64-bit targets + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_maddld(ull, ull, ull); +} + +unsigned long long extract_sig (double d) { +// CHECK-LABEL: @extract_sig( +// CHECK: [[TMP1:%.*]] = call i64 @llvm.ppc.extract.sig(double %0) +// CHECK-NEXT: ret i64 [[TMP1]] +// +// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets +// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __extract_sig (d); +} + +double insert_exp (double d, unsigned long long ull) { +// CHECK-LABEL: @insert_exp( +// CHECK: [[TMP2:%.*]] = call double @llvm.ppc.insert.exp(double %0, i64 %1) +// CHECK-NEXT: ret double [[TMP2]] +// +// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets +// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __insert_exp (d, ull); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-error.c b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-error.c new file mode 100644 index 0000000000000..2d7449f4f1318 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9-error.c @@ -0,0 +1,15 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -target-cpu pwr9 \ +// RUN: -fsyntax-only -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr9 \ +// RUN: -fsyntax-only -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -target-cpu pwr9 \ +// RUN: -fsyntax-only -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix -target-cpu pwr9 \ +// RUN: -fsyntax-only -Wall -Werror -verify %s + +extern unsigned int ui; + +void test_builtin_ppc_cmprb() { + int res = __builtin_ppc_cmprb(3, ui, ui); // expected-error {{argument value 3 is outside the valid range [0, 1]}} +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9.c b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9.c new file mode 100644 index 0000000000000..c7531da88b40f --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr9.c @@ -0,0 +1,29 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix %s -emit-llvm %s \ +// RUN: -target-cpu pwr9 -o - | FileCheck %s +// RUN: not %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm-only %s \ +// RUN: -target-cpu pwr8 2>&1 | FileCheck %s --check-prefix=CHECK-NONPWR9-ERR + +extern unsigned int ui; + +int test_builtin_ppc_cmprb() { + // CHECK-LABEL: @test_builtin_ppc_cmprb( + // CHECK: %2 = call i32 @llvm.ppc.cmprb(i32 0, i32 %0, i32 %1) + // CHECK: %5 = call i32 @llvm.ppc.cmprb(i32 1, i32 %3, i32 %4) + // CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __builtin_ppc_cmprb(0, ui, ui) + __builtin_ppc_cmprb(1, ui, ui); +} + +unsigned int extract_exp (double d) { +// CHECK-LABEL: @extract_exp +// CHECK: [[TMP1:%.*]] = call i32 @llvm.ppc.extract.exp(double %0) +// CHECK-NEXT: ret i32 [[TMP1]] +// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs + return __extract_exp (d); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c b/clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c new file mode 100644 index 0000000000000..c56e42b57356f --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c @@ -0,0 +1,57 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s + +extern unsigned int ui; +extern unsigned long long ull; + +void test_builtin_ppc_rldimi() { + // CHECK-LABEL: test_builtin_ppc_rldimi + // CHECK: %res = alloca i64, align 8 + // CHECK-NEXT: [[RA:%[0-9]+]] = load i64, i64* @ull, align 8 + // CHECK-NEXT: [[RB:%[0-9]+]] = load i64, i64* @ull, align 8 + // CHECK-NEXT: [[RC:%[0-9]+]] = call i64 @llvm.fshl.i64(i64 [[RA]], i64 [[RA]], i64 63) + // CHECK-NEXT: [[RD:%[0-9]+]] = and i64 [[RC]], 72057593769492480 + // CHECK-NEXT: [[RE:%[0-9]+]] = and i64 [[RB]], -72057593769492481 + // CHECK-NEXT: [[RF:%[0-9]+]] = or i64 [[RD]], [[RE]] + // CHECK-NEXT: store i64 [[RF]], i64* %res, align 8 + // CHECK-NEXT: ret void + + /*shift = 63, mask = 0x00FFFFFFF0000000 = 72057593769492480, ~mask = 0xFF0000000FFFFFFF = -72057593769492481*/ + unsigned long long res = __builtin_ppc_rldimi(ull, ull, 63, 0x00FFFFFFF0000000); +} + +void test_builtin_ppc_rlwimi() { + // CHECK-LABEL: test_builtin_ppc_rlwimi + // CHECK: %res = alloca i32, align 4 + // CHECK-NEXT: [[RA:%[0-9]+]] = load i32, i32* @ui, align 4 + // CHECK-NEXT: [[RB:%[0-9]+]] = load i32, i32* @ui, align 4 + // CHECK-NEXT: [[RC:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 31) + // CHECK-NEXT: [[RD:%[0-9]+]] = and i32 [[RC]], 16776960 + // CHECK-NEXT: [[RE:%[0-9]+]] = and i32 [[RB]], -16776961 + // CHECK-NEXT: [[RF:%[0-9]+]] = or i32 [[RD]], [[RE]] + // CHECK-NEXT: store i32 [[RF]], i32* %res, align 4 + // CHECK-NEXT: ret void + + /*shift = 31, mask = 0xFFFF00 = 16776960, ~mask = 0xFFFFFFFFFF0000FF = -16776961*/ + unsigned int res = __builtin_ppc_rlwimi(ui, ui, 31, 0xFFFF00); +} + +void test_builtin_ppc_rlwnm() { + // CHECK-LABEL: test_builtin_ppc_rlwnm + // CHECK: %res = alloca i32, align 4 + // CHECK-NEXT: [[RA:%[0-9]+]] = load i32, i32* @ui, align 4 + // CHECK-NEXT: [[RB:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 31) + // CHECK-NEXT: [[RC:%[0-9]+]] = and i32 [[RB]], 511 + // CHECK-NEXT: store i32 [[RC]], i32* %res, align 4 + // CHECK-NEXT: ret void + + /*shift = 31, mask = 0x1FF = 511*/ + unsigned int res = __builtin_ppc_rlwnm(ui, 31, 0x1FF); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-sync.c b/clang/test/CodeGen/builtins-ppc-xlcompat-sync.c index 6413f34fbc410..1aeec57151b7c 100644 --- a/clang/test/CodeGen/builtins-ppc-xlcompat-sync.c +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-sync.c @@ -1,260 +1,472 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ -// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s // RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ -// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s --check-prefix=CHECK-32 + +extern unsigned long a; +extern const void *b; +extern void *c; -void test_popcntb() { // CHECK-LABEL: @test_popcntb( // CHECK-NEXT: entry: - - unsigned long a; - unsigned long b = __popcntb(a); -// CHECK: %1 = call i64 @llvm.ppc.popcntb(i64 %0) +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* @a, align 8 +// CHECK-NEXT: [[POPCNTB:%.*]] = call i64 @llvm.ppc.popcntb.i64.i64(i64 [[TMP0]]) +// CHECK-NEXT: ret i64 [[POPCNTB]] +// +// CHECK-32-LABEL: @test_popcntb( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-32-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4 +// CHECK-32-NEXT: [[POPCNTB:%.*]] = call i32 @llvm.ppc.popcntb.i32.i32(i32 [[TMP0]]) +// CHECK-32-NEXT: ret i32 [[POPCNTB]] +// +unsigned long test_popcntb() { + return __popcntb(a); } -void test_eieio() { // CHECK-LABEL: @test_eieio( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.eieio() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_eieio( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.eieio() +// CHECK-32-NEXT: ret void +// +void test_eieio() { __eieio(); -// CHECK: call void @llvm.ppc.eieio() } -void test_iospace_eieio() { // CHECK-LABEL: @test_iospace_eieio( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.iospace.eieio() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_iospace_eieio( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.iospace.eieio() +// CHECK-32-NEXT: ret void +// +void test_iospace_eieio() { __iospace_eieio(); -// CHECK: call void @llvm.ppc.iospace.eieio() } -void test_isync() { // CHECK-LABEL: @test_isync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.isync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_isync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.isync() +// CHECK-32-NEXT: ret void +// +void test_isync() { __isync(); -// CHECK: call void @llvm.ppc.isync() } -void test_lwsync() { // CHECK-LABEL: @test_lwsync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.lwsync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_lwsync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.lwsync() +// CHECK-32-NEXT: ret void +// +void test_lwsync() { __lwsync(); -// CHECK: call void @llvm.ppc.lwsync() } -void test_iospace_lwsync() { // CHECK-LABEL: @test_iospace_lwsync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.iospace.lwsync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_iospace_lwsync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.iospace.lwsync() +// CHECK-32-NEXT: ret void +// +void test_iospace_lwsync() { __iospace_lwsync(); -// CHECK: call void @llvm.ppc.iospace.lwsync() } -void test_sync() { // CHECK-LABEL: @test_sync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.sync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_sync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.sync() +// CHECK-32-NEXT: ret void +// +void test_sync() { __sync(); -// CHECK: call void @llvm.ppc.sync() } -void test_iospace_sync() { // CHECK-LABEL: @test_iospace_sync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.iospace.sync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_iospace_sync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.iospace.sync() +// CHECK-32-NEXT: ret void +// +void test_iospace_sync() { __iospace_sync(); -// CHECK: call void @llvm.ppc.iospace.sync() } -void test_dcbfl() { // CHECK-LABEL: @test_dcbfl( -// CHECK-NEXT: entry: - - const void* a; - __dcbfl(a); -// CHECK: call void @llvm.ppc.dcbfl(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbfl(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_dcbfl( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbfl(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_dcbfl() { + __dcbfl(b); } -void test_dcbflp() { // CHECK-LABEL: @test_dcbflp( -// CHECK-NEXT: entry: - - const void* a; - __dcbflp(a); -// CHECK: call void @llvm.ppc.dcbflp(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbflp(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_dcbflp( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbflp(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_dcbflp() { + __dcbflp(b); } -void test_dcbst() { // CHECK-LABEL: @test_dcbst( -// CHECK-NEXT: entry: - - const void* a; - __dcbst(a); -// CHECK: call void @llvm.ppc.dcbst(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbst(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_dcbst( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbst(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_dcbst() { + __dcbst(b); } -void test_dcbt() { // CHECK-LABEL: @test_dcbt( -// CHECK-NEXT: entry: - - void* a; - __dcbt(a); -// CHECK: call void @llvm.ppc.dcbt(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbt(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_dcbt( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbt(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_dcbt() { + __dcbt(c); } -void test_dcbtst() { // CHECK-LABEL: @test_dcbtst( -// CHECK-NEXT: entry: - - void* a; - __dcbtst(a); -// CHECK: call void @llvm.ppc.dcbtst(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbtst(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_dcbtst( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbtst(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_dcbtst() { + __dcbtst(c); } -void test_dcbz() { // CHECK-LABEL: @test_dcbz( -// CHECK-NEXT: entry: - - void* a; - __dcbz(a); -// CHECK: call void @llvm.ppc.dcbz(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbz(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_dcbz( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbz(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_dcbz() { + __dcbz(c); } -void test_icbt() { +// FIXME: __icbt is only valid for pwr8 and up. // CHECK-LABEL: @test_icbt( -// CHECK-NEXT: entry: - - void* a; - __icbt(a); -// CHECK: call void @llvm.ppc.icbt(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.icbt(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_icbt( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.icbt(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_icbt() { + __icbt(c); } -void test_builtin_ppc_popcntb() { // CHECK-LABEL: @test_builtin_ppc_popcntb( // CHECK-NEXT: entry: - - unsigned long a; - unsigned long b = __builtin_ppc_popcntb(a); -// CHECK: %1 = call i64 @llvm.ppc.popcntb(i64 %0) +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* @a, align 8 +// CHECK-NEXT: [[POPCNTB:%.*]] = call i64 @llvm.ppc.popcntb.i64.i64(i64 [[TMP0]]) +// CHECK-NEXT: ret i64 [[POPCNTB]] +// +// CHECK-32-LABEL: @test_builtin_ppc_popcntb( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-32-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4 +// CHECK-32-NEXT: [[POPCNTB:%.*]] = call i32 @llvm.ppc.popcntb.i32.i32(i32 [[TMP0]]) +// CHECK-32-NEXT: ret i32 [[POPCNTB]] +// +unsigned long test_builtin_ppc_popcntb() { + return __builtin_ppc_popcntb(a); } -void test_builtin_ppc_eieio() { // CHECK-LABEL: @test_builtin_ppc_eieio( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.eieio() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_eieio( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.eieio() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_eieio() { __builtin_ppc_eieio(); -// CHECK: call void @llvm.ppc.eieio() } -void test_builtin_ppc_iospace_eieio() { // CHECK-LABEL: @test_builtin_ppc_iospace_eieio( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.iospace.eieio() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_iospace_eieio( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.iospace.eieio() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_iospace_eieio() { __builtin_ppc_iospace_eieio(); -// CHECK: call void @llvm.ppc.iospace.eieio() } -void test_builtin_ppc_isync() { // CHECK-LABEL: @test_builtin_ppc_isync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.isync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_isync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.isync() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_isync() { __builtin_ppc_isync(); -// CHECK: call void @llvm.ppc.isync() } -void test_builtin_ppc_lwsync() { // CHECK-LABEL: @test_builtin_ppc_lwsync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.lwsync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_lwsync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.lwsync() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_lwsync() { __builtin_ppc_lwsync(); -// CHECK: call void @llvm.ppc.lwsync() } -void test_builtin_ppc_iospace_lwsync() { // CHECK-LABEL: @test_builtin_ppc_iospace_lwsync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.iospace.lwsync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_iospace_lwsync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.iospace.lwsync() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_iospace_lwsync() { __builtin_ppc_iospace_lwsync(); -// CHECK: call void @llvm.ppc.iospace.lwsync() } -void test_builtin_ppc_sync() { // CHECK-LABEL: @test_builtin_ppc_sync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.sync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_sync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.sync() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_sync() { __builtin_ppc_sync(); -// CHECK: call void @llvm.ppc.sync() } -void test_builtin_ppc_iospace_sync() { // CHECK-LABEL: @test_builtin_ppc_iospace_sync( -// CHECK-NEXT: entry: - +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.ppc.iospace.sync() +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_iospace_sync( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: call void @llvm.ppc.iospace.sync() +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_iospace_sync() { __builtin_ppc_iospace_sync(); -// CHECK: call void @llvm.ppc.iospace.sync() } -void test_builtin_ppc_dcbfl() { // CHECK-LABEL: @test_builtin_ppc_dcbfl( -// CHECK-NEXT: entry: - - const void* a; - __builtin_ppc_dcbfl(a); -// CHECK: call void @llvm.ppc.dcbfl(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbfl(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_dcbfl( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbfl(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_dcbfl() { + __builtin_ppc_dcbfl(b); } -void test_builtin_ppc_dcbflp() { // CHECK-LABEL: @test_builtin_ppc_dcbflp( -// CHECK-NEXT: entry: - - const void* a; - __builtin_ppc_dcbflp(a); -// CHECK: call void @llvm.ppc.dcbflp(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbflp(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_dcbflp( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbflp(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_dcbflp() { + __builtin_ppc_dcbflp(b); } -void test_builtin_ppc_dcbst() { // CHECK-LABEL: @test_builtin_ppc_dcbst( -// CHECK-NEXT: entry: - - const void* a; - __builtin_ppc_dcbst(a); -// CHECK: call void @llvm.ppc.dcbst(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbst(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_dcbst( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @b, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbst(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_dcbst() { + __builtin_ppc_dcbst(b); } -void test_builtin_ppc_dcbt() { // CHECK-LABEL: @test_builtin_ppc_dcbt( -// CHECK-NEXT: entry: - - void* a; - __builtin_ppc_dcbt(a); -// CHECK: call void @llvm.ppc.dcbt(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbt(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_dcbt( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbt(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_dcbt() { + __builtin_ppc_dcbt(c); } -void test_builtin_ppc_dcbtst() { // CHECK-LABEL: @test_builtin_ppc_dcbtst( -// CHECK-NEXT: entry: - - void* a; - __builtin_ppc_dcbtst(a); -// CHECK: call void @llvm.ppc.dcbtst(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbtst(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_dcbtst( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbtst(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_dcbtst() { + __builtin_ppc_dcbtst(c); } -void test_builtin_ppc_dcbz() { // CHECK-LABEL: @test_builtin_ppc_dcbz( -// CHECK-NEXT: entry: - - void* a; - __builtin_ppc_dcbz(a); -// CHECK: call void @llvm.ppc.dcbz(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.dcbz(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_dcbz( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.dcbz(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_dcbz() { + __builtin_ppc_dcbz(c); } -void test_builtin_ppc_icbt() { +// FIXME: __icbt is only valid for pwr8 and up. // CHECK-LABEL: @test_builtin_ppc_icbt( -// CHECK-NEXT: entry: - - void* a; - __builtin_ppc_icbt(a); -// CHECK: call void @llvm.ppc.icbt(i8* %0) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 8 +// CHECK-NEXT: call void @llvm.ppc.icbt(i8* [[TMP0]]) +// CHECK-NEXT: ret void +// +// CHECK-32-LABEL: @test_builtin_ppc_icbt( +// CHECK-32-NEXT: entry: +// CHECK-32-NEXT: [[TMP0:%.*]] = load i8*, i8** @c, align 4 +// CHECK-32-NEXT: call void @llvm.ppc.icbt(i8* [[TMP0]]) +// CHECK-32-NEXT: ret void +// +void test_builtin_ppc_icbt() { + __builtin_ppc_icbt(c); } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-trap-64bit-only.c b/clang/test/CodeGen/builtins-ppc-xlcompat-trap-64bit-only.c new file mode 100644 index 0000000000000..e49539c5a430d --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-trap-64bit-only.c @@ -0,0 +1,42 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -O2 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | \ +// RUN: FileCheck %s --check-prefixes=CHECK64 +// RUN: %clang_cc1 -O2 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | \ +// RUN: FileCheck %s --check-prefixes=CHECK64 +// RUN: not %clang_cc1 -O2 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 2>&1 | \ +// RUN: FileCheck %s -check-prefixes=CHECK32-ERROR +// RUN: %clang_cc1 -O2 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | \ +// RUN: FileCheck %s --check-prefixes=CHECK64 + +extern long long lla, llb; +extern double da; + +// tdw +void test_xl_tdw(void) { +// CHECK64: void @llvm.ppc.tdw(i64 %0, i64 %1, i32 1) +// CHECK32-ERROR: error: this builtin is only available on 64-bit targets + __tdw(lla, llb, 1); +} + +void test_tdw(void) { +// CHECK64: void @llvm.ppc.tdw(i64 %0, i64 %1, i32 13) +// CHECK32-ERROR: error: this builtin is only available on 64-bit targets + __builtin_ppc_tdw(lla, llb, 13); +} + +// trapd +void test_trapd(void) { +// CHECK64: void @llvm.ppc.trapd(i64 %conv) +// CHECK32-ERROR: error: this builtin is only available on 64-bit targets + __builtin_ppc_trapd(da); +} + +void test_xl_trapd(void) { +// CHECK64: void @llvm.ppc.trapd(i64 %conv) +// CHECK32-ERROR: error: this builtin is only available on 64-bit targets + __trapd(da); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-trap.c b/clang/test/CodeGen/builtins-ppc-xlcompat-trap.c new file mode 100644 index 0000000000000..e2eb8cbbadaaf --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-trap.c @@ -0,0 +1,39 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -O2 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -O2 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -O2 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -O2 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | \ +// RUN: FileCheck %s + +extern int ia, ib; + +// td +void test_tw(void) { +// CHECK: void @llvm.ppc.tw(i32 %0, i32 %1, i32 1) + + __builtin_ppc_tw(ia, ib, 1); +} + +void test_xl_tw(void) { +// CHECK: void @llvm.ppc.tw(i32 %0, i32 %1, i32 1) + + __tw(ia, ib, 1); +} + +// trap +void test_trap(void) { +// CHECK: void @llvm.ppc.trap(i32 %0) + __builtin_ppc_trap(ia); +} + +void test_xl_trap(void) { +// CHECK: void @llvm.ppc.trap(i32 %0) + __trap(ia); +} diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c index 61130922241cd..b7341b943ada5 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -284,62 +284,6 @@ f64x2 replace_lane_f64x2(f64x2 v, double x) { // WEBASSEMBLY-NEXT: ret } -i8x16 load8_lane(const signed char *p, i8x16 v) { - return __builtin_wasm_load8_lane(p, v, 0); - // WEBASSEMBLY: tail call <16 x i8> @llvm.wasm.load8.lane( - // WEBASSEMBLY-SAME: i8* %p, <16 x i8> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -i16x8 load16_lane(const short *p, i16x8 v) { - return __builtin_wasm_load16_lane(p, v, 0); - // WEBASSEMBLY: tail call <8 x i16> @llvm.wasm.load16.lane( - // WEBASSEMBLY-SAME: i16* %p, <8 x i16> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -i32x4 load32_lane(const int *p, i32x4 v) { - return __builtin_wasm_load32_lane(p, v, 0); - // WEBASSEMBLY: tail call <4 x i32> @llvm.wasm.load32.lane( - // WEBASSEMBLY-SAME: i32* %p, <4 x i32> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -i64x2 load64_lane(const long long *p, i64x2 v) { - return __builtin_wasm_load64_lane(p, v, 0); - // WEBASSEMBLY: tail call <2 x i64> @llvm.wasm.load64.lane( - // WEBASSEMBLY-SAME: i64* %p, <2 x i64> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -void store8_lane(signed char *p, i8x16 v) { - __builtin_wasm_store8_lane(p, v, 0); - // WEBASSEMBLY: call void @llvm.wasm.store8.lane( - // WEBASSEMBLY-SAME: i8* %p, <16 x i8> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -void store16_lane(short *p, i16x8 v) { - __builtin_wasm_store16_lane(p, v, 0); - // WEBASSEMBLY: call void @llvm.wasm.store16.lane( - // WEBASSEMBLY-SAME: i16* %p, <8 x i16> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -void store32_lane(int *p, i32x4 v) { - __builtin_wasm_store32_lane(p, v, 0); - // WEBASSEMBLY: call void @llvm.wasm.store32.lane( - // WEBASSEMBLY-SAME: i32* %p, <4 x i32> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - -void store64_lane(long long *p, i64x2 v) { - __builtin_wasm_store64_lane(p, v, 0); - // WEBASSEMBLY: call void @llvm.wasm.store64.lane( - // WEBASSEMBLY-SAME: i64* %p, <2 x i64> %v, i32 0) - // WEBASSEMBLY-NEXT: ret -} - i8x16 add_sat_s_i8x16(i8x16 x, i8x16 y) { return __builtin_wasm_add_sat_s_i8x16(x, y); // WEBASSEMBLY: call <16 x i8> @llvm.sadd.sat.v16i8( @@ -892,12 +836,6 @@ u32x4 trunc_sat_zero_u_f64x2_i32x4(f64x2 x) { // WEBASSEMBLY: ret <4 x i32> %1 } -f32x4 wasm_demote_zero_f64x2_f32x4(f64x2 x) { - return __builtin_wasm_demote_zero_f64x2_f32x4(x); - // WEBASSEMBLY: call <4 x float> @llvm.wasm.demote.zero(<2 x double> %x) - // WEBASSEMBLY: ret -} - i32x4 load32_zero(const int *p) { return __builtin_wasm_load32_zero(p); // WEBASSEMBLY: call <4 x i32> @llvm.wasm.load32.zero(i32* %p) diff --git a/clang/test/CodeGen/lto-newpm-pipeline.c b/clang/test/CodeGen/lto-newpm-pipeline.c index c8220e3547e14..c2cd3a4720cca 100644 --- a/clang/test/CodeGen/lto-newpm-pipeline.c +++ b/clang/test/CodeGen/lto-newpm-pipeline.c @@ -28,6 +28,8 @@ // CHECK-FULL-O0: Running pass: AlwaysInlinerPass // CHECK-FULL-O0-NEXT: Running analysis: InnerAnalysisManagerProxy // CHECK-FULL-O0-NEXT: Running analysis: ProfileSummaryAnalysis +// CHECK-FULL-O0: Running pass: CoroSplitPass +// CHECK-FULL-O0-NEXT: Running pass: CoroCleanupPass // CHECK-FULL-O0-NEXT: Running pass: CanonicalizeAliasesPass // CHECK-FULL-O0-NEXT: Running pass: NameAnonGlobalPass // CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass @@ -35,6 +37,7 @@ // CHECK-THIN-O0: Running pass: AlwaysInlinerPass // CHECK-THIN-O0-NEXT: Running analysis: InnerAnalysisManagerProxy // CHECK-THIN-O0-NEXT: Running analysis: ProfileSummaryAnalysis +// CHECK-THIN-O0: Running pass: CoroCleanupPass // CHECK-THIN-O0-NEXT: Running pass: CanonicalizeAliasesPass // CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass // CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass diff --git a/clang/test/CodeGen/vector-bool-pixel-altivec-init-no-parentheses.c b/clang/test/CodeGen/vector-bool-pixel-altivec-init-no-parentheses.c new file mode 100644 index 0000000000000..7a5c20e3d0bc2 --- /dev/null +++ b/clang/test/CodeGen/vector-bool-pixel-altivec-init-no-parentheses.c @@ -0,0 +1,88 @@ +// RUN: not %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED-ERR +// RUN: not %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED-ERR +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: not %clang -mcpu=pwr8 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED-ERR +// RUN: not %clang -mcpu=pwr9 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=MIXED-ERR +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL + +// Vector bool type +vector bool char vbi8_1; +vector bool char vbi8_2; + +vector bool short vbi16_1; +vector bool short vbi16_2; + +vector bool int vbi32_1; +vector bool int vbi32_2; + +vector bool long long vbi64_1; +vector bool long long vbi64_2; + +// Vector pixel type +vector pixel p1; + +//////////////////////////////////////////////////////////////////////////////// +void test_vector_bool_pixel_init_no_parentheses() { + // vector bool char initialization + vbi8_1 = (vector bool char)'a'; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned char' + // XL: + char c = 'c'; + vbi8_2 = (vector bool char)c; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned char' + // XL: [[INS_ELT:%.*]] = insertelement <16 x i8> + // XL: [[SHUFF:%.*]] = shufflevector <16 x i8> [[INS_ELT]], <16 x i8> poison, <16 x i32> zeroinitializer + // XL: store <16 x i8> [[SHUFF]] + + // vector bool short initialization + vbi16_1 = (vector bool short)5; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned short' + // XL: + short si16 = 55; + vbi16_2 = (vector bool short)si16; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned short' + // XL: [[INS_ELT:%.*]] = insertelement <8 x i16> + // XL: [[SHUFF:%.*]] = shufflevector <8 x i16> [[INS_ELT]], <8 x i16> poison, <8 x i32> zeroinitializer + // XL: store <8 x i16> [[SHUFF]] + + // vector bool int initialization + vbi32_1 = (vector bool int)9; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned int' + // XL: + int si32 = 99; + vbi32_2 = (vector bool int)si32; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned int' + // XL: [[INS_ELT:%.*]] = insertelement <4 x i32> + // XL: [[SHUFF:%.*]] = shufflevector <4 x i32> [[INS_ELT]], <4 x i32> poison, <4 x i32> zeroinitializer + // XL: store <4 x i32> [[SHUFF]] + + // vector bool long long initialization + vbi64_1 = (vector bool long long)13; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned long long' + // XL: + long long si64 = 1313; + vbi64_2 = (vector bool long long)si64; + // MIXED-ERR: error: invalid conversion between vector type '__vector __bool unsigned long long' + // XL: [[INS_ELT:%.*]] = insertelement <2 x i64> + // XL: [[SHUFF:%.*]] = shufflevector <2 x i64> [[INS_ELT]], <2 x i64> poison, <2 x i32> zeroinitializer + // XL: store <2 x i64> [[SHUFF]] + + // vector pixel initialization + p1 = (vector pixel)1; + // MIXED-ERR: error: invalid conversion between vector type '__vector __pixel ' + // XL: +} diff --git a/clang/test/CodeGen/vector-bool-pixel-altivec-init.c b/clang/test/CodeGen/vector-bool-pixel-altivec-init.c new file mode 100644 index 0000000000000..dcaf2d3e5faf3 --- /dev/null +++ b/clang/test/CodeGen/vector-bool-pixel-altivec-init.c @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=mixed -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \ +// RUN: -faltivec-src-compat=xl -triple powerpc64le-unknown-unknown -S \ +// RUN: -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=mixed --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=MIXED +// RUN: %clang -mcpu=pwr8 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL +// RUN: %clang -mcpu=pwr9 -faltivec-src-compat=xl --target=powerpc-unknown-unknown \ +// RUN: -S -emit-llvm %s -o - | FileCheck %s --check-prefix=XL + +// Vector bool type +vector bool char vbi8_1; +vector bool char vbi8_2; + +vector bool short vbi16_1; +vector bool short vbi16_2; + +vector bool int vbi32_1; +vector bool int vbi32_2; + +vector bool long long vbi64_1; +vector bool long long vbi64_2; + +// Vector pixel type +vector pixel p1; + +//////////////////////////////////////////////////////////////////////////////// +void test_vector_bool_pixel_init() { + // vector bool char initialization + vbi8_1 = (vector bool char)('a'); + // MIXED: + // XL: + char c = 'c'; + vbi8_2 = (vector bool char)(c); + // MIXED: [[INS:%.*]] = insertelement <16 x i8> + // MIXED: store <16 x i8> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <16 x i8> + // XL: [[SHUFF:%.*]] = shufflevector <16 x i8> [[INS_ELT]], <16 x i8> poison, <16 x i32> zeroinitializer + // XL: store <16 x i8> [[SHUFF]] + + // vector bool short initialization + vbi16_1 = (vector bool short)(5); + // MIXED: + // XL: + short si16 = 55; + vbi16_2 = (vector bool short)(si16); + // MIXED: [[INS:%.*]] = insertelement <8 x i16> + // MIXED: store <8 x i16> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <8 x i16> + // XL: [[SHUFF:%.*]] = shufflevector <8 x i16> [[INS_ELT]], <8 x i16> poison, <8 x i32> zeroinitializer + // XL: store <8 x i16> [[SHUFF]] + + // vector bool int initialization + vbi32_1 = (vector bool int)(9); + // MIXED: + // XL: + int si32 = 99; + vbi32_2 = (vector bool int)(si32); + // MIXED: [[INS:%.*]] = insertelement <4 x i32> + // MIXED: store <4 x i32> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <4 x i32> + // XL: [[SHUFF:%.*]] = shufflevector <4 x i32> [[INS_ELT]], <4 x i32> poison, <4 x i32> zeroinitializer + // XL: store <4 x i32> [[SHUFF]] + + // vector bool long long initialization + vbi64_1 = (vector bool long long)(13); + // MIXED: + // XL: + long long si64 = 1313; + vbi64_2 = (vector bool long long)(si64); + // MIXED: [[INS:%.*]] = insertelement <2 x i64> + // MIXED: store <2 x i64> [[INS:%.*]] + // XL: [[INS_ELT:%.*]] = insertelement <2 x i64> + // XL: [[SHUFF:%.*]] = shufflevector <2 x i64> [[INS_ELT]], <2 x i64> poison, <2 x i32> zeroinitializer + // XL: store <2 x i64> [[SHUFF]] + + // vector pixel initialization + p1 = (vector pixel)(1); + // MIXED: + // XL: +} diff --git a/clang/test/CodeGenCXX/auto-variable-template.cpp b/clang/test/CodeGenCXX/auto-variable-template.cpp index 79a145a73cf31..ae7154f3cb142 100644 --- a/clang/test/CodeGenCXX/auto-variable-template.cpp +++ b/clang/test/CodeGenCXX/auto-variable-template.cpp @@ -12,3 +12,21 @@ int main() { vtemplate(); } // CHECK: define{{.*}} i32 @main() // CHECK: call void @_ZNK1fclEv(%struct.f* {{[^,]*}} @_Z9vtemplateIiE) + +template +struct pack { + template + constexpr static auto some_boolean_cx_value = true; +}; + +auto usage() { + return pack::some_boolean_cx_value; +} + +// CHECK: define{{.*}} i1 @_Z5usagev() + +auto otherusage() { + return pack{}.some_boolean_cx_value; +} + +// CHECK: define{{.*}} i1 @_Z10otherusagev() diff --git a/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp index d3b3e9e9fa631..b1e0cdb0d91ff 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local-reference.cpp @@ -1,13 +1,14 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefixes=CHECK,LINUX_AIX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple powerpc64-unknown-aix-xcoff | FileCheck --check-prefixes=CHECK,LINUX_AIX %s // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s int &f(); -// LINUX: @r ={{.*}} thread_local global i32* null +// LINUX_AIX: @r ={{.*}} thread_local global i32* null // DARWIN: @r = internal thread_local global i32* null thread_local int &r = f(); -// LINUX: @_ZTH1r ={{.*}} alias void (), void ()* @__tls_init +// LINUX_AIX: @_ZTH1r ={{.*}} alias void (), void ()* @__tls_init // DARWIN: @_ZTH1r = internal alias void (), void ()* @__tls_init int &g() { return r; } @@ -17,20 +18,20 @@ int &g() { return r; } // CHECK: store i32* %{{.*}}, i32** @r, align 8 // CHECK-LABEL: define{{.*}} nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) i32* @_Z1gv() -// LINUX: call i32* @_ZTW1r() +// LINUX_AIX: call i32* @_ZTW1r() // DARWIN: call cxx_fast_tlscc i32* @_ZTW1r() // CHECK: ret i32* %{{.*}} -// LINUX: define weak_odr hidden i32* @_ZTW1r() [[ATTR0:#[0-9]+]] comdat { +// LINUX_AIX: define weak_odr hidden i32* @_ZTW1r() [[ATTR0:#[0-9]+]]{{( comdat)?}} { // DARWIN: define cxx_fast_tlscc i32* @_ZTW1r() [[ATTR1:#[0-9]+]] { -// LINUX: call void @_ZTH1r() +// LINUX_AIX: call void @_ZTH1r() // DARWIN: call cxx_fast_tlscc void @_ZTH1r() // CHECK: load i32*, i32** @r, align 8 // CHECK: ret i32* %{{.*}} -// LINUX-LABEL: define internal void @__tls_init() +// LINUX_AIX-LABEL: define internal void @__tls_init() // DARWIN-LABEL: define internal cxx_fast_tlscc void @__tls_init() // CHECK: call void @[[R_INIT]]() -// LINUX: attributes [[ATTR0]] = { {{.*}}"target-features"{{.*}} } +// LINUX_AIX: attributes [[ATTR0]] = { {{.*}}"target-features"{{.*}} } // DARWIN: attributes [[ATTR1]] = { {{.*}}nounwind{{.*}}"target-features"{{.*}} } diff --git a/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp b/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp index a03d7e661f32e..992a25dadc31b 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp @@ -1,12 +1,13 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=LINUX_AIX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple powerpc64-unknown-aix-xcoff | FileCheck --check-prefix=LINUX_AIX %s // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=DARWIN %s // Regression test for PR40327 -// LINUX: @default_tls ={{.*}} thread_local global i32 -// LINUX: @hidden_tls = hidden thread_local global i32 -// LINUX: define weak_odr hidden i32* @_ZTW11default_tls() -// LINUX: define weak_odr hidden i32* @_ZTW10hidden_tls() +// LINUX_AIX: @default_tls ={{.*}} thread_local global i32 +// LINUX_AIX: @hidden_tls ={{( hidden)?}} thread_local global i32 +// LINUX_AIX: define weak_odr hidden i32* @_ZTW11default_tls() +// LINUX_AIX: define weak_odr hidden i32* @_ZTW10hidden_tls() // // DARWIN: @default_tls = internal thread_local global i32 // DARWIN: @hidden_tls = internal thread_local global i32 diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp index da200c61c5ea3..f3146715b9214 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp @@ -1,19 +1,20 @@ -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s -// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -O2 -disable-llvm-passes -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX --check-prefix=CHECK-OPT %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefixes=CHECK,LINUX,LINUX_AIX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -O2 -disable-llvm-passes -o - -triple x86_64-linux-gnu | FileCheck --check-prefixes=CHECK,LINUX,LINUX_AIX,CHECK-OPT %s // RUN: %clang_cc1 -std=c++11 -femulated-tls -emit-llvm %s -o - \ -// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefixes=CHECK,LINUX,LINUX_AIX %s // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple powerpc64-unknown-aix-xcoff | FileCheck --check-prefixes=CHECK,AIX,LINUX_AIX %s -// RUN: %clang_cc1 -std=c++11 -fno-use-cxa-atexit -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s -// RUN: %clang_cc1 -std=c++11 -fno-use-cxa-atexit -emit-llvm %s -O2 -disable-llvm-passes -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=CHECK --check-prefix=LINUX --check-prefix=CHECK-OPT %s +// RUN: %clang_cc1 -std=c++11 -fno-use-cxa-atexit -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefixes=CHECK,LINUX,LINUX_AIX %s +// RUN: %clang_cc1 -std=c++11 -fno-use-cxa-atexit -emit-llvm %s -O2 -disable-llvm-passes -o - -triple x86_64-linux-gnu | FileCheck --check-prefixes=CHECK,LINUX,LINUX_AIX,CHECK-OPT %s // RUN: %clang_cc1 -std=c++11 -fno-use-cxa-atexit -femulated-tls -emit-llvm %s -o - \ -// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=LINUX %s +// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefixes=CHECK,LINUX,LINUX_AIX %s // RUN: %clang_cc1 -std=c++11 -fno-use-cxa-atexit -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=CHECK --check-prefix=DARWIN %s int f(); int g(); -// LINUX-DAG: @a ={{.*}} thread_local global i32 0 +// LINUX_AIX-DAG: @a ={{.*}} thread_local global i32 0 // DARWIN-DAG: @a = internal thread_local global i32 0 thread_local int a = f(); extern thread_local int b; @@ -23,7 +24,7 @@ int c = b; static thread_local int d = g(); struct U { static thread_local int m; }; -// LINUX-DAG: @_ZN1U1mE ={{.*}} thread_local global i32 0 +// LINUX_AIX-DAG: @_ZN1U1mE ={{.*}} thread_local global i32 0 // DARWIN-DAG: @_ZN1U1mE = internal thread_local global i32 0 thread_local int U::m = f(); @@ -89,9 +90,9 @@ void *e2 = V::m + W::m + &X::m; // CHECK-DAG: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]] -// LINUX-DAG: @_ZTH1a ={{.*}} alias void (), void ()* @__tls_init +// LINUX_AIX-DAG: @_ZTH1a ={{.*}} alias void (), void ()* @__tls_init // DARWIN-DAG: @_ZTH1a = internal alias void (), void ()* @__tls_init -// LINUX-DAG: @_ZTHN1U1mE ={{.*}} alias void (), void ()* @__tls_init +// LINUX_AIX-DAG: @_ZTHN1U1mE ={{.*}} alias void (), void ()* @__tls_init // DARWIN-DAG: @_ZTHN1U1mE = internal alias void (), void ()* @__tls_init // CHECK-DAG: @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @[[V_M_INIT:[^, ]*]] // CHECK-DAG: @_ZTHN1XIiE1mE = linkonce_odr alias void (), void ()* @[[X_M_INIT:[^, ]*]] @@ -106,16 +107,16 @@ void *e2 = V::m + W::m + &X::m; // Individual variable initialization functions: // CHECK: define {{.*}} @[[A_INIT:.*]]() -// CHECK: call i32 @_Z1fv() +// CHECK: call{{.*}} i32 @_Z1fv() // CHECK-NEXT: store i32 {{.*}}, i32* @a, align 4 // CHECK-LABEL: define{{.*}} i32 @_Z1fv() int f() { // CHECK: %[[GUARD:.*]] = load i8, i8* @_ZGVZ1fvE1n, align 1 // CHECK: %[[NEED_INIT:.*]] = icmp eq i8 %[[GUARD]], 0 - // CHECK: br i1 %[[NEED_INIT]] + // CHECK: br i1 %[[NEED_INIT]]{{.*}} - // CHECK: %[[CALL:.*]] = call i32 @_Z1gv() + // CHECK: %[[CALL:.*]] = call{{.*}} i32 @_Z1gv() // CHECK: store i32 %[[CALL]], i32* @_ZZ1fvE1n, align 4 // CHECK: store i8 1, i8* @_ZGVZ1fvE1n // CHECK: br label @@ -126,55 +127,57 @@ int f() { } // CHECK: define {{.*}} @[[C_INIT:.*]]() -// LINUX: call i32* @_ZTW1b() +// LINUX_AIX: call i32* @_ZTW1b() // DARWIN: call cxx_fast_tlscc i32* @_ZTW1b() // CHECK-NEXT: load i32, i32* %{{.*}}, align 4 // CHECK-NEXT: store i32 %{{.*}}, i32* @c, align 4 -// LINUX-LABEL: define linkonce_odr hidden i32* @_ZTW1b() +// LINUX_AIX-LABEL: define linkonce_odr hidden i32* @_ZTW1b() // LINUX: br i1 icmp ne (void ()* @_ZTH1b, void ()* null), +// AIX-NOT: br i1 icmp ne (void ()* @_ZTH1b, void ()* null), // not null: -// LINUX: call void @_ZTH1b() +// LINUX_AIX: call void @_ZTH1b() // LINUX: br label +// AIX-NOT: br label // finally: -// LINUX: ret i32* @b +// LINUX_AIX: ret i32* @b // DARWIN-LABEL: declare cxx_fast_tlscc i32* @_ZTW1b() // There is no definition of the thread wrapper on Darwin for external TLV. // CHECK: define {{.*}} @[[D_INIT:.*]]() -// CHECK: call i32 @_Z1gv() +// CHECK: call{{.*}} i32 @_Z1gv() // CHECK-NEXT: store i32 %{{.*}}, i32* @_ZL1d, align 4 // CHECK: define {{.*}} @[[U_M_INIT:.*]]() -// CHECK: call i32 @_Z1fv() +// CHECK: call{{.*}} i32 @_Z1fv() // CHECK-NEXT: store i32 %{{.*}}, i32* @_ZN1U1mE, align 4 // CHECK: define {{.*}} @[[E_INIT:.*]]() -// LINUX: call i32* @_ZTWN1VIiE1mE() +// LINUX_AIX: call i32* @_ZTWN1VIiE1mE() // DARWIN: call cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() // CHECK-NEXT: load i32, i32* %{{.*}}, align 4 -// LINUX: call {{.*}}* @_ZTWN1XIiE1mE() +// LINUX_AIX: call {{.*}}* @_ZTWN1XIiE1mE() // DARWIN: call cxx_fast_tlscc {{.*}}* @_ZTWN1XIiE1mE() // CHECK: store {{.*}} @e -// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() +// LINUX_AIX-LABEL: define weak_odr hidden i32* @_ZTWN1VIiE1mE() // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() -// LINUX: call void @_ZTHN1VIiE1mE() +// LINUX_AIX: call void @_ZTHN1VIiE1mE() // DARWIN: call cxx_fast_tlscc void @_ZTHN1VIiE1mE() // CHECK: ret i32* @_ZN1VIiE1mE -// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1WIiE1mE() +// LINUX_AIX-LABEL: define weak_odr hidden i32* @_ZTWN1WIiE1mE() // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1WIiE1mE() // CHECK-NOT: call // CHECK: ret i32* @_ZN1WIiE1mE -// LINUX-LABEL: define weak_odr hidden {{.*}}* @_ZTWN1XIiE1mE() +// LINUX_AIX-LABEL: define weak_odr hidden {{.*}}* @_ZTWN1XIiE1mE() // DARWIN-LABEL: define weak_odr hidden cxx_fast_tlscc {{.*}}* @_ZTWN1XIiE1mE() -// LINUX: call void @_ZTHN1XIiE1mE() +// LINUX_AIX: call void @_ZTHN1XIiE1mE() // DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE() // CHECK: ret {{.*}}* @_ZN1XIiE1mE -// LINUX: define internal void @[[VF_M_INIT]]() +// LINUX_AIX: define internal void @[[VF_M_INIT]]() // DARWIN: define internal cxx_fast_tlscc void @[[VF_M_INIT]]() // LINUX-SAME: comdat($_ZN1VIfE1mE) // DARWIN-NOT: comdat @@ -182,12 +185,12 @@ int f() { // CHECK: %[[VF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 // CHECK: br i1 %[[VF_M_INITIALIZED]], // need init: -// CHECK: call i32 @_Z1gv() +// CHECK: call{{.*}} i32 @_Z1gv() // CHECK: store i32 %{{.*}}, i32* @_ZN1VIfE1mE, align 4 // CHECK: store i8 1, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*) // CHECK: br label -// LINUX: define internal void @[[XF_M_INIT]]() +// LINUX_AIX: define internal void @[[XF_M_INIT]]() // DARWIN: define internal cxx_fast_tlscc void @[[XF_M_INIT]]() // LINUX-SAME: comdat($_ZN1XIfE1mE) // DARWIN-NOT: comdat @@ -195,31 +198,37 @@ int f() { // CHECK: %[[XF_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 // CHECK: br i1 %[[XF_M_INITIALIZED]], // need init: +// AIX-NOT: br // LINUX: call {{.*}}__cxa_thread_atexit +// AIX: call {{.*}}__pt_atexit_np // DARWIN: call {{.*}}_tlv_atexit // CHECK: store i8 1, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*) // CHECK: br label // LINUX: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) +// AIX: declare i32 @__pt_atexit_np(i32, i32 (i32, ...)*, ...) // DARWIN: declare i32 @_tlv_atexit(void (i8*)*, i8*, i8*) // DARWIN: declare cxx_fast_tlscc i32* @_ZTWN1VIcE1mE() -// LINUX: define linkonce_odr hidden i32* @_ZTWN1VIcE1mE() {{#[0-9]+}} comdat { +// LINUX_AIX: define linkonce_odr hidden i32* @_ZTWN1VIcE1mE() {{#[0-9]+}}{{( comdat)?}} { // LINUX: br i1 icmp ne (void ()* @_ZTHN1VIcE1mE, -// LINUX: call void @_ZTHN1VIcE1mE() -// LINUX: ret i32* @_ZN1VIcE1mE +// AIX-NOT: br i1 icmp ne (void ()* @_ZTHN1VIcE1mE +// LINUX_AIX: call void @_ZTHN1VIcE1mE() +// LINUX_AIX: ret i32* @_ZN1VIcE1mE // DARWIN: declare cxx_fast_tlscc i32* @_ZTWN1WIcE1mE() -// LINUX: define linkonce_odr hidden i32* @_ZTWN1WIcE1mE() {{#[0-9]+}} comdat { +// LINUX_AIX: define linkonce_odr hidden i32* @_ZTWN1WIcE1mE() {{#[0-9]+}}{{( comdat)?}} { // LINUX: br i1 icmp ne (void ()* @_ZTHN1WIcE1mE, -// LINUX: call void @_ZTHN1WIcE1mE() -// LINUX: ret i32* @_ZN1WIcE1mE +// AIX-NOT: br i1 icmp ne (void ()* @_ZTHN1WIcE1mE, +// LINUX_AIX: call void @_ZTHN1WIcE1mE() +// LINUX_AIX: ret i32* @_ZN1WIcE1mE // DARWIN: declare cxx_fast_tlscc {{.*}}* @_ZTWN1XIcE1mE() -// LINUX: define linkonce_odr hidden {{.*}}* @_ZTWN1XIcE1mE() {{#[0-9]+}} comdat { +// LINUX_AIX: define linkonce_odr hidden {{.*}}* @_ZTWN1XIcE1mE() {{#[0-9]+}}{{( comdat)?}} { // LINUX: br i1 icmp ne (void ()* @_ZTHN1XIcE1mE, -// LINUX: call void @_ZTHN1XIcE1mE() -// LINUX: ret {{.*}}* @_ZN1XIcE1mE +// AIX-NOT: br i1 icmp ne (void ()* @_ZTHN1XIcE1mE, +// LINUX_AIX: call void @_ZTHN1XIcE1mE() +// LINUX_AIX: ret {{.*}}* @_ZN1XIcE1mE struct S { S(); ~S(); }; struct T { ~T(); }; @@ -229,6 +238,7 @@ void tls_dtor() { // CHECK: load i8, i8* @_ZGVZ8tls_dtorvE1s // CHECK: call void @_ZN1SC1Ev(%struct.S* {{[^,]*}} @_ZZ8tls_dtorvE1s) // LINUX: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZZ8tls_dtorvE1s{{.*}} @__dso_handle + // AIX: call i32 (i32, i32 (i32, ...)*, ...) @__pt_atexit_np(i32 0, {{.*}}@__dtor__ZZ8tls_dtorvE1s){{.*}} // DARWIN: call i32 @_tlv_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZZ8tls_dtorvE1s{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1s static thread_local S s; @@ -236,6 +246,7 @@ void tls_dtor() { // CHECK: load i8, i8* @_ZGVZ8tls_dtorvE1t // CHECK-NOT: _ZN1T // LINUX: call i32 @__cxa_thread_atexit({{.*}}@_ZN1TD1Ev {{.*}}@_ZZ8tls_dtorvE1t{{.*}} @__dso_handle + // AIX: call i32 (i32, i32 (i32, ...)*, ...) @__pt_atexit_np(i32 0, {{.*}}@__dtor__ZZ8tls_dtorvE1t){{.*}} // DARWIN: call i32 @_tlv_atexit({{.*}}@_ZN1TD1Ev {{.*}}@_ZZ8tls_dtorvE1t{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1t static thread_local T t; @@ -243,11 +254,36 @@ void tls_dtor() { // CHECK: load i8, i8* @_ZGVZ8tls_dtorvE1u // CHECK: call void @_ZN1SC1Ev(%struct.S* {{[^,]*}} @_ZGRZ8tls_dtorvE1u_) // LINUX: call i32 @__cxa_thread_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle + // AIX: call i32 (i32, i32 (i32, ...)*, ...) @__pt_atexit_np(i32 0, {{.*}}__dtor__ZZ8tls_dtorvE1u){{.*}} // DARWIN: call i32 @_tlv_atexit({{.*}}@_ZN1SD1Ev {{.*}} @_ZGRZ8tls_dtorvE1u_{{.*}} @__dso_handle // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1u static thread_local const S &u = S(); } +// AIX: define {{.*}}@__dtor__ZZ8tls_dtorvE1s(i32 signext %0, ...){{.*}}{ +// AIX: entry: +// AIX: %.addr = alloca i32, align 4 +// AIX: store i32 %0, i32* %.addr, align 4 +// AIX: call void @_ZN1SD1Ev(%struct.S* @_ZZ8tls_dtorvE1s) +// AIX: ret i32 0 +// AIX: } + +// AIX: define {{.*}}@__dtor__ZZ8tls_dtorvE1t(i32 signext %0, ...){{.*}}{ +// AIX: entry: +// AIX: %.addr = alloca i32, align 4 +// AIX: store i32 %0, i32* %.addr, align 4 +// AIX: call void @_ZN1TD1Ev(%struct.T* @_ZZ8tls_dtorvE1t) +// AIX: ret i32 0 +// AIX: } + +// AIX: define {{.*}}@__dtor__ZZ8tls_dtorvE1u(i32 signext %0, ...){{.*}}{ +// AIX: entry: +// AIX: %.addr = alloca i32, align 4 +// AIX: store i32 %0, i32* %.addr, align 4 +// AIX: call void @_ZN1SD1Ev(%struct.S* @_ZGRZ8tls_dtorvE1u_) +// AIX: ret i32 0 +// AIX: } + // CHECK: define {{.*}} @_Z7PR15991v( int PR15991() { thread_local int n; @@ -261,7 +297,7 @@ struct PR19254 { }; // CHECK: define {{.*}} @_ZN7PR192541fEv( int PR19254::f() { - // LINUX: call void @_ZTHN7PR192541nE( + // LINUX_AIX: call void @_ZTHN7PR192541nE( // DARWIN: call cxx_fast_tlscc i32* @_ZTWN7PR192541nE( return this->n; } @@ -272,10 +308,10 @@ thread_local int anon_i{f()}; void set_anon_i() { anon_i = 2; } -// LINUX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() +// LINUX_AIX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE() // DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWN12_GLOBAL__N_16anon_iE() -// LINUX: define internal void @[[V_M_INIT]]() +// LINUX_AIX: define internal void @[[V_M_INIT]]() // DARWIN: define internal cxx_fast_tlscc void @[[V_M_INIT]]() // LINUX-SAME: comdat($_ZN1VIiE1mE) // DARWIN-NOT: comdat @@ -283,12 +319,12 @@ void set_anon_i() { // CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 // CHECK: br i1 %[[V_M_INITIALIZED]], // need init: -// CHECK: call i32 @_Z1gv() +// CHECK: call{{.*}} i32 @_Z1gv() // CHECK: store i32 %{{.*}}, i32* @_ZN1VIiE1mE, align 4 // CHECK: store i8 1, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) // CHECK: br label -// LINUX: define internal void @[[X_M_INIT]]() +// LINUX_AIX: define internal void @[[X_M_INIT]]() // DARWIN: define internal cxx_fast_tlscc void @[[X_M_INIT]]() // LINUX-SAME: comdat($_ZN1XIiE1mE) // DARWIN-NOT: comdat @@ -297,6 +333,7 @@ void set_anon_i() { // CHECK: br i1 %[[X_M_INITIALIZED]], // need init: // LINUX: call {{.*}}__cxa_thread_atexit +// AIX: call {{.*}}__pt_atexit_np // DARWIN: call {{.*}}_tlv_atexit // CHECK: store i8 1, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*) // CHECK: br label @@ -322,9 +359,9 @@ void set_anon_i() { // CHECK-NOT: call void @[[V_M_INIT]]() -// LINUX: define weak_odr hidden i32* @_ZTW1a() +// LINUX_AIX: define weak_odr hidden i32* @_ZTW1a() // DARWIN: define cxx_fast_tlscc i32* @_ZTW1a() -// LINUX: call void @_ZTH1a() +// LINUX_AIX: call void @_ZTH1a() // DARWIN: call cxx_fast_tlscc void @_ZTH1a() // CHECK: ret i32* @a // CHECK: } @@ -335,12 +372,20 @@ void set_anon_i() { // thread-local variables in this TU. // CHECK-NOT: define {{.*}} @_ZTWL1d() -// LINUX-LABEL: define weak_odr hidden i32* @_ZTWN1U1mE() +// LINUX_AIX-LABEL: define weak_odr hidden i32* @_ZTWN1U1mE() // DARWIN-LABEL: define cxx_fast_tlscc i32* @_ZTWN1U1mE() -// LINUX: call void @_ZTHN1U1mE() +// LINUX_AIX: call void @_ZTHN1U1mE() // DARWIN: call cxx_fast_tlscc void @_ZTHN1U1mE() // CHECK: ret i32* @_ZN1U1mE -// LINUX: declare extern_weak void @_ZTH1b() [[ATTR:#[0-9]+]] +// LINUX_AIX: declare extern_weak void @_ZTH1b() [[ATTR:#[0-9]+]] + +// AIX: define linkonce_odr void @_ZTHN1WIiE1mE(){{.*}} { +// AIX-NEXT: ret void +// AIX-NEXT: } +// CHECK-NOT: @_ZTHN1WIfE1mE = +// AIX: define weak_odr void @_ZTHN1WIfE1mE(){{.*}} { +// AIX-NEXT: ret void +// AIX-NEXT: } -// LINUX: attributes [[ATTR]] = { {{.+}} } +// LINUX_AIX: attributes [[ATTR]] = { {{.+}} } diff --git a/clang/test/CodeGenCXX/debug-info-template.cpp b/clang/test/CodeGenCXX/debug-info-template.cpp index 4342b3e27a0b2..0255ec9df00fa 100644 --- a/clang/test/CodeGenCXX/debug-info-template.cpp +++ b/clang/test/CodeGenCXX/debug-info-template.cpp @@ -187,3 +187,13 @@ template struct ClassTemplateInlineNamespaceArg { }; ClassTemplateInlineNamespaceArg ClassTemplateInlineNamespaceArgObj; // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ClassTemplateInlineNamespaceArg", + +namespace IndirectDefaultArgument { +template +struct t1 { }; +template +void f1() { +} +template void f1>(); +// CHECK: !DISubprogram(name: "f1 >", +} diff --git a/clang/test/CodeGenCoroutines/coro-always-inline.cpp b/clang/test/CodeGenCoroutines/coro-always-inline.cpp index e4aa14a6ac397..ef7183b9642d5 100644 --- a/clang/test/CodeGenCoroutines/coro-always-inline.cpp +++ b/clang/test/CodeGenCoroutines/coro-always-inline.cpp @@ -40,15 +40,13 @@ struct coroutine_traits { // CHECK-LABEL: @_Z3foov // CHECK-LABEL: entry: -// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca %"struct.std::experimental::awaitable"*, align 8 -// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca %"struct.std::experimental::awaitable"*, align 8 -// CHECK: [[CAST0:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8* -// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST0]]) -// CHECK: [[CAST1:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8* -// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST1]]) - -// CHECK: [[CAST2:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8* -// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST2]]) -// CHECK: [[CAST3:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** %this.addr.i{{[0-9]*}} to i8* -// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST3]]) +// CHECK: [[CAST0:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"* %ref.tmp{{.*}} to i8* +// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[CAST0]]) +// CHECK: [[CAST1:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"* %ref.tmp{{.*}} to i8* +// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[CAST1]]) + +// CHECK: [[CAST2:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"* %ref.tmp{{.*}} to i8* +// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[CAST2]]) +// CHECK: [[CAST3:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"* %ref.tmp{{.*}} to i8* +// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[CAST3]]) void foo() { co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp index 3ddd172e2379f..e9f09c8da038b 100644 --- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp +++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -O0 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s +// RUN: %clang -fcoroutines-ts -std=c++14 -O0 -emit-llvm -c %s -o %t -Xclang -disable-llvm-passes && %clang -c %t #include "Inputs/coroutine.h" diff --git a/clang/test/CodeGenObjC/arc-blocks.m b/clang/test/CodeGenObjC/arc-blocks.m index 078408bc1d6c0..ab0ee3789cba8 100644 --- a/clang/test/CodeGenObjC/arc-blocks.m +++ b/clang/test/CodeGenObjC/arc-blocks.m @@ -477,7 +477,7 @@ @implementation Test12 // CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true) // CHECK: define internal void ()* @"\01-[Test12 nblock]"( -// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false) +// CHECK: %add.ptr = getelementptr inbounds i8, i8* %1, i64 %ivar // CHECK: define internal void @"\01-[Test12 setNblock:]"( // CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true) diff --git a/clang/test/CodeGenObjC/protocol-in-extended-class.m b/clang/test/CodeGenObjC/protocol-in-extended-class.m index 26c858e53e803..74f1be9e53b5a 100644 --- a/clang/test/CodeGenObjC/protocol-in-extended-class.m +++ b/clang/test/CodeGenObjC/protocol-in-extended-class.m @@ -26,4 +26,4 @@ -(void) Meth { // CHECK-LP64: __OBJC_PROTOCOL_$_ExtendedProtocol: -// CHECK-LP32: L_OBJC_PROTOCOL_ExtendedProtocol: +// CHECK-LP32: _OBJC_PROTOCOL_ExtendedProtocol: diff --git a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl index 21e0f2b057475..d24c9c5f85a4b 100644 --- a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl +++ b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl @@ -2,6 +2,8 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN %s // RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN,AMDGCN20 %s // RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL1.2 -O0 -triple spir-unknown-unknown-unknown | FileCheck -enable-var-scope -check-prefixes=SPIR %s +// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL3.0 -O0 -triple amdgcn -cl-ext=+__opencl_c_program_scope_global_variables | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN,AMDGCN20 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL3.0 -O0 -triple amdgcn | FileCheck -enable-var-scope -check-prefixes=ALL,AMDGCN %s typedef int int2 __attribute__((ext_vector_type(2))); @@ -39,7 +41,7 @@ struct LargeStructTwoMember { int2 y[20]; }; -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ >= 300 && defined(__opencl_c_program_scope_global_variables)) struct LargeStructOneMember g_s; #endif @@ -98,7 +100,7 @@ void FuncOneLargeMember(struct LargeStructOneMember u) { // AMDGCN20: %[[r0:.*]] = bitcast %struct.LargeStructOneMember addrspace(5)* %[[byval_temp]] to i8 addrspace(5)* // AMDGCN20: call void @llvm.memcpy.p5i8.p1i8.i64(i8 addrspace(5)* align 8 %[[r0]], i8 addrspace(1)* align 8 bitcast (%struct.LargeStructOneMember addrspace(1)* @g_s to i8 addrspace(1)*), i64 800, i1 false) // AMDGCN20: call void @FuncOneLargeMember(%struct.LargeStructOneMember addrspace(5)* byval(%struct.LargeStructOneMember) align 8 %[[byval_temp]]) -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ >= 300 && defined(__opencl_c_program_scope_global_variables)) void test_indirect_arg_globl(void) { FuncOneLargeMember(g_s); } diff --git a/clang/test/CodeGenOpenCL/address-spaces-conversions.cl b/clang/test/CodeGenOpenCL/address-spaces-conversions.cl index cd3099e0a1a4f..8fdb46184bed6 100644 --- a/clang/test/CodeGenOpenCL/address-spaces-conversions.cl +++ b/clang/test/CodeGenOpenCL/address-spaces-conversions.cl @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -ffake-address-space-map -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -ffake-address-space-map -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -cl-std=CL2.0 -emit-llvm -o - | FileCheck --check-prefix=CHECK-NOFAKE %s +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck --check-prefix=CHECK-NOFAKE %s // When -ffake-address-space-map is not used, all addr space mapped to 0 for x86_64. // test that we generate address space casts everywhere we need conversions of diff --git a/clang/test/CodeGenOpenCL/address-spaces-mangling.cl b/clang/test/CodeGenOpenCL/address-spaces-mangling.cl index 50622f0991430..b46834c2a678c 100644 --- a/clang/test/CodeGenOpenCL/address-spaces-mangling.cl +++ b/clang/test/CodeGenOpenCL/address-spaces-mangling.cl @@ -2,10 +2,14 @@ // RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=yes -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes="ASMANG,ASMANG20" %s // RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes="NOASMANG,NOASMANG10" %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes="NOASMANG,NOASMANG20" %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes="NOASMANG,NOASMANG20" %s +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -ffake-address-space-map -faddress-space-map-mangling=yes -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefixes="ASMANG,ASMANG20" %s // We check that the address spaces are mangled the same in both version of OpenCL // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s // We can't name this f as private is equivalent to default // no specifier given address space so we get multiple definition @@ -47,7 +51,7 @@ void f(constant int *arg) { } // OCL-20-DAG: @_Z1fPU3AS2i // OCL-12-DAG: @_Z1fPU3AS2i -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || defined(__opencl_c_generic_address_space) __attribute__((overloadable)) void f(generic int *arg) { } // ASMANG20: @_Z1fPU3AS4i diff --git a/clang/test/CodeGenOpenCL/address-spaces.cl b/clang/test/CodeGenOpenCL/address-spaces.cl index ebd227a6a9c7d..be131c7820f92 100644 --- a/clang/test/CodeGenOpenCL/address-spaces.cl +++ b/clang/test/CodeGenOpenCL/address-spaces.cl @@ -1,9 +1,13 @@ // RUN: %clang_cc1 %s -O0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR +// RUN: %clang_cc1 %s -O0 -cl-std=CL3.0 -cl-ext=-__opencl_c_generic_address_space -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,SPIR // RUN: %clang_cc1 %s -O0 -DCL20 -cl-std=CL2.0 -ffake-address-space-map -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20SPIR // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s +// RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL3.0 -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -DCL20 -cl-std=CL2.0 -emit-llvm -o - | FileCheck %s --check-prefixes=CL20,CL20AMDGCN // RUN: %clang_cc1 %s -O0 -triple amdgcn-mesa-mesa3d -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s +// RUN: %clang_cc1 %s -O0 -triple amdgcn-mesa-mesa3d -cl-std=CL3.0 -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s // RUN: %clang_cc1 %s -O0 -triple r600-- -emit-llvm -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s +// RUN: %clang_cc1 %s -O0 -triple r600-- -emit-llvm -cl-std=CL3.0 -o - | FileCheck --check-prefixes=CHECK,AMDGCN %s // SPIR: %struct.S = type { i32, i32, i32* } // CL20SPIR: %struct.S = type { i32, i32, i32 addrspace(4)* } diff --git a/clang/test/CodeGenOpenCL/amdgpu-sizeof-alignof.cl b/clang/test/CodeGenOpenCL/amdgpu-sizeof-alignof.cl index a5d438933fa47..3bd395da6d452 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-sizeof-alignof.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-sizeof-alignof.cl @@ -5,6 +5,18 @@ // RUN: %clang_cc1 -triple amdgcn---amdgizcl -cl-std=CL1.2 %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -triple amdgcn---amdgizcl -cl-std=CL2.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple r600 -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-mesa-mesa3d -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn---opencl -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn---amdgizcl -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-mesa-mesa3d -cl-ext=+__opencl_c_generic_address_space -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn---opencl -cl-ext=+__opencl_c_generic_address_space -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn---amdgizcl -cl-ext=+__opencl_c_generic_address_space -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple r600 -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-mesa-mesa3d -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn---opencl -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn---amdgizcl -cl-ext=+cl_khr_fp64,+__opencl_c_fp64 -cl-std=CL3.0 %s -emit-llvm -o - | FileCheck %s + #ifdef __AMDGCN__ #define PTSIZE 8 #else @@ -58,9 +70,12 @@ void test() { check(sizeof(double) == 8); check(__alignof__(double) == 8); #endif - - check(sizeof(void*) == (__OPENCL_C_VERSION__ >= 200 ? 8 : 4)); - check(__alignof__(void*) == (__OPENCL_C_VERSION__ >= 200 ? 8 : 4)); + check(sizeof(private void*) == 4); + check(__alignof__(private void*) == 4); +#if (__OPENCL_C_VERSION__ == 200) || defined(__opencl_c_generic_address_space) + check(sizeof(generic void*) == 8); + check(__alignof__(generic void*) == 8); +#endif check(sizeof(global_ptr_t) == PTSIZE); check(__alignof__(global_ptr_t) == PTSIZE); check(sizeof(constant_ptr_t) == PTSIZE); diff --git a/clang/test/CodeGenOpenCL/overload.cl b/clang/test/CodeGenOpenCL/overload.cl index f182cb5fd2af4..bc844595a59a5 100644 --- a/clang/test/CodeGenOpenCL/overload.cl +++ b/clang/test/CodeGenOpenCL/overload.cl @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -cl-std=CL2.0 -emit-llvm -o - -triple spir-unknown-unknown %s | FileCheck %s +// RUN: %clang_cc1 -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -emit-llvm -o - -triple spir-unknown-unknown %s | FileCheck %s typedef short short4 __attribute__((ext_vector_type(4))); diff --git a/clang/test/Driver/cuda-arch-translation.cu b/clang/test/Driver/cuda-arch-translation.cu index b574d082218e8..683add5338795 100644 --- a/clang/test/Driver/cuda-arch-translation.cu +++ b/clang/test/Driver/cuda-arch-translation.cu @@ -6,67 +6,69 @@ // REQUIRES: nvptx-registered-target // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM20 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM20 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_21 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM21 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM21 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_30 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM30 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM30 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_32 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM32 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM32 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_35 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM35 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM35 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_37 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM37 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM37 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_50 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM50 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM50 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_52 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM52 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM52 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_53 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM53 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM53 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_60 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM60 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM60 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_61 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM61 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM61 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_62 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM62 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM62 %s // RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_70 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,SM70 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx600 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX600 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx601 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX601 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx602 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX602 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx700 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX700 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx701 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX701 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx702 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX702 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx703 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX703 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx704 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX704 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx705 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX705 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx801 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX801 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx802 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX802 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx803 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX803 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx805 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX805 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx810 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX810 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx900 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX900 %s -// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx902 %s 2>&1 \ -// RUN: | FileCheck -check-prefixes=COMMON,GFX902 %s +// RUN: | FileCheck -check-prefixes=CUDA,SM70 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx600 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX600 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx601 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX601 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx602 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX602 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx700 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX700 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx701 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX701 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx702 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX702 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx703 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX703 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx704 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX704 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx705 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX705 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx801 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX801 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx802 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX802 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx803 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX803 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx805 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX805 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx810 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX810 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx900 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX900 %s +// RUN: %clang -x hip -### -target x86_64-linux-gnu -c --cuda-gpu-arch=gfx902 %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HIP,GFX902 %s -// COMMON: ptxas -// COMMON-SAME: -m64 -// COMMON: fatbinary +// CUDA: ptxas +// CUDA-SAME: -m64 +// CUDA: fatbinary + +// HIP: clang-offload-bundler // SM20:--image=profile=sm_20{{.*}}--image=profile=compute_20 // SM21:--image=profile=sm_21{{.*}}--image=profile=compute_20 @@ -81,19 +83,19 @@ // SM61:--image=profile=sm_61{{.*}}--image=profile=compute_61 // SM62:--image=profile=sm_62{{.*}}--image=profile=compute_62 // SM70:--image=profile=sm_70{{.*}}--image=profile=compute_70 -// GFX600:--image=profile=gfx600{{.*}}--image=profile=compute_amdgcn -// GFX601:--image=profile=gfx601{{.*}}--image=profile=compute_amdgcn -// GFX602:--image=profile=gfx602{{.*}}--image=profile=compute_amdgcn -// GFX700:--image=profile=gfx700{{.*}}--image=profile=compute_amdgcn -// GFX701:--image=profile=gfx701{{.*}}--image=profile=compute_amdgcn -// GFX702:--image=profile=gfx702{{.*}}--image=profile=compute_amdgcn -// GFX703:--image=profile=gfx703{{.*}}--image=profile=compute_amdgcn -// GFX704:--image=profile=gfx704{{.*}}--image=profile=compute_amdgcn -// GFX705:--image=profile=gfx705{{.*}}--image=profile=compute_amdgcn -// GFX801:--image=profile=gfx801{{.*}}--image=profile=compute_amdgcn -// GFX802:--image=profile=gfx802{{.*}}--image=profile=compute_amdgcn -// GFX803:--image=profile=gfx803{{.*}}--image=profile=compute_amdgcn -// GFX805:--image=profile=gfx805{{.*}}--image=profile=compute_amdgcn -// GFX810:--image=profile=gfx810{{.*}}--image=profile=compute_amdgcn -// GFX900:--image=profile=gfx900{{.*}}--image=profile=compute_amdgcn -// GFX902:--image=profile=gfx902{{.*}}--image=profile=compute_amdgcn +// GFX600:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx600 +// GFX601:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx601 +// GFX602:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx602 +// GFX700:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx700 +// GFX701:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx701 +// GFX702:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx702 +// GFX703:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx703 +// GFX704:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx704 +// GFX705:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx705 +// GFX801:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx801 +// GFX802:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx802 +// GFX803:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx803 +// GFX805:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx805 +// GFX810:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx810 +// GFX900:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx900 +// GFX902:-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx902 diff --git a/clang/test/Driver/cuda-bad-arch.cu b/clang/test/Driver/cuda-bad-arch.cu index 22a7be1e7d839..8f52f6e4b6c12 100644 --- a/clang/test/Driver/cuda-bad-arch.cu +++ b/clang/test/Driver/cuda-bad-arch.cu @@ -10,6 +10,8 @@ // RUN: | FileCheck -check-prefix BAD %s // RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_19 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix BAD %s +// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix BAD %s // BAD: error: Unsupported CUDA gpu architecture @@ -23,9 +25,9 @@ // RUN: | FileCheck -check-prefix OK %s // RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_52 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=gfx908 -c %s 2>&1 \ +// RUN: %clang -### -x hip -target x86_64-linux-gnu --cuda-gpu-arch=gfx908 -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s -// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=gfx90a -c %s 2>&1 \ +// RUN: %clang -### -x hip -target x86_64-linux-gnu --cuda-gpu-arch=gfx90a -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s // RUN: %clang -### -target x86_64-linux-gnu -c %s 2>&1 \ // RUN: | FileCheck -check-prefix OK %s diff --git a/clang/test/Driver/cuda-flush-denormals-to-zero.cu b/clang/test/Driver/cuda-flush-denormals-to-zero.cu index e8ac6d73c8ff2..0f2b5de431fa8 100644 --- a/clang/test/Driver/cuda-flush-denormals-to-zero.cu +++ b/clang/test/Driver/cuda-flush-denormals-to-zero.cu @@ -12,8 +12,8 @@ // RUN: %clang -no-canonical-prefixes -### -target x86_64-linux-gnu -c -march=haswell --cuda-gpu-arch=sm_20 -fno-cuda-flush-denormals-to-zero -nocudainc -nocudalib %s 2>&1 | FileCheck -check-prefix=NOFTZ %s // Test explicit argument, with CUDA offload kind -// RUN: %clang -no-canonical-prefixes -### -target x86_64-linux-gnu -c -march=haswell --cuda-gpu-arch=gfx803 -fgpu-flush-denormals-to-zero -nocudainc -nogpulib %s 2>&1 | FileCheck -check-prefix=FTZ %s -// RUN: %clang -no-canonical-prefixes -### -target x86_64-linux-gnu -c -march=haswell --cuda-gpu-arch=gfx803 -fno-gpu-flush-denormals-to-zero -nocudainc -nogpulib %s 2>&1 | FileCheck -check-prefix=NOFTZ %s +// RUN: %clang -x hip -no-canonical-prefixes -### -target x86_64-linux-gnu -c -march=haswell --cuda-gpu-arch=gfx803 -fgpu-flush-denormals-to-zero -nocudainc -nogpulib %s 2>&1 | FileCheck -check-prefix=FTZ %s +// RUN: %clang -x hip -no-canonical-prefixes -### -target x86_64-linux-gnu -c -march=haswell --cuda-gpu-arch=gfx803 -fno-gpu-flush-denormals-to-zero -nocudainc -nogpulib %s 2>&1 | FileCheck -check-prefix=NOFTZ %s // Test explicit argument, with HIP offload kind // RUN: %clang -x hip -no-canonical-prefixes -### -target x86_64-linux-gnu -c -march=haswell --cuda-gpu-arch=gfx803 -fgpu-flush-denormals-to-zero -nocudainc -nogpulib %s 2>&1 | FileCheck -check-prefix=FTZ %s diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index 54a8a6a3f74a9..3b1f1d555bbc7 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -424,3 +424,14 @@ // GDWARF64_VER: error: invalid argument '-gdwarf64' only allowed with 'DWARFv3 or greater' // GDWARF64_32ARCH: error: invalid argument '-gdwarf64' only allowed with '64 bit architecture' // GDWARF64_ELF: error: invalid argument '-gdwarf64' only allowed with 'ELF platforms' + +/// Default to -fno-dwarf-directory-asm for -fno-integrated-as before DWARF v5. +// RUN: %clang -### -target x86_64 -c -gdwarf-2 %s 2>&1 | FileCheck --check-prefix=DIRECTORY %s +// RUN: %clang -### -target x86_64 -c -gdwarf-5 %s 2>&1 | FileCheck --check-prefix=DIRECTORY %s +// RUN: %clang -### -target x86_64 -c -gdwarf-4 -fno-integrated-as %s 2>&1 | FileCheck --check-prefix=NODIRECTORY %s +// RUN: %clang -### -target x86_64 -c -gdwarf-5 -fno-integrated-as %s 2>&1 | FileCheck --check-prefix=DIRECTORY %s + +// RUN: %clang -### -target x86_64 -c -gdwarf-4 -fno-dwarf-directory-asm %s 2>&1 | FileCheck --check-prefix=NODIRECTORY %s + +// DIRECTORY-NOT: "-fno-dwarf-directory-asm" +// NODIRECTORY: "-fno-dwarf-directory-asm" diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index baa37b5fd79d9..b7d61abe7ec53 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -247,6 +247,20 @@ // CHECK-ASAN-GLOBALS: -cc1{{.*}}-fsanitize-address-globals-dead-stripping // CHECK-NO-ASAN-GLOBALS-NOT: -cc1{{.*}}-fsanitize-address-globals-dead-stripping +// RUN: %clang -target x86_64-linux-gnu -fsanitize-address-outline-instrumentation %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ASAN-OUTLINE-WARN +// CHECK-ASAN-OUTLINE-WARN: warning: argument unused during compilation: '-fsanitize-address-outline-instrumentation' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-outline-instrumentation %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ASAN-OUTLINE-OK +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-outline-instrumentation -fsanitize-address-outline-instrumentation %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-ASAN-OUTLINE-OK +// CHECK-ASAN-OUTLINE-OK: "-mllvm" "-asan-instrumentation-with-call-threshold=0" +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-outline-instrumentation %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-CHECK-ASAN-CALLBACK +// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-outline-instrumentation -fno-sanitize-address-outline-instrumentation %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-CHECK-ASAN-CALLBACK +// CHECK-NO-CHECK-ASAN-CALLBACK-NOT: "-mllvm" "-asan-instrumentation-with-call-threshold=0" + // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-odr-indicator %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR // RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fsanitize-address-use-odr-indicator -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-ODR-INDICATOR // CHECK-ASAN-ODR-INDICATOR: -cc1{{.*}}-fsanitize-address-use-odr-indicator diff --git a/clang/test/Driver/ppc-isa-features.cpp b/clang/test/Driver/ppc-isa-features.cpp new file mode 100644 index 0000000000000..9e2bc3f90bf7c --- /dev/null +++ b/clang/test/Driver/ppc-isa-features.cpp @@ -0,0 +1,21 @@ +// RUN: %clang -target powerpc64-unknown-unknown -mcpu=pwr7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-PWR7 +// RUN: %clang -target powerpc64le-unknown-unknown -mcpu=pwr8 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-PWR8 +// RUN: %clang -target powerpc64-unknown-aix -mcpu=pwr9 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-PWR9 +// RUN: %clang -target powerpc-unknown-aix -mcpu=pwr10 -S -emit-llvm %s -o - | FileCheck %s -check-prefix=CHECK-PWR10 + +// CHECK-PWR7: -isa-v207-instructions +// CHECK-PWR7: -isa-v30-instructions + +// CHECK-PWR8: +isa-v207-instructions +// CHECK-PWR8: -isa-v30-instructions + +// CHECK-PWR9: +isa-v207-instructions +// CHECK-PWR9: +isa-v30-instructions + +// CHECK-PWR10: +isa-v207-instructions +// CHECK-PWR10: +isa-v30-instructions +// CHECK-PWR10: +isa-v31-instructions + +int main(int argc, char *argv[]) { + return 0; +} diff --git a/clang/test/Driver/pseudo-probe.c b/clang/test/Driver/pseudo-probe.c index 297992cfd1a15..79b23df557a6c 100644 --- a/clang/test/Driver/pseudo-probe.c +++ b/clang/test/Driver/pseudo-probe.c @@ -1,7 +1,13 @@ // RUN: %clang -### -fpseudo-probe-for-profiling %s 2>&1 | FileCheck %s --check-prefix=YESPROBE // RUN: %clang -### -fno-pseudo-probe-for-profiling %s 2>&1 | FileCheck %s --check-prefix=NOPROBE // RUN: %clang -### -fpseudo-probe-for-profiling -fdebug-info-for-profiling %s 2>&1 | FileCheck %s --check-prefix=CONFLICT +// RUN: %clang -### -fpseudo-probe-for-profiling -funique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=YESPROBE +// RUN: %clang -### -fpseudo-probe-for-profiling -fno-unique-internal-linkage-names %s 2>&1 | FileCheck %s --check-prefix=NONAME // YESPROBE: -fpseudo-probe-for-profiling +// YESPROBE: -funique-internal-linkage-names // NOPROBE-NOT: -fpseudo-probe-for-profiling +// NOPROBE-NOT: -funique-internal-linkage-names +// NONAME: -fpseudo-probe-for-profiling +// NONAME-NOT: -funique-internal-linkage-names // CONFLICT: invalid argument diff --git a/clang/test/Driver/riscv-args.c b/clang/test/Driver/riscv-args.c index 7b68df977f7c3..305a50885eade 100644 --- a/clang/test/Driver/riscv-args.c +++ b/clang/test/Driver/riscv-args.c @@ -1,7 +1,6 @@ // Check the arguments are correctly passed // Make sure -T is the last with gcc-toolchain option -// RUN: %clang -### -target riscv32 \ -// RUN: --gcc-toolchain= -Xlinker --defsym=FOO=10 -T a.lds %s 2>&1 \ +// RUN: %clang -### -target riscv32 --gcc-toolchain= -Xlinker --defsym=FOO=10 -T a.lds -u foo %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LD %s -// CHECK-LD: {{.*}} "--defsym=FOO=10" {{.*}} "-T" "a.lds" +// CHECK-LD: {{.*}} "--defsym=FOO=10" {{.*}} "-u" "foo" {{.*}} "-T" "a.lds" diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c index 46f8729e18676..5e89552345f67 100644 --- a/clang/test/Driver/sanitizer-ld.c +++ b/clang/test/Driver/sanitizer-ld.c @@ -284,28 +284,28 @@ // CHECK-MSAN-NO-LINK-RUNTIME-LINUX-NOT: libclang_rt.msan // RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ -// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: -target x86_64-unknown-linux-gnux32 -fuse-ld=ld \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s // RUN: %clang -fsanitize=float-divide-by-zero %s -### -o %t.o 2>&1 \ -// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: -target x86_64-unknown-linux-gnux32 -fuse-ld=ld \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s // RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ -// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: -target x86_64-unknown-linux-gnux32 -fuse-ld=ld \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: -static-libsan \ // RUN: | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s // CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}" // CHECK-UBSAN-LINUX-NOT: libclang_rt.asan // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx -// CHECK-UBSAN-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-i386.a" "--no-whole-archive" +// CHECK-UBSAN-LINUX: "--whole-archive" "{{.*}}libclang_rt.ubsan_standalone-x32.a" "--no-whole-archive" // CHECK-UBSAN-LINUX-NOT: libclang_rt.asan // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_standalone_cxx // CHECK-UBSAN-LINUX-NOT: "-lstdc++" diff --git a/clang/test/Headers/builtins-header.c b/clang/test/Headers/builtins-header.c new file mode 100644 index 0000000000000..db5e0c56765d0 --- /dev/null +++ b/clang/test/Headers/builtins-header.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -ffreestanding -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -ffreestanding -emit-llvm -o - %s | FileCheck %s + +#include + +// Verify that we can include + +// CHECK: target triple = "powerpc64 diff --git a/clang/test/Headers/wasm.c b/clang/test/Headers/wasm.c index 1cf87b4bb786a..7f279725192a4 100644 --- a/clang/test/Headers/wasm.c +++ b/clang/test/Headers/wasm.c @@ -162,9 +162,10 @@ v128_t test_v128_load64_zero(const void *mem) { // CHECK-LABEL: @test_v128_load8_lane( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.wasm.load8.lane(i8* [[PTR:%.*]], <16 x i8> [[TMP0]], i32 15) -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> +// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <16 x i8> +// CHECK-NEXT: [[VECINS_I:%.*]] = insertelement <16 x i8> [[TMP1]], i8 [[TMP0]], i32 15 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VECINS_I]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_v128_load8_lane(const uint8_t *ptr, v128_t vec) { @@ -173,9 +174,10 @@ v128_t test_v128_load8_lane(const uint8_t *ptr, v128_t vec) { // CHECK-LABEL: @test_v128_load16_lane( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.wasm.load16.lane(i16* [[PTR:%.*]], <8 x i16> [[TMP0]], i32 7) -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i16> [[TMP1]] to <4 x i32> +// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <8 x i16> +// CHECK-NEXT: [[VECINS_I:%.*]] = insertelement <8 x i16> [[TMP1]], i16 [[TMP0]], i32 7 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i16> [[VECINS_I]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_v128_load16_lane(const uint16_t *ptr, v128_t vec) { @@ -184,8 +186,9 @@ v128_t test_v128_load16_lane(const uint16_t *ptr, v128_t vec) { // CHECK-LABEL: @test_v128_load32_lane( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.wasm.load32.lane(i32* [[PTR:%.*]], <4 x i32> [[VEC:%.*]], i32 3) -// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] +// CHECK-NEXT: [[VECINS_I:%.*]] = insertelement <4 x i32> [[VEC:%.*]], i32 [[TMP0]], i32 3 +// CHECK-NEXT: ret <4 x i32> [[VECINS_I]] // v128_t test_v128_load32_lane(const uint32_t *ptr, v128_t vec) { return wasm_v128_load32_lane(ptr, vec, 3); @@ -193,9 +196,10 @@ v128_t test_v128_load32_lane(const uint32_t *ptr, v128_t vec) { // CHECK-LABEL: @test_v128_load64_lane( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i64> @llvm.wasm.load64.lane(i64* [[PTR:%.*]], <2 x i64> [[TMP0]], i32 1) -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to <4 x i32> +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] +// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <2 x i64> +// CHECK-NEXT: [[VECINS_I:%.*]] = insertelement <2 x i64> [[TMP1]], i64 [[TMP0]], i32 1 +// CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[VECINS_I]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_v128_load64_lane(const uint64_t *ptr, v128_t vec) { @@ -215,7 +219,8 @@ void test_v128_store(void *mem, v128_t a) { // CHECK-LABEL: @test_v128_store8_lane( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <16 x i8> -// CHECK-NEXT: tail call void @llvm.wasm.store8.lane(i8* [[PTR:%.*]], <16 x i8> [[TMP0]], i32 15) +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <16 x i8> [[TMP0]], i32 15 +// CHECK-NEXT: store i8 [[VECEXT_I]], i8* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // void test_v128_store8_lane(uint8_t *ptr, v128_t vec) { @@ -225,7 +230,8 @@ void test_v128_store8_lane(uint8_t *ptr, v128_t vec) { // CHECK-LABEL: @test_v128_store16_lane( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <8 x i16> -// CHECK-NEXT: tail call void @llvm.wasm.store16.lane(i16* [[PTR:%.*]], <8 x i16> [[TMP0]], i32 7) +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <8 x i16> [[TMP0]], i32 7 +// CHECK-NEXT: store i16 [[VECEXT_I]], i16* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // void test_v128_store16_lane(uint16_t *ptr, v128_t vec) { @@ -234,7 +240,8 @@ void test_v128_store16_lane(uint16_t *ptr, v128_t vec) { // CHECK-LABEL: @test_v128_store32_lane( // CHECK-NEXT: entry: -// CHECK-NEXT: tail call void @llvm.wasm.store32.lane(i32* [[PTR:%.*]], <4 x i32> [[VEC:%.*]], i32 3) +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <4 x i32> [[VEC:%.*]], i32 3 +// CHECK-NEXT: store i32 [[VECEXT_I]], i32* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // void test_v128_store32_lane(uint32_t *ptr, v128_t vec) { @@ -244,7 +251,8 @@ void test_v128_store32_lane(uint32_t *ptr, v128_t vec) { // CHECK-LABEL: @test_v128_store64_lane( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[VEC:%.*]] to <2 x i64> -// CHECK-NEXT: tail call void @llvm.wasm.store64.lane(i64* [[PTR:%.*]], <2 x i64> [[TMP0]], i32 1) +// CHECK-NEXT: [[VECEXT_I:%.*]] = extractelement <2 x i64> [[TMP0]], i32 1 +// CHECK-NEXT: store i64 [[VECEXT_I]], i64* [[PTR:%.*]], align 1, !tbaa [[TBAA2]] // CHECK-NEXT: ret void // void test_v128_store64_lane(uint64_t *ptr, v128_t vec) { @@ -1281,7 +1289,7 @@ v128_t test_v128_andnot(v128_t a, v128_t b) { // CHECK-LABEL: @test_v128_any_true( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> [[TMP0]]) #[[ATTR10:[0-9]+]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> [[TMP0]]) #[[ATTR6:[0-9]+]] // CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp ne i32 [[TMP1]], 0 // CHECK-NEXT: ret i1 [[TOBOOL_I]] // @@ -1291,7 +1299,7 @@ bool test_v128_any_true(v128_t a) { // CHECK-LABEL: @test_v128_bitselect( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.wasm.bitselect.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[MASK:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.wasm.bitselect.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[MASK:%.*]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP0]] // v128_t test_v128_bitselect(v128_t a, v128_t b, v128_t mask) { @@ -1301,7 +1309,7 @@ v128_t test_v128_bitselect(v128_t a, v128_t b, v128_t mask) { // CHECK-LABEL: @test_i8x16_abs( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.abs.v16i8(<16 x i8> [[TMP0]], i1 false) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.abs.v16i8(<16 x i8> [[TMP0]], i1 false) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -1323,7 +1331,7 @@ v128_t test_i8x16_neg(v128_t a) { // CHECK-LABEL: @test_i8x16_all_true( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.alltrue.v16i8(<16 x i8> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp ne i32 [[TMP1]], 0 // CHECK-NEXT: ret i1 [[TOBOOL_I]] // @@ -1334,7 +1342,7 @@ bool test_i8x16_all_true(v128_t a) { // CHECK-LABEL: @test_i8x16_bitmask( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.bitmask.v16i8(<16 x i8> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.bitmask.v16i8(<16 x i8> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret i32 [[TMP1]] // int32_t test_i8x16_bitmask(v128_t a) { @@ -1344,7 +1352,7 @@ int32_t test_i8x16_bitmask(v128_t a) { // CHECK-LABEL: @test_i8x16_popcnt( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.wasm.popcnt(<16 x i8> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.wasm.popcnt(<16 x i8> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -1410,7 +1418,7 @@ v128_t test_i8x16_add(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1422,7 +1430,7 @@ v128_t test_i8x16_add_sat(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1446,7 +1454,7 @@ v128_t test_i8x16_sub(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.sub.sat.signed.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.sub.sat.signed.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1458,7 +1466,7 @@ v128_t test_i8x16_sub_sat(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.sub.sat.unsigned.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.sub.sat.unsigned.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1522,7 +1530,7 @@ v128_t test_u8x16_max(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.avgr.unsigned.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.avgr.unsigned.v16i8(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1533,7 +1541,7 @@ v128_t test_u8x16_avgr(v128_t a, v128_t b) { // CHECK-LABEL: @test_i16x8_abs( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[TMP0]], i1 false) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[TMP0]], i1 false) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i16> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -1555,7 +1563,7 @@ v128_t test_i16x8_neg(v128_t a) { // CHECK-LABEL: @test_i16x8_all_true( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.alltrue.v8i16(<8 x i16> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp ne i32 [[TMP1]], 0 // CHECK-NEXT: ret i1 [[TOBOOL_I]] // @@ -1566,7 +1574,7 @@ bool test_i16x8_all_true(v128_t a) { // CHECK-LABEL: @test_i16x8_bitmask( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.bitmask.v8i16(<8 x i16> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.bitmask.v8i16(<8 x i16> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret i32 [[TMP1]] // int32_t test_i16x8_bitmask(v128_t a) { @@ -1631,7 +1639,7 @@ v128_t test_i16x8_add(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1643,7 +1651,7 @@ v128_t test_i16x8_add_sat(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1667,7 +1675,7 @@ v128_t test_i16x8_sub(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.sub.sat.signed.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.sub.sat.signed.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1679,7 +1687,7 @@ v128_t test_i16x8_sub_sat(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.sub.sat.unsigned.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.sub.sat.unsigned.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1755,7 +1763,7 @@ v128_t test_u16x8_max(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.avgr.unsigned.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.avgr.unsigned.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -1765,7 +1773,7 @@ v128_t test_u16x8_avgr(v128_t a, v128_t b) { // CHECK-LABEL: @test_i32x4_abs( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[A:%.*]], i1 false) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[A:%.*]], i1 false) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP0]] // v128_t test_i32x4_abs(v128_t a) { @@ -1783,7 +1791,7 @@ v128_t test_i32x4_neg(v128_t a) { // CHECK-LABEL: @test_i32x4_all_true( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> [[A:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.wasm.alltrue.v4i32(<4 x i32> [[A:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp ne i32 [[TMP0]], 0 // CHECK-NEXT: ret i1 [[TOBOOL_I]] // @@ -1793,7 +1801,7 @@ bool test_i32x4_all_true(v128_t a) { // CHECK-LABEL: @test_i32x4_bitmask( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.wasm.bitmask.v4i32(<4 x i32> [[A:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.wasm.bitmask.v4i32(<4 x i32> [[A:%.*]]) #[[ATTR6]] // CHECK-NEXT: ret i32 [[TMP0]] // int32_t test_i32x4_bitmask(v128_t a) { @@ -1904,7 +1912,7 @@ v128_t test_u32x4_max(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.dot(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_i32x4_dot_i16x8(v128_t a, v128_t b) { @@ -1914,7 +1922,7 @@ v128_t test_i32x4_dot_i16x8(v128_t a, v128_t b) { // CHECK-LABEL: @test_i64x2_abs( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i64> @llvm.abs.v2i64(<2 x i64> [[TMP0]], i1 false) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i64> @llvm.abs.v2i64(<2 x i64> [[TMP0]], i1 false) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -1936,7 +1944,7 @@ v128_t test_i64x2_neg(v128_t a) { // CHECK-LABEL: @test_i64x2_all_true( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.alltrue.v2i64(<2 x i64> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp ne i32 [[TMP1]], 0 // CHECK-NEXT: ret i1 [[TOBOOL_I]] // @@ -1947,7 +1955,7 @@ bool test_i64x2_all_true(v128_t a) { // CHECK-LABEL: @test_i64x2_bitmask( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x i64> -// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.bitmask.v2i64(<2 x i64> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.wasm.bitmask.v2i64(<2 x i64> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret i32 [[TMP1]] // int32_t test_i64x2_bitmask(v128_t a) { @@ -2035,7 +2043,7 @@ v128_t test_i64x2_mul(v128_t a, v128_t b) { // CHECK-LABEL: @test_f32x4_abs( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2057,7 +2065,7 @@ v128_t test_f32x4_neg(v128_t a) { // CHECK-LABEL: @test_f32x4_sqrt( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.sqrt.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.sqrt.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2068,7 +2076,7 @@ v128_t test_f32x4_sqrt(v128_t a) { // CHECK-LABEL: @test_f32x4_ceil( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.ceil.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.ceil.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2079,7 +2087,7 @@ v128_t test_f32x4_ceil(v128_t a) { // CHECK-LABEL: @test_f32x4_floor( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.floor.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.floor.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2090,7 +2098,7 @@ v128_t test_f32x4_floor(v128_t a) { // CHECK-LABEL: @test_f32x4_trunc( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.trunc.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.trunc.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2101,7 +2109,7 @@ v128_t test_f32x4_trunc(v128_t a) { // CHECK-LABEL: @test_f32x4_nearest( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.nearbyint.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.nearbyint.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2161,7 +2169,7 @@ v128_t test_f32x4_div(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.minimum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.minimum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x float> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2173,7 +2181,7 @@ v128_t test_f32x4_min(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.maximum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.maximum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x float> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2185,7 +2193,7 @@ v128_t test_f32x4_max(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.wasm.pmin.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.wasm.pmin.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x float> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2197,7 +2205,7 @@ v128_t test_f32x4_pmin(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.wasm.pmax.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.wasm.pmax.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x float> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2208,7 +2216,7 @@ v128_t test_f32x4_pmax(v128_t a, v128_t b) { // CHECK-LABEL: @test_f64x2_abs( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2230,7 +2238,7 @@ v128_t test_f64x2_neg(v128_t a) { // CHECK-LABEL: @test_f64x2_sqrt( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.sqrt.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.sqrt.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2241,7 +2249,7 @@ v128_t test_f64x2_sqrt(v128_t a) { // CHECK-LABEL: @test_f64x2_ceil( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.ceil.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.ceil.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2252,7 +2260,7 @@ v128_t test_f64x2_ceil(v128_t a) { // CHECK-LABEL: @test_f64x2_floor( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.floor.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.floor.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2263,7 +2271,7 @@ v128_t test_f64x2_floor(v128_t a) { // CHECK-LABEL: @test_f64x2_trunc( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.trunc.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.trunc.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2274,7 +2282,7 @@ v128_t test_f64x2_trunc(v128_t a) { // CHECK-LABEL: @test_f64x2_nearest( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x double> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2334,7 +2342,7 @@ v128_t test_f64x2_div(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.minimum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.minimum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x double> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2346,7 +2354,7 @@ v128_t test_f64x2_min(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.maximum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.maximum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x double> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2358,7 +2366,7 @@ v128_t test_f64x2_max(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.wasm.pmin.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.wasm.pmin.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x double> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2370,7 +2378,7 @@ v128_t test_f64x2_pmin(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.wasm.pmax.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <2 x double> @llvm.wasm.pmax.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x double> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2381,7 +2389,7 @@ v128_t test_f64x2_pmax(v128_t a, v128_t b) { // CHECK-LABEL: @test_i32x4_trunc_sat_f32x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP1]] // v128_t test_i32x4_trunc_sat_f32x4(v128_t a) { @@ -2391,7 +2399,7 @@ v128_t test_i32x4_trunc_sat_f32x4(v128_t a) { // CHECK-LABEL: @test_u32x4_trunc_sat_f32x4( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <4 x float> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP1]] // v128_t test_u32x4_trunc_sat_f32x4(v128_t a) { @@ -2443,7 +2451,7 @@ v128_t test_f64x2_convert_low_u32x4(v128_t a) { // CHECK-LABEL: @test_i32x4_trunc_sat_f64x2_zero( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> zeroinitializer, <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2454,7 +2462,7 @@ v128_t test_i32x4_trunc_sat_f64x2_zero(v128_t a) { // CHECK-LABEL: @test_u32x4_trunc_sat_f64x2_zero( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> zeroinitializer, <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2465,9 +2473,10 @@ v128_t test_u32x4_trunc_sat_f64x2_zero(v128_t a) { // CHECK-LABEL: @test_f32x4_demote_f64x2_zero( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <2 x double> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.wasm.demote.zero(<2 x double> [[TMP0]]) #[[ATTR10]] -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x float> [[TMP1]] to <4 x i32> -// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> [[TMP0]], <2 x double> zeroinitializer, <4 x i32> +// CHECK-NEXT: [[CONV_I:%.*]] = fptrunc <4 x double> [[SHUFFLE_I]] to <4 x float> +// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x float> [[CONV_I]] to <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] // v128_t test_f32x4_demote_f64x2_zero(v128_t a) { return wasm_f32x4_demote_f64x2_zero(a); @@ -2537,7 +2546,7 @@ v128_t test_i64x2_shuffle(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.swizzle(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.swizzle(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2549,7 +2558,7 @@ v128_t test_i8x16_swizzle(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.narrow.signed.v16i8.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.narrow.signed.v16i8.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2561,7 +2570,7 @@ v128_t test_i8x16_narrow_i16x8(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.narrow.unsigned.v16i8.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.wasm.narrow.unsigned.v16i8.v8i16(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2571,7 +2580,7 @@ v128_t test_u8x16_narrow_i16x8(v128_t a, v128_t b) { // CHECK-LABEL: @test_i16x8_narrow_i32x4( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.wasm.narrow.signed.v8i16.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.wasm.narrow.signed.v8i16.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[TMP0]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP1]] // @@ -2581,7 +2590,7 @@ v128_t test_i16x8_narrow_i32x4(v128_t a, v128_t b) { // CHECK-LABEL: @test_u16x8_narrow_i32x4( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.wasm.narrow.unsigned.v8i16.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.wasm.narrow.unsigned.v8i16.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[TMP0]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP1]] // @@ -2728,7 +2737,7 @@ v128_t test_u64x2_extend_high_u32x4(v128_t a) { // CHECK-LABEL: @test_i16x8_extadd_pairwise_i8x16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.wasm.extadd.pairwise.signed.v8i16(<16 x i8> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.wasm.extadd.pairwise.signed.v8i16(<16 x i8> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i16> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2739,7 +2748,7 @@ v128_t test_i16x8_extadd_pairwise_i8x16(v128_t a) { // CHECK-LABEL: @test_u16x8_extadd_pairwise_u8x16( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.wasm.extadd.pairwise.unsigned.v8i16(<16 x i8> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i16> @llvm.wasm.extadd.pairwise.unsigned.v8i16(<16 x i8> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i16> [[TMP1]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP2]] // @@ -2750,7 +2759,7 @@ v128_t test_u16x8_extadd_pairwise_u8x16(v128_t a) { // CHECK-LABEL: @test_i32x4_extadd_pairwise_i16x8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.wasm.extadd.pairwise.signed.v4i32(<8 x i16> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.wasm.extadd.pairwise.signed.v4i32(<8 x i16> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP1]] // v128_t test_i32x4_extadd_pairwise_i16x8(v128_t a) { @@ -2760,7 +2769,7 @@ v128_t test_i32x4_extadd_pairwise_i16x8(v128_t a) { // CHECK-LABEL: @test_u32x4_extadd_pairwise_u16x8( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.wasm.extadd.pairwise.unsigned.v4i32(<8 x i16> [[TMP0]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i32> @llvm.wasm.extadd.pairwise.unsigned.v4i32(<8 x i16> [[TMP0]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP1]] // v128_t test_u32x4_extadd_pairwise_u16x8(v128_t a) { @@ -2771,7 +2780,7 @@ v128_t test_u32x4_extadd_pairwise_u16x8(v128_t a) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.low.signed.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.low.signed.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2783,7 +2792,7 @@ v128_t test_i16x8_extmul_low_i8x16(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.high.signed.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.high.signed.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2795,7 +2804,7 @@ v128_t test_i16x8_extmul_high_i8x16(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.low.unsigned.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.low.unsigned.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2807,7 +2816,7 @@ v128_t test_u16x8_extmul_low_u8x16(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.high.unsigned.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.extmul.high.unsigned.v8i16(<16 x i8> [[TMP0]], <16 x i8> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // @@ -2819,7 +2828,7 @@ v128_t test_u16x8_extmul_high_u8x16(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.low.signed.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.low.signed.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_i32x4_extmul_low_i16x8(v128_t a, v128_t b) { @@ -2830,7 +2839,7 @@ v128_t test_i32x4_extmul_low_i16x8(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.high.signed.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.high.signed.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_i32x4_extmul_high_i16x8(v128_t a, v128_t b) { @@ -2841,7 +2850,7 @@ v128_t test_i32x4_extmul_high_i16x8(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.low.unsigned.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.low.unsigned.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_u32x4_extmul_low_u16x8(v128_t a, v128_t b) { @@ -2852,7 +2861,7 @@ v128_t test_u32x4_extmul_low_u16x8(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.high.unsigned.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.wasm.extmul.high.unsigned.v4i32(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: ret <4 x i32> [[TMP2]] // v128_t test_u32x4_extmul_high_u16x8(v128_t a, v128_t b) { @@ -2861,7 +2870,7 @@ v128_t test_u32x4_extmul_high_u16x8(v128_t a, v128_t b) { // CHECK-LABEL: @test_i64x2_extmul_low_i32x4( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.low.signed.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.low.signed.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP1]] // @@ -2871,7 +2880,7 @@ v128_t test_i64x2_extmul_low_i32x4(v128_t a, v128_t b) { // CHECK-LABEL: @test_i64x2_extmul_high_i32x4( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.high.signed.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.high.signed.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP1]] // @@ -2881,7 +2890,7 @@ v128_t test_i64x2_extmul_high_i32x4(v128_t a, v128_t b) { // CHECK-LABEL: @test_u64x2_extmul_low_u32x4( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.low.unsigned.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.low.unsigned.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP1]] // @@ -2891,7 +2900,7 @@ v128_t test_u64x2_extmul_low_u32x4(v128_t a, v128_t b) { // CHECK-LABEL: @test_u64x2_extmul_high_u32x4( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.high.unsigned.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP0:%.*]] = tail call <2 x i64> @llvm.wasm.extmul.high.unsigned.v2i64(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR6]] // CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[TMP0]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP1]] // @@ -2903,7 +2912,7 @@ v128_t test_u64x2_extmul_high_u32x4(v128_t a, v128_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <8 x i16> // CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B:%.*]] to <8 x i16> -// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.q15mulr.sat.signed(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR10]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.wasm.q15mulr.sat.signed(<8 x i16> [[TMP0]], <8 x i16> [[TMP1]]) #[[ATTR6]] // CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i16> [[TMP2]] to <4 x i32> // CHECK-NEXT: ret <4 x i32> [[TMP3]] // diff --git a/clang/test/Layout/aix-bitfield-alignment.c b/clang/test/Layout/aix-bitfield-alignment.c index a736695cc6030..d47b3d7a0c7d8 100644 --- a/clang/test/Layout/aix-bitfield-alignment.c +++ b/clang/test/Layout/aix-bitfield-alignment.c @@ -232,3 +232,37 @@ int s = sizeof(G); // CHECK-NEXT: 0 | struct G // CHECK-NEXT: 0:0-44 | long long ll // CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8 + +#pragma align(packed) +struct H { + char c; + int : 0; + int i; +} H; +#pragma align(reset) + +int h = sizeof(H); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct H +// CHECK-NEXT: 0 | char c +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: 4 | int i +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1 + +#pragma pack(2) +struct I { + char c; + int : 0; + int i; +} I; +#pragma pack(pop) + +int i = sizeof(I); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct I +// CHECK-NEXT: 0 | char c +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: 4 | int i +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2 diff --git a/clang/test/Layout/aix-packed-bitfields.c b/clang/test/Layout/aix-packed-bitfields.c new file mode 100644 index 0000000000000..9bc907af0f596 --- /dev/null +++ b/clang/test/Layout/aix-packed-bitfields.c @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s + +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s +// +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s +// +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s + +struct A { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; + +int a = sizeof(struct A); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct A +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 4:0-29 | int a2 +// CHECK-NEXT: 8:0-3 | int a3 +// CHECK-NEXT: sizeof=12, {{(dsize=12, )?}}align=4, preferredalign=4 + +#pragma align(packed) +struct AlignPacked { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; +#pragma align(reset) + +int b = sizeof(struct AlignPacked); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct AlignPacked +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 3:6-35 | int a2 +// CHECK-NEXT: 7:4-7 | int a3 +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1 + +#pragma pack(1) +struct Pack1 { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; +#pragma pack(pop) + +int c = sizeof(struct Pack1); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct Pack1 +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 3:6-35 | int a2 +// CHECK-NEXT: 7:4-7 | int a3 +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1 + +#pragma pack(2) +struct Pack2 { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; +#pragma pack(pop) + +int d = sizeof(struct Pack2); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct Pack2 +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 3:6-35 | int a2 +// CHECK-NEXT: 7:4-7 | int a3 +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2 diff --git a/clang/test/Misc/opencl-c-3.0.incorrect_options.cl b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl index 493c5fde10541..07151d9a08c81 100644 --- a/clang/test/Misc/opencl-c-3.0.incorrect_options.cl +++ b/clang/test/Misc/opencl-c-3.0.incorrect_options.cl @@ -1,4 +1,6 @@ -// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=-__opencl_c_fp64,+cl_khr_fp64 %s 2>&1 | FileCheck %s -// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=-__opencl_c_fp64,+cl_khr_fp64 %s 2>&1 | FileCheck -check-prefix=CHECK-FP64 %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_fp64,-cl_khr_fp64 %s 2>&1 | FileCheck -check-prefix=CHECK-FP64 %s +// RUN: not %clang_cc1 -cl-std=CL3.0 -triple spir-unknown-unknown -cl-ext=+__opencl_c_read_write_images,-__opencl_c_images %s 2>&1 | FileCheck -check-prefix=CHECK-READ-WRITE-IMAGES %s -// CHECK: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values +// CHECK-FP64: error: options cl_khr_fp64 and __opencl_c_fp64 are set to different values +// CHECK-READ-WRITE-IMAGES: error: feature __opencl_c_read_write_images requires support of __opencl_c_images feature diff --git a/clang/test/OpenMP/allocate_codegen_attr.cpp b/clang/test/OpenMP/allocate_codegen_attr.cpp new file mode 100644 index 0000000000000..0ef5c77a2738f --- /dev/null +++ b/clang/test/OpenMP/allocate_codegen_attr.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// SIMD-ONLY0-NOT: {{__kmpc|__tgt}} +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +enum omp_allocator_handle_t { + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + KMP_ALLOCATOR_MAX_HANDLE = __UINTPTR_MAX__ +}; + +struct St{ + int a; +}; + +struct St1{ + int a; + static int b; + [[omp::directive(allocate(b) allocator(omp_default_mem_alloc))]]; +} d; + +int a, b, c; +[[omp::directive(allocate(a) allocator(omp_large_cap_mem_alloc)), + directive(allocate(b) allocator(omp_const_mem_alloc)), + directive(allocate(d, c) allocator(omp_high_bw_mem_alloc))]]; + +template +struct ST { + static T m; + [[omp::directive(allocate(m) allocator(omp_low_lat_mem_alloc))]]; +}; + +template T foo() { + T v; + [[omp::directive(allocate(v) allocator(omp_cgroup_mem_alloc))]]; + v = ST::m; + return v; +} + +namespace ns{ + int a; +} +[[omp::directive(allocate(ns::a) allocator(omp_pteam_mem_alloc))]]; + +// CHECK-NOT: call {{.+}} {{__kmpc_alloc|__kmpc_free}} + +// CHECK-LABEL: @main +int main () { + static int a; + [[omp::directive(allocate(a) allocator(omp_thread_mem_alloc))]]; + a=2; + // CHECK-NOT: {{__kmpc_alloc|__kmpc_free}} + // CHECK: alloca double, + // CHECK-NOT: {{__kmpc_alloc|__kmpc_free}} + double b = 3; + [[omp::directive(allocate(b))]]; + return (foo()); +} + +// CHECK: define {{.*}}i32 @{{.+}}foo{{.+}}() +// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{.+}}) +// CHECK-NEXT: [[V_VOID_ADDR:%.+]] = call i8* @__kmpc_alloc(i32 [[GTID]], i64 4, i8* inttoptr (i64 6 to i8*)) +// CHECK-NEXT: [[V_ADDR:%.+]] = bitcast i8* [[V_VOID_ADDR]] to i32* +// CHECK-NOT: {{__kmpc_alloc|__kmpc_free}} +// CHECK: store i32 %{{.+}}, i32* [[V_ADDR]], +// CHECK-NEXT: [[V_VAL:%.+]] = load i32, i32* [[V_ADDR]], +// CHECK-NEXT: [[V_VOID_ADDR:%.+]] = bitcast i32* [[V_ADDR]] to i8* +// CHECK-NEXT: call void @__kmpc_free(i32 [[GTID]], i8* [[V_VOID_ADDR]], i8* inttoptr (i64 6 to i8*)) +// CHECK-NOT: {{__kmpc_alloc|__kmpc_free}} +// CHECK: ret i32 [[V_VAL]] + +// CHECK-NOT: call {{.+}} {{__kmpc_alloc|__kmpc_free}} +extern template int ST::m; + +// CHECK: define{{.*}} void @{{.+}}bar{{.+}}(i32 %{{.+}}, float* {{.+}}) +void bar(int a, float &z) { +// CHECK: [[A_VOID_PTR:%.+]] = call i8* @__kmpc_alloc(i32 [[GTID:%.+]], i64 4, i8* inttoptr (i64 1 to i8*)) +// CHECK: [[A_ADDR:%.+]] = bitcast i8* [[A_VOID_PTR]] to i32* +// CHECK: store i32 %{{.+}}, i32* [[A_ADDR]], +// CHECK: [[Z_VOID_PTR:%.+]] = call i8* @__kmpc_alloc(i32 [[GTID]], i64 8, i8* inttoptr (i64 1 to i8*)) +// CHECK: [[Z_ADDR:%.+]] = bitcast i8* [[Z_VOID_PTR]] to float** +// CHECK: store float* %{{.+}}, float** [[Z_ADDR]], +[[omp::directive(allocate(a,z) allocator(omp_default_mem_alloc))]]; +// CHECK-NEXT: [[Z_VOID_PTR:%.+]] = bitcast float** [[Z_ADDR]] to i8* +// CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[Z_VOID_PTR]], i8* inttoptr (i64 1 to i8*)) +// CHECK-NEXT: [[A_VOID_PTR:%.+]] = bitcast i32* [[A_ADDR]] to i8* +// CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[A_VOID_PTR]], i8* inttoptr (i64 1 to i8*)) +// CHECK: ret void +} +#endif + diff --git a/clang/test/OpenMP/assumes_messages_attr.c b/clang/test/OpenMP/assumes_messages_attr.c new file mode 100644 index 0000000000000..bd06e85cbf3b5 --- /dev/null +++ b/clang/test/OpenMP/assumes_messages_attr.c @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -fopenmp-version=51 -std=c99 -fms-extensions -fdouble-square-bracket-attributes -Wno-pragma-pack %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -fopenmp-version=51 -std=c99 -fms-extensions -fdouble-square-bracket-attributes -Wno-pragma-pack %s + +[[omp::directive(assumes)]]; // expected-error {{expected at least one 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism' clause for '#pragma omp assumes'}} +[[omp::directive(begin)]]; // expected-error {{expected an OpenMP directive}} +[[omp::directive(begin assumes)]]; // expected-error {{expected at least one 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism' clause for '#pragma omp begin assumes'}} +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes foobar)]]; // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(begin assumes foobar)]]; // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(end assumes)]]; + +[[omp::directive(begin assumes foobar(foo 2 baz))]]; // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(assumes foobar(foo 2 baz))]]; // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes no_openmp(1))]]; // expected-warning {{'no_openmp' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(begin assumes no_openmp(1 2 3))]]; // expected-warning {{'no_openmp' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(end assumes no_openmp(1))]]; + +[[omp::directive(assumes foobar no_openmp bazbaz)]]; // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(begin assumes foobar no_openmp bazbaz)]]; // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(end assumes)]]; + +[[omp::directive(begin assumes foobar(foo 2 baz) no_openmp bazbaz(foo 2 baz))]]; // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(assumes foobar(foo 2 baz) no_openmp bazbaz(foo 2 baz))]]; // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes no_openmp foobar no_openmp)]]; // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(begin assumes no_openmp foobar no_openmp)]]; // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes holds(1, 2 3))]]; +[[omp::directive(begin assumes holds(1, 2 3))]]; +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes absent(1, 2 3))]]; +[[omp::directive(begin assumes absent(1, 2 3))]]; +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes contains(1, 2 3))]]; +[[omp::directive(begin assumes contains(1, 2 3))]]; +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes ext)]]; // expected-warning {{valid assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(begin assumes ext)]]; // expected-warning {{valid begin assumes clauses start with 'ext_', 'absent', 'contains', 'holds', 'no_openmp', 'no_openmp_routines', 'no_parallelism'; token will be ignored}} +[[omp::directive(end assumes)]]; + +[[omp::directive(assumes ext_123(not allowed))]]; // expected-warning {{'ext_123' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(begin assumes ext_123(not allowed))]]; // expected-warning {{'ext_123' clause should not be followed by arguments; tokens will be ignored}} expected-note {{the ignored tokens spans until here}} +[[omp::directive(end assumes)]]; + +[[omp::directive(end assumes)]]; // expected-error {{'#pragma omp end assumes' with no matching '#pragma omp begin assumes'}} + +// TODO: we should emit a warning at least. +[[omp::directive(begin assumes ext_abc)]]; + diff --git a/clang/test/OpenMP/critical_codegen_attr.cpp b/clang/test/OpenMP/critical_codegen_attr.cpp new file mode 100644 index 0000000000000..e3890ff6058cc --- /dev/null +++ b/clang/test/OpenMP/critical_codegen_attr.cpp @@ -0,0 +1,130 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefixes=ALL,NORMAL +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefixes=ALL,NORMAL +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fopenmp-version=51 -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -fopenmp-enable-irbuilder -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefixes=ALL,IRBUILDER +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fopenmp-enable-irbuilder -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fopenmp-enable-irbuilder -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefixes=ALL,IRBUILDER + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fopenmp-version=51 -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// SIMD-ONLY0-NOT: {{__kmpc|__tgt}} +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +// ALL: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* } +// ALL: [[UNNAMED_LOCK:@.+]] = common global [8 x i32] zeroinitializer +// ALL: [[THE_NAME_LOCK:@.+]] = common global [8 x i32] zeroinitializer +// ALL: [[THE_NAME_LOCK1:@.+]] = common global [8 x i32] zeroinitializer + +// ALL: define {{.*}}void [[FOO:@.+]]() + +void foo() { extern void mayThrow(); mayThrow(); } + +// ALL-LABEL: @main +// TERM_DEBUG-LABEL: @main +int main() { + // ALL: [[A_ADDR:%.+]] = alloca i8 + char a; + +// ALL: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]]) +// ALL: call {{.*}}void @__kmpc_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[UNNAMED_LOCK]]) +// ALL-NEXT: store i8 2, i8* [[A_ADDR]] +// ALL-NEXT: call {{.*}}void @__kmpc_end_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[UNNAMED_LOCK]]) + [[omp::directive(critical)]] + a = 2; +// IRBUILDER: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]]) +// ALL: call {{.*}}void @__kmpc_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK]]) +// IRBUILDER-NEXT: call {{.*}}void [[FOO]]() +// NORMAL-NEXT: invoke {{.*}}void [[FOO]]() +// ALL: call {{.*}}void @__kmpc_end_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK]]) + [[omp::directive(critical(the_name))]] + foo(); +// IRBUILDER: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]]) +// ALL: call {{.*}}void @__kmpc_critical_with_hint([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK1]], i{{64|32}} 23) +// IRBUILDER-NEXT: call {{.*}}void [[FOO]]() +// NORMAL-NEXT: invoke {{.*}}void [[FOO]]() +// ALL: call {{.*}}void @__kmpc_end_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK1]]) + [[omp::directive(critical(the_name1) hint(23))]] + foo(); + // IRBUILDER: [[GTID:%.+]] = call {{.*}}i32 @__kmpc_global_thread_num([[IDENT_T_TY]]* [[DEFAULT_LOC:@.+]]) + // ALL: call {{.*}}void @__kmpc_critical([[IDENT_T_TY]]* [[DEFAULT_LOC]], i32 [[GTID]], [8 x i32]* [[THE_NAME_LOCK]]) + // ALL: br label + // ALL-NOT: call {{.*}}void @__kmpc_end_critical( + // ALL: br label + // ALL-NOT: call {{.*}}void @__kmpc_end_critical( + // NORMAL: br label + if (a) + [[omp::directive(critical(the_name))]] + while (1) + ; + // ALL: call {{.*}}void [[FOO]]() + foo(); + // ALL-NOT: call void @__kmpc_critical + // ALL-NOT: call void @__kmpc_end_critical + return a; +} + +// ALL-LABEL: lambda_critical +// TERM_DEBUG-LABEL: lambda_critical +void lambda_critical(int a, int b) { + auto l = [=]() { + [[omp::directive(critical)]] + { + // ALL: call void @__kmpc_critical( + int c = a + b; + } + }; + + l(); + + auto l1 = [=]() { + [[omp::sequence(directive(parallel), directive(critical))]] + { + // ALL: call void @__kmpc_critical( + int c = a + b; + } + }; + + l1(); +} + +struct S { + int a; +}; +// ALL-LABEL: critical_ref +void critical_ref(S &s) { + // ALL: [[S_ADDR:%.+]] = alloca %struct.S*, + // ALL: [[S_REF:%.+]] = load %struct.S*, %struct.S** [[S_ADDR]], + // ALL: [[S_A_REF:%.+]] = getelementptr inbounds %struct.S, %struct.S* [[S_REF]], i32 0, i32 0 + ++s.a; + // ALL: call void @__kmpc_critical( + [[omp::directive(critical)]] + // ALL: [[S_REF:%.+]] = load %struct.S*, %struct.S** [[S_ADDR]], + // ALL: [[S_A_REF:%.+]] = getelementptr inbounds %struct.S, %struct.S* [[S_REF]], i32 0, i32 0 + ++s.a; + // ALL: call void @__kmpc_end_critical( +} + +// ALL-LABEL: parallel_critical +// TERM_DEBUG-LABEL: parallel_critical +void parallel_critical() { + [[omp::sequence(directive(parallel), directive(critical))]] + // TERM_DEBUG-NOT: __kmpc_global_thread_num + // TERM_DEBUG: call void @__kmpc_critical({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] + // TERM_DEBUG: invoke void {{.*}}foo{{.*}}() + // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], + // TERM_DEBUG-NOT: __kmpc_global_thread_num + // TERM_DEBUG: call void @__kmpc_end_critical({{.+}}), !dbg [[DBG_LOC_END:![0-9]+]] + // TERM_DEBUG: [[TERM_LPAD]] + // TERM_DEBUG: call void @__clang_call_terminate + // TERM_DEBUG: unreachable + foo(); +} +// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-12]], +// TERM_DEBUG-DAG: [[DBG_LOC_END]] = !DILocation(line: [[@LINE-3]], +#endif + diff --git a/clang/test/OpenMP/masked_messages_attr.cpp b/clang/test/OpenMP/masked_messages_attr.cpp new file mode 100644 index 0000000000000..37252930b1f0f --- /dev/null +++ b/clang/test/OpenMP/masked_messages_attr.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 %s -Wuninitialized + +void xxx(int argc) { + int x; // expected-note {{initialize the variable 'x' to silence this warning}} + [[omp::directive(masked)]] + argc = x; // expected-warning {{variable 'x' is uninitialized when used here}} +} + +void yyy(int argc) { + int x; // expected-note {{initialize the variable 'x' to silence this warning}} + [[omp::directive(masked filter(1))]] + argc = x; // expected-warning {{variable 'x' is uninitialized when used here}} +} + +int foo(); + +int main() { + [[omp::directive(masked)]] + ; + [[omp::directive(masked filter(1) filter(2))]] // expected-error {{directive '#pragma omp masked' cannot contain more than one 'filter' clause}} + ; + int x,y,z; + [[omp::directive(masked filter(x) filter(y) filter(z))]] // expected-error 2 {{directive '#pragma omp masked' cannot contain more than one 'filter' clause}} + ; + [[omp::directive(masked nowait)]] // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp masked'}} + [[omp::directive(masked unknown)]] // expected-warning {{extra tokens at the end of '#pragma omp masked' are ignored}} + foo(); + { + [[omp::directive(masked)]] + } // expected-error {{expected statement}} + { + [[omp::directive(masked filter(2))]] + } // expected-error {{expected statement}} + [[omp::directive(for)]] + for (int i = 0; i < 10; ++i) { + foo(); + [[omp::directive(masked filter(1))]] // expected-error {{region cannot be closely nested inside 'for' region}} + foo(); + } + [[omp::directive(sections)]] + { + foo(); + [[omp::directive(masked)]] // expected-error {{region cannot be closely nested inside 'sections' region}} + foo(); + } + [[omp::directive(single)]] + for (int i = 0; i < 10; ++i) { + foo(); + [[omp::directive(masked allocate(i))]] // expected-error {{region cannot be closely nested inside 'single' region}} expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp masked'}} + foo(); + } + [[omp::directive(masked)]] + for (int i = 0; i < 10; ++i) { + foo(); + [[omp::directive(masked)]] + foo(); + } + [[omp::directive(for ordered)]] + for (int i = 0; i < 10; ++i) + [[omp::directive(masked)]] // expected-error {{region cannot be closely nested inside 'for' region}} + { + foo(); + } + + return 0; +} + +int foo() { + L1: // expected-note {{jump exits scope of OpenMP structured block}} + foo(); + [[omp::directive(masked filter(0))]] + { + foo(); + goto L1; // expected-error {{cannot jump from this goto statement to its label}} + } + goto L2; // expected-error {{cannot jump from this goto statement to its label}} + [[omp::directive(masked filter(-2))]] + { // expected-note {{jump bypasses OpenMP structured block}} + L2: + foo(); + } + + return 0; +} + diff --git a/clang/test/OpenMP/openmp_attribute.cpp b/clang/test/OpenMP/openmp_attribute.cpp new file mode 100644 index 0000000000000..5b6f64e6a2073 --- /dev/null +++ b/clang/test/OpenMP/openmp_attribute.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fsyntax-only -verify -DSUPPORTED=1 %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fsyntax-only -verify -DSUPPORTED=1 -x c -std=c2x %s +// RUN: %clang_cc1 -fsyntax-only -verify -DSUPPORTED=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -DSUPPORTED=0 -x c -std=c2x %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify -DSUPPORTED=1 %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify -DSUPPORTED=1 -x c -std=c2x %s +// expected-no-diagnostics + +#ifndef SUPPORTED +#error "Someone messed up a RUN line" +#endif + +#ifdef __cplusplus +#if __has_cpp_attribute(omp::sequence) != SUPPORTED +#error "No idea what you're talking about" +#endif + +#if __has_cpp_attribute(omp::directive) != SUPPORTED +#error "No idea what you're talking about" +#endif + +#if __has_cpp_attribute(omp::totally_bogus) +#error "No idea what you're talking about" +#endif + +#else // __cplusplus + +#if __has_c_attribute(omp::sequence) != SUPPORTED +#error "No idea what you're talking about" +#endif + +#if __has_c_attribute(omp::directive) != SUPPORTED +#error "No idea what you're talking about" +#endif + +#if __has_c_attribute(omp::totally_bogus) +#error "No idea what you're talking about" +#endif + +#endif + diff --git a/clang/test/OpenMP/openmp_attribute_compat.cpp b/clang/test/OpenMP/openmp_attribute_compat.cpp new file mode 100644 index 0000000000000..5f51e30102de1 --- /dev/null +++ b/clang/test/OpenMP/openmp_attribute_compat.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fsyntax-only -verify=pre -Wpre-openmp-51-compat %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fsyntax-only -verify=off %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=ext -Wopenmp %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=ext -Wopenmp-51-extensions %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=ext -Wall %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=ext %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=off -Wno-openmp %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=off -Wno-openmp-51-extensions %s + +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fsyntax-only -verify=pre -Wpre-openmp-51-compat -x c -fdouble-square-bracket-attributes %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -fsyntax-only -verify=off -x c -std=c2x %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fsyntax-only -verify=ext -Wopenmp -x c -std=c2x %s + +// off-no-diagnostics + +int x; +[[omp::directive(threadprivate(x))]]; // pre-warning {{specifying OpenMP directives with [[]] is incompatible with OpenMP standards before OpenMP 5.1}} \ + // ext-warning {{specifying OpenMP directives with [[]] is an OpenMP 5.1 extension}} + diff --git a/clang/test/OpenMP/openmp_attribute_parsing.cpp b/clang/test/OpenMP/openmp_attribute_parsing.cpp new file mode 100644 index 0000000000000..4d2c84cd323a5 --- /dev/null +++ b/clang/test/OpenMP/openmp_attribute_parsing.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -std=c++17 -fopenmp -fopenmp-version=51 -fsyntax-only -verify %s + +// This file tests the custom parsing logic for the OpenMP 5.1 attribute +// syntax. It does not test actual OpenMP directive syntax, just the attribute +// parsing bits. + +// FIXME: the diagnostic here is a bit unsatisfying. We handle the custom omp +// attribute parsing logic when parsing the attribute argument list, and we +// only process an attribute argument list when we see an open paren after the +// attribute name. So this means we never hit the omp-specific parsing and +// instead handle this through the usual Sema attribute handling in +// SemaDeclAttr.cpp, which diagnoses this as an unknown attribute. +[[omp::directive]]; // expected-warning {{unknown attribute 'directive' ignored}} +[[omp::sequence]]; // expected-warning {{unknown attribute 'sequence' ignored}} +[[omp::unknown]]; // expected-warning {{unknown attribute 'unknown' ignored}} + +[[omp::directive()]]; // expected-error {{expected an OpenMP directive}} +[[omp::sequence()]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} + +// Both sequence and directive require an argument list, test that we diagnose +// when the inner directive or sequence is missing its argument list. +[[omp::sequence(directive)]]; // expected-error {{expected '('}} +[[omp::sequence(sequence)]]; // expected-error {{expected '('}} +[[omp::sequence(omp::directive)]]; // expected-error {{expected '('}} +[[omp::sequence(omp::sequence)]]; // expected-error {{expected '('}} + +// All of the diagnostics here come from the inner sequence and directive not +// being given an argument, but this tests that we can parse either with or +// without the 'omp::'. +[[omp::sequence(directive(), sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[omp::sequence(omp::directive(), sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[omp::sequence(directive(), omp::sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[omp::sequence(omp::directive(), omp::sequence())]]; // expected-error {{expected an OpenMP directive}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} + +// Test that we properly diagnose missing parens within the inner arguments of +// a sequence attribute. +[[omp::sequence( // expected-note {{to match this '('}} + directive( +)]]; // expected-error {{expected ')'}} expected-error {{expected an OpenMP directive}} +[[omp::sequence( // expected-note {{to match this '('}} + sequence( +)]]; // expected-error {{expected ')'}} expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} + +// Test that we properly handle the using attribute syntax. +[[using omp: directive()]]; // expected-error {{expected an OpenMP directive}} +[[using omp: sequence()]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[using omp: sequence(omp::directive())]]; // expected-error {{expected an OpenMP directive}} +[[using omp: sequence(directive())]]; // expected-error {{expected an OpenMP directive}} + +// Test that we give a sensible error on an unknown attribute in the omp +// namespace that has an argument list. +[[omp::unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}} +[[using omp: unknown()]]; // expected-warning {{unknown attribute 'unknown' ignored}} + +// Test that unknown arguments to the omp::sequence are rejected, regardless of +// what level they're at. +[[omp::sequence(unknown)]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[omp::sequence(sequence(unknown))]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[omp::sequence(omp::unknown)]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} +[[omp::sequence(sequence(omp::unknown))]]; // expected-error {{expected an OpenMP 'directive' or 'sequence' attribute argument}} + +// FIXME: combining non-openmp attributes with openmp attributes has surprising +// results due to the replay of tokens. We properly parse the non-openmp +// attributes, but we also replay the OpenMP tokens. The attributes then get +// passed to the OpenMP parsing functions and it does not attach the attribute +// to the declaration statement AST node as you might expect. This means that +// the expected diagnostics are not issued. Thankfully, due to the positioning +// of OpenMP attributes and what they appertain to, this should not be a +// frequent issue (hopefully). +int x; +[[deprecated, omp::directive(threadprivate(x))]] int y; // FIXME-expected-note {{'y' has been explicitly marked deprecated here}} +[[omp::directive(threadprivate(x)), deprecated]] int z; // FIXME-expected-note {{'z' has been explicitly marked deprecated here}} +void test() { + x = 1; + y = 1; // FIXME-expected-warning {{warning: 'y' is deprecated}} + z = 1; // FIXME-expected-warning {{warning: 'z' is deprecated}} +} diff --git a/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c b/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c index b78919312087e..6168ec073acb0 100644 --- a/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c +++ b/clang/test/OpenMP/remarks_parallel_in_multiple_target_state_machines.c @@ -8,37 +8,28 @@ void baz(void) __attribute__((assume("omp_no_openmp"))); void bar1(void) { #pragma omp parallel // #0 - // all-remark@#0 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // safe-remark@#0 {{Parallel region is used in unknown ways; will not attempt to rewrite the state machine.}} - // force-remark@#0 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__2_wrapper, kernel ID: }} + // safe-remark@#0 {{Parallel region is used in unknown ways. Will not attempt to rewrite the state machine. [OMP101]}} { } } void bar2(void) { #pragma omp parallel // #1 - // all-remark@#1 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // safe-remark@#1 {{Parallel region is used in unknown ways; will not attempt to rewrite the state machine.}} - // force-remark@#1 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__6_wrapper, kernel ID: }} + // safe-remark@#1 {{Parallel region is used in unknown ways. Will not attempt to rewrite the state machine. [OMP101]}} { } } void foo1(void) { #pragma omp target teams // #2 - // all-remark@#2 {{Generic-mode kernel is executed with a customized state machine [3 known parallel regions] (good).}} - // all-remark@#2 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__1_wrapper, kernel ID: __omp_offloading}} - // all-remark@#2 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__2_wrapper, kernel ID: __omp_offloading}} + // all-remark@#2 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} + { - baz(); // all-remark {{Kernel will be executed in generic-mode due to this potential side-effect, consider to add `__attribute__((assume("ompx_spmd_amenable")))` to the called function '_Z3bazv'.}} + baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} #pragma omp parallel // #3 - // all-remark@#3 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // all-remark@#3 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__1_wrapper, kernel ID: __omp_offloading}} { } bar1(); #pragma omp parallel // #4 - // all-remark@#4 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // all-remark@#4 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__2_wrapper, kernel ID: __omp_offloading}} { } } @@ -46,21 +37,15 @@ void foo1(void) { void foo2(void) { #pragma omp target teams // #5 - // all-remark@#5 {{Generic-mode kernel is executed with a customized state machine [4 known parallel regions] (good).}} - // all-remark@#5 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__5_wrapper, kernel ID: __omp_offloading}} - // all-remark@#5 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__4_wrapper, kernel ID: __omp_offloading}} + // all-remark@#5 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // all-remark {{Kernel will be executed in generic-mode due to this potential side-effect, consider to add `__attribute__((assume("ompx_spmd_amenable")))` to the called function '_Z3bazv'.}} + baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} #pragma omp parallel // #6 - // all-remark@#6 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // all-remark@#6 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__4_wrapper, kernel ID: __omp_offloading}} { } bar1(); bar2(); #pragma omp parallel // #7 - // all-remark@#7 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // all-remark@#7 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__5_wrapper, kernel ID: __omp_offloading}} { } bar1(); @@ -70,21 +55,15 @@ void foo2(void) { void foo3(void) { #pragma omp target teams // #8 - // all-remark@#8 {{Generic-mode kernel is executed with a customized state machine [4 known parallel regions] (good).}} - // all-remark@#8 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__7_wrapper, kernel ID: __omp_offloading}} - // all-remark@#8 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__8_wrapper, kernel ID: __omp_offloading}} + // all-remark@#8 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // all-remark {{Kernel will be executed in generic-mode due to this potential side-effect, consider to add `__attribute__((assume("ompx_spmd_amenable")))` to the called function '_Z3bazv'.}} + baz(); // all-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} #pragma omp parallel // #9 - // all-remark@#9 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // all-remark@#9 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__7_wrapper, kernel ID: __omp_offloading}} { } bar1(); bar2(); #pragma omp parallel // #10 - // all-remark@#10 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} - // all-remark@#10 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__8_wrapper, kernel ID: __omp_offloading}} { } bar1(); @@ -104,5 +83,4 @@ void spmd(void) { } } -// all-remark@* 5 {{OpenMP runtime call __kmpc_global_thread_num moved to beginning of OpenMP region}} -// all-remark@* 9 {{OpenMP runtime call __kmpc_global_thread_num deduplicated}} +// all-remark@* 9 {{OpenMP runtime call __kmpc_global_thread_num deduplicated. [OMP170]}} diff --git a/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c b/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c index 2495f738bcedd..18a874e5628fa 100644 --- a/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c +++ b/clang/test/OpenMP/remarks_parallel_in_target_state_machine.c @@ -8,28 +8,21 @@ void baz(void) __attribute__((assume("omp_no_openmp"))); void bar(void) { #pragma omp parallel // #1 \ - // expected-remark@#1 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} \ - // expected-remark@#1 {{Parallel region is used in unknown ways; will not attempt to rewrite the state machine.}} + // expected-remark@#1 {{Parallel region is used in unknown ways. Will not attempt to rewrite the state machine. [OMP101]}} { } } void foo(void) { -#pragma omp target teams // #2 \ - // expected-remark@#2 {{Generic-mode kernel is executed with a customized state machine [3 known parallel regions] (good).}} - // expected-remark@#2 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__1_wrapper, kernel ID: __omp_offloading}} \ - // expected-remark@#2 {{Target region containing the parallel region that is specialized. (parallel region ID: __omp_outlined__2_wrapper, kernel ID: __omp_offloading}} +#pragma omp target teams // #2 + // expected-remark@#2 {{Rewriting generic-mode kernel with a customized state machine. [OMP131]}} { - baz(); // expected-remark {{Kernel will be executed in generic-mode due to this potential side-effect, consider to add `__attribute__((assume("ompx_spmd_amenable")))` to the called function '_Z3bazv'.}} -#pragma omp parallel // #3 \ - // expected-remark@#3 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} \ - // expected-remark@#3 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__1_wrapper, kernel ID: __omp_offloading}} + baz(); // expected-remark {{Value has potential side effects preventing SPMD-mode execution. Add `__attribute__((assume("ompx_spmd_amenable")))` to the called function to override. [OMP121]}} +#pragma omp parallel { } bar(); -#pragma omp parallel // #4 \ - // expected-remark@#4 {{Found a parallel region that is called in a target region but not part of a combined target construct nor nested inside a target construct without intermediate code. This can lead to excessive register usage for unrelated target regions in the same translation unit due to spurious call edges assumed by ptxas.}} \ - // expected-remark@#4 {{Specialize parallel region that is only reached from a single target region to avoid spurious call edges and excessive register usage in other target regions. (parallel region ID: __omp_outlined__2_wrapper, kernel ID: __omp_offloading}} +#pragma omp parallel { } } @@ -47,5 +40,4 @@ void spmd(void) { } } -// expected-remark@* {{OpenMP runtime call __kmpc_global_thread_num moved to beginning of OpenMP region}} -// expected-remark@* {{OpenMP runtime call __kmpc_global_thread_num deduplicated}} +// expected-remark@* {{OpenMP runtime call __kmpc_global_thread_num deduplicated. [OMP170]}} diff --git a/clang/test/OpenMP/target_map_names_attr.cpp b/clang/test/OpenMP/target_map_names_attr.cpp new file mode 100644 index 0000000000000..c45e7c8b996bb --- /dev/null +++ b/clang/test/OpenMP/target_map_names_attr.cpp @@ -0,0 +1,215 @@ +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s --check-prefix DEBUG +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix CHECK +#ifndef HEADER +#define HEADER + +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";d;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";i;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";i[1:23];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";p;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";p[1:24];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.i;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.s.f;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.p[:22];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.ps->s.i;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.ps->ps;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.ps->ps->ps;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.ps->ps->s.f[:22];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->i;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->s.f;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->p[:22];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->ps->s.i;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->ps->ps;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->ps->ps->ps;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->ps->ps->s.f[:22];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.f[:22];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.p[:33];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";ps->p[:33];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.s;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" + +struct S1 { + int i; + float f[50]; +}; + +struct S2 { + int i; + float f[50]; + S1 s; + double *p; + struct S2 *ps; +}; + +void foo() { + double d; + int i[100]; + float *p; + + S2 s; + S2 *ps; + + [[omp::directive(target map(d))]] + { } + [[omp::directive(target map(i))]] + { } + [[omp::directive(target map(i[1:23]))]] + { } + [[omp::directive(target map(p))]] + { } + [[omp::directive(target map(p[1:24]))]] + { } + [[omp::directive(target map(s))]] + { } + [[omp::directive(target map(s.i))]] + { } + [[omp::directive(target map(s.s.f))]] + { } + [[omp::directive(target map(s.p))]] + { } + [[omp::directive(target map(to: s.p[:22]))]] + { } + [[omp::directive(target map(s.ps))]] + { } + [[omp::directive(target map(from: s.ps->s.i))]] + { } + [[omp::directive(target map(to: s.ps->ps))]] + { } + [[omp::directive(target map(s.ps->ps->ps))]] + { } + [[omp::directive(target map(to: s.ps->ps->s.f[:22]))]] + { } + [[omp::directive(target map(ps))]] + { } + [[omp::directive(target map(ps->i))]] + { } + [[omp::directive(target map(ps->s.f))]] + { } + [[omp::directive(target map(from: ps->p))]] + { } + [[omp::directive(target map(to: ps->p[:22]))]] + { } + [[omp::directive(target map(ps->ps))]] + { } + [[omp::directive(target map(from: ps->ps->s.i))]] + { } + [[omp::directive(target map(from: ps->ps->ps))]] + { } + [[omp::directive(target map(ps->ps->ps->ps))]] + { } + [[omp::directive(target map(to: ps->ps->ps->s.f[:22]))]] + { } + [[omp::directive(target map(to: s.f[:22]) map(from: s.p[:33]))]] + { } + [[omp::directive(target map(from: s.f[:22]) map(to: ps->p[:33]))]] + { } + [[omp::directive(target map(from: s.f[:22], s.s) map(to: ps->p[:33]))]] + { } +} + +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";B;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";unknown;unknown;0;0;;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";A;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";x;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";fn;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" +// DEBUG: @{{.+}} = private constant [7 x i8*] [i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]+}} x i8], [{{[0-9]+}} x i8]* @{{[0-9]+}}, i32 0, i32 0)] + +void bar(int N) { + double B[10]; + double A[N]; + double x; + S1 s; + auto fn = [&x]() { return x; }; + [[omp::directive(target)]] + { + (void)B; + (void)A; + (void)fn(); + (void)s.f; + } +} + +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";t;{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" + +[[omp::directive(declare target)]]; +double t; +[[omp::directive(end declare target)]]; + +void baz() { + [[omp::directive(target map(to:t))]] + { } + [[omp::directive(target map(to:t) nowait)]] + { } + [[omp::directive(target teams map(to:t))]] + { } + [[omp::directive(target teams map(to:t) nowait)]] + { } + [[omp::directive(target data map(to:t))]] + { } + [[omp::sequence(directive(target enter data map(to:t)), + directive(target enter data map(to:t) nowait), + directive(target exit data map(from:t)), + directive(target exit data map(from:t) nowait), + directive(target update from(t)), + directive(target update to(t)), + directive(target update from(t) nowait), + directive(target update to(t) nowait))]]; +} + +struct S3 { + double Z[64]; +}; + +[[omp::directive(declare mapper(id: S3 s) map(s.Z[0:64]))]] +void qux() { + S3 s; + [[omp::directive(target map(mapper(id), to:s))]] + { } +} + +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";s.Z[0:64];{{.*}}.cpp;{{[0-9]+}};{{[0-9]+}};;\00" + +// Clang used to mistakenly generate the map name "x" for both x and y on this +// directive. Conditions to reproduce the bug: a single map clause has two +// variables, and at least the second is used in the associated statement. +// +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";x;{{.*}}.cpp;[[@LINE+3]];7;;\00" +// DEBUG: @{{[0-9]+}} = private unnamed_addr constant [{{[0-9]+}} x i8] c";y;{{.*}}.cpp;[[@LINE+2]];10;;\00" +void secondMapNameInClause() { + int x, y; + [[omp::directive(target map(to: x, y))]]; + x = y = 1; +} + +// DEBUG: %{{.+}} = call i32 @__tgt_target_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: %{{.+}} = call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}, i32 {{.+}}, i32 {{.+}}) +// DEBUG: call void @__tgt_target_data_begin_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: call void @__tgt_target_data_end_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: call void @__tgt_target_data_update_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: %{{.+}} = call i32 @__tgt_target_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* %{{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: %{{.+}} = call i32 @__tgt_target_teams_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}, i32 {{.+}}, i32 {{.+}}) +// DEBUG: call void @__tgt_target_data_begin_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: call void @__tgt_target_data_end_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) +// DEBUG: call void @__tgt_target_data_update_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** getelementptr inbounds ([{{[0-9]+}} x i8*], [{{[0-9]+}} x i8*]* @.offload_mapnames{{.*}}, i32 0, i32 0), i8** {{.+}}) + +// CHECK: %{{.+}} = call i32 @__tgt_target_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: %{{.+}} = call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}, i32 {{.+}}, i32 {{.+}}) +// CHECK: call void @__tgt_target_data_begin_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: call void @__tgt_target_data_end_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: call void @__tgt_target_data_update_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: %{{.+}} = call i32 @__tgt_target_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* %{{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: %{{.+}} = call i32 @__tgt_target_teams_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}, i32 {{.+}}, i32 {{.+}}) +// CHECK: call void @__tgt_target_data_begin_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: call void @__tgt_target_data_end_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) +// CHECK: call void @__tgt_target_data_update_nowait_mapper(%struct.ident_t* @{{.+}}, i64 -1, i32 1, i8** %{{.+}}, i8** %{{.+}}, i64* {{.+}}, i64* {{.+}}, i8** null, i8** {{.+}}) + + +// DEBUG: void @.omp_mapper._ZTS2S3.id(i8* {{.*}}, i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i64 {{.*}}, i8* [[NAME_ARG:%.+]]) +// DEBUG: store i8* [[NAME_ARG]], i8** [[NAME_STACK:%.+]] +// DEBUG: [[MAPPER_NAME:%.+]] = load i8*, i8** [[NAME_STACK]] +// DEBUG: call void @__tgt_push_mapper_component(i8* %{{.*}}, i8* %{{.*}}, i8* %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i8* [[MAPPER_NAME]]) + +#endif + diff --git a/clang/test/OpenMP/taskloop_reduction_messages_attr.cpp b/clang/test/OpenMP/taskloop_reduction_messages_attr.cpp new file mode 100644 index 0000000000000..3dc2258620004 --- /dev/null +++ b/clang/test/OpenMP/taskloop_reduction_messages_attr.cpp @@ -0,0 +1,311 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -fsyntax-only %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -std=c++11 -fsyntax-only %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -fsyntax-only %s -Wuninitialized +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -std=c++11 -fsyntax-only %s -Wuninitialized + +typedef void **omp_allocator_handle_t; +extern const omp_allocator_handle_t omp_null_allocator; +extern const omp_allocator_handle_t omp_default_mem_alloc; +extern const omp_allocator_handle_t omp_large_cap_mem_alloc; +extern const omp_allocator_handle_t omp_const_mem_alloc; +extern const omp_allocator_handle_t omp_high_bw_mem_alloc; +extern const omp_allocator_handle_t omp_low_lat_mem_alloc; +extern const omp_allocator_handle_t omp_cgroup_mem_alloc; +extern const omp_allocator_handle_t omp_pteam_mem_alloc; +extern const omp_allocator_handle_t omp_thread_mem_alloc; + +void xxx(int argc) { + int fp; // expected-note {{initialize the variable 'fp' to silence this warning}} + [[omp::directive(taskloop reduction(+:fp))]] // expected-warning {{variable 'fp' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +void foobar(int &ref) { + [[omp::directive(taskloop reduction(+:ref))]] + for (int i = 0; i < 10; ++i) + foo(); +} + +struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; + S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}} + +public: + S2() : a(0) {} + S2(S2 &s2) : a(s2.a) {} + static float S2s; // expected-note 2 {{static data member is predetermined as shared}} + static const float S2sc; // expected-note 2 {{'S2sc' declared here}} +}; +const float S2::S2sc = 0; +S2 b; // expected-note 3 {{'b' defined here}} +const S2 ba[5]; // expected-note 2 {{'ba' defined here}} +class S3 { + int a; + +public: + int b; + S3() : a(0) {} + S3(const S3 &s3) : a(s3.a) {} + S3 operator+(const S3 &arg1) { return arg1; } +}; +int operator+(const S3 &arg1, const S3 &arg2) { return 5; } +S3 c; // expected-note 3 {{'c' defined here}} +const S3 ca[5]; // expected-note 2 {{'ca' defined here}} +extern const int f; // expected-note 4 {{'f' declared here}} +class S4 { + int a; + S4(); // expected-note {{implicitly declared private here}} + S4(const S4 &s4); + S4 &operator+(const S4 &arg) { return (*this); } + +public: + S4(int v) : a(v) {} +}; +S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; } +class S5 { + int a:32; + S5() : a(0) {} // expected-note {{implicitly declared private here}} + S5(const S5 &s5) : a(s5.a) {} + S5 &operator+(const S5 &arg); + +public: + S5(int v) : a(v) {} +}; +class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}} +#if __cplusplus >= 201103L // C++11 or later +// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}} +#endif + int a; + +public: + S6() : a(6) {} + operator int() { return 6; } +} o; + +struct S7 { + int a: 32; + S7() { + [[omp::directive(taskloop reduction(+:a))]] // expected-error {{expected addressable reduction item for the task-based directives}} + for (int i = 0; i < 10; ++i) + ++a; + } +}; + +S3 h, k; +[[omp::directive(threadprivate(h))]]; // expected-note 2 {{defined as threadprivate or thread local}} + +template // expected-note {{declared here}} +T tmain(T argc) { + const T d = T(); // expected-note 4 {{'d' defined here}} + const T da[5] = {T()}; // expected-note 2 {{'da' defined here}} + T qa[5] = {T()}; + T i, z; + T &j = i; // expected-note 4 {{'j' defined here}} + S3 &p = k; // expected-note 2 {{'p' defined here}} + const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}} + T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}} + T fl; + [[omp::directive(taskloop reduction)]] // expected-error {{expected '(' after 'reduction'}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction +)]] // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp taskloop' are ignored}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction())]] // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(*))]] // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(\))]] // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(foo : argc))]] //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(^ : T))]] // expected-error {{'T' does not refer to a value}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : z, a, b, c, d, f))]] // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified variable cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(min : a, b, c, d, f))]] // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(max : h.b))]] // expected-error {{expected variable name, array element or array section}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : ba))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(* : ca))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(- : da))]] // expected-error {{const-qualified variable cannot be reduction}} expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(^ : fl))]] // expected-error {{invalid operands to binary expression ('float' and 'float')}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(&& : S2::S2s))]] // expected-error {{shared variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(&& : S2::S2sc))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : h, k))]] // expected-error {{threadprivate or thread local variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : o))]] // expected-error 2 {{no viable overloaded '='}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop private(i), reduction(+ : j), reduction(+ : q))]] // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel private(k)), directive(taskloop reduction(+ : p), reduction(+ : p)))]] // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : p), reduction(+ : p))]] // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : r))]] // expected-error 2 {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel shared(i)), directive(parallel reduction(min : i)), directive(taskloop reduction(max : j)))]] // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel private(fl)), directive(taskloop reduction(+ : fl) allocate(omp_thread_mem_alloc: fl)))]] // expected-warning 2 {{allocator with the 'thread' trait access has unspecified behavior on 'taskloop' directive}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel reduction(* : fl)), directive(taskloop reduction(+ : fl)))]] + for (int i = 0; i < 10; ++i) + foo(); + + return T(); +} + +namespace A { +double x; +[[omp::directive(threadprivate(x))]]; // expected-note {{defined as threadprivate or thread local}} +} +namespace B { +using A::x; +} + +int main(int argc, char **argv) { + const int d = 5; // expected-note 2 {{'d' defined here}} + const int da[5] = {0}; // expected-note {{'da' defined here}} + int qa[5] = {0}; + S4 e(4); + S5 g(5); + int i, z; + int &j = i; // expected-note 2 {{'j' defined here}} + S3 &p = k; // expected-note 2 {{'p' defined here}} + const int &r = da[i]; // expected-note {{'r' defined here}} + int &q = qa[i]; // expected-note {{'q' defined here}} + float fl; + [[omp::directive(taskloop reduction)]] // expected-error {{expected '(' after 'reduction'}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction +)]] // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp taskloop' are ignored}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction())]] // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(*))]] // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(\))]] // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(~ : argc))]] // expected-error {{expected unqualified-id}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(&& : argc, z))]] + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(^ : S1))]] // expected-error {{'S1' does not refer to a value}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : a, b, c, d, f))]] // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified variable cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(min : a, b, c, d, f))]] // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(max : h.b))]] // expected-error {{expected variable name, array element or array section}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : ba))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(* : ca))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(- : da))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(^ : fl))]] // expected-error {{invalid operands to binary expression ('float' and 'float')}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(&& : S2::S2s))]] // expected-error {{shared variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(&& : S2::S2sc))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(& : e, g))]] // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : h, k, B::x))]] // expected-error 2 {{threadprivate or thread local variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : o))]] // expected-error {{no viable overloaded '='}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop private(i), reduction(+ : j), reduction(+ : q))]] // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel private(k)), directive(taskloop reduction(+ : p), reduction(+ : p)))]] // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : p), reduction(+ : p))]] // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::directive(taskloop reduction(+ : r))]] // expected-error {{const-qualified variable cannot be reduction}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel shared(i)), directive(parallel reduction(min : i)), directive(taskloop reduction(max : j)))]] // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}} + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel private(fl)), directive(taskloop reduction(+ : fl)))]] + for (int i = 0; i < 10; ++i) + foo(); + [[omp::sequence(directive(parallel reduction(* : fl)), directive(taskloop reduction(+ : fl)))]] + for (int i = 0; i < 10; ++i) + foo(); + static int m; + [[omp::directive(taskloop reduction(+ : m))]] // OK + for (int i = 0; i < 10; ++i) + m++; + [[omp::directive(taskloop reduction(task, + : m))]] // expected-error {{'reduction' clause with 'task' modifier allowed only on non-simd parallel or worksharing constructs}} + for (int i = 0; i < 10; ++i) + m++; + [[omp::directive(taskloop nogroup reduction(+ : m))]] // expected-error {{'reduction' clause cannot be used with 'nogroup' clause}} + for (int i = 0; i < 10; ++i) + m++; + + return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain' requested here}} expected-note {{in instantiation of function template specialization 'tmain' requested here}} +} + diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages_attr.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages_attr.cpp new file mode 100644 index 0000000000000..9c4bde791d3ed --- /dev/null +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages_attr.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -fopenmp -fopenmp-version=51 -std=c++11 %s -Wuninitialized +// RUN: %clang_cc1 -verify -fsyntax-only -fopenmp-simd -fopenmp-version=51 -std=c++11 %s -Wuninitialized + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note 2 {{declared here}} + +template // expected-note {{declared here}} +T tmain(T argc) { + char **a; + T k; + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(C)))]] + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(T)))]] // expected-error {{'T' does not refer to a value}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams))]] // expected-error {{expected '(' after 'num_teams'}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams()))]] // expected-error {{expected expression}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(argc > 0 ? a[1] : a[2])))]] // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(argc + k)))]] + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(argc), num_teams (argc+1)))]] // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'num_teams' clause}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(S1)))]] // expected-error {{'S1' does not refer to a value}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(-2)))]] // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}} + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(-10u)))]] + for (int i=0; i<100; i++) foo(); + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams(3.14)))]] // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}} + for (int i=0; i<100; i++) foo(); + + return 0; +} + +int main(int argc, char **argv) { + int k; + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams))]] // expected-error {{expected '(' after 'num_teams'}} + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams ()))]] // expected-error {{expected expression}} + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (argc > 0 ? argv[1] : argv[2])))]] // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (argc + k)))]] + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (argc), num_teams (argc+1)))]] // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'num_teams' clause}} + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (S1)))]] // expected-error {{'S1' does not refer to a value}} + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (-2)))]] // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}} + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (-10u)))]] + for (int i=0; i<100; i++) foo(); + + [[omp::sequence(directive(target), directive(teams distribute parallel for simd num_teams (3.14)))]] // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} + for (int i=0; i<100; i++) foo(); + + return tmain(argc); // expected-note {{in instantiation of function template specialization 'tmain' requested here}} +} diff --git a/clang/test/OpenMP/unroll_codegen_unroll_for_attr.cpp b/clang/test/OpenMP/unroll_codegen_unroll_for_attr.cpp new file mode 100644 index 0000000000000..f431201bcf476 --- /dev/null +++ b/clang/test/OpenMP/unroll_codegen_unroll_for_attr.cpp @@ -0,0 +1,237 @@ +// Check code generation +// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -emit-llvm %s -o - | FileCheck %s --check-prefix=IR + +// Check same results after serialization round-trip +// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -emit-pch -o %t %s +// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 -include-pch %t -emit-llvm %s -o - | FileCheck %s --check-prefix=IR +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +// placeholder for loop body code. +extern "C" void body(...) {} + + +// IR-LABEL: @func( +// IR-NEXT: [[ENTRY:.*]]: +// IR-NEXT: %[[START_ADDR:.+]] = alloca i32, align 4 +// IR-NEXT: %[[END_ADDR:.+]] = alloca i32, align 4 +// IR-NEXT: %[[STEP_ADDR:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTOMP_IV:.+]] = alloca i32, align 4 +// IR-NEXT: %[[TMP:.+]] = alloca i32, align 4 +// IR-NEXT: %[[I:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_1:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_2:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_3:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTUNROLLED_IV_I:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_6:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_8:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_12:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTCAPTURE_EXPR_14:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTUNROLLED_IV__UNROLLED_IV_I:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTOMP_LB:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTOMP_UB:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTOMP_STRIDE:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTOMP_IS_LAST:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTUNROLLED_IV__UNROLLED_IV_I18:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I:.+]] = alloca i32, align 4 +// IR-NEXT: %[[DOTUNROLL_INNER_IV_I:.+]] = alloca i32, align 4 +// IR-NEXT: %[[TMP0:.+]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @2) +// IR-NEXT: store i32 %[[START:.+]], i32* %[[START_ADDR]], align 4 +// IR-NEXT: store i32 %[[END:.+]], i32* %[[END_ADDR]], align 4 +// IR-NEXT: store i32 %[[STEP:.+]], i32* %[[STEP_ADDR]], align 4 +// IR-NEXT: %[[TMP1:.+]] = load i32, i32* %[[START_ADDR]], align 4 +// IR-NEXT: store i32 %[[TMP1]], i32* %[[I]], align 4 +// IR-NEXT: %[[TMP2:.+]] = load i32, i32* %[[START_ADDR]], align 4 +// IR-NEXT: store i32 %[[TMP2]], i32* %[[DOTCAPTURE_EXPR_]], align 4 +// IR-NEXT: %[[TMP3:.+]] = load i32, i32* %[[END_ADDR]], align 4 +// IR-NEXT: store i32 %[[TMP3]], i32* %[[DOTCAPTURE_EXPR_1]], align 4 +// IR-NEXT: %[[TMP4:.+]] = load i32, i32* %[[STEP_ADDR]], align 4 +// IR-NEXT: store i32 %[[TMP4]], i32* %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[TMP5:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_1]], align 4 +// IR-NEXT: %[[TMP6:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_]], align 4 +// IR-NEXT: %[[SUB:.+]] = sub i32 %[[TMP5]], %[[TMP6]] +// IR-NEXT: %[[SUB4:.+]] = sub i32 %[[SUB]], 1 +// IR-NEXT: %[[TMP7:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[ADD:.+]] = add i32 %[[SUB4]], %[[TMP7]] +// IR-NEXT: %[[TMP8:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[DIV:.+]] = udiv i32 %[[ADD]], %[[TMP8]] +// IR-NEXT: %[[SUB5:.+]] = sub i32 %[[DIV]], 1 +// IR-NEXT: store i32 %[[SUB5]], i32* %[[DOTCAPTURE_EXPR_3]], align 4 +// IR-NEXT: store i32 0, i32* %[[DOTUNROLLED_IV_I]], align 4 +// IR-NEXT: %[[TMP9:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_3]], align 4 +// IR-NEXT: %[[ADD7:.+]] = add i32 %[[TMP9]], 1 +// IR-NEXT: store i32 %[[ADD7]], i32* %[[DOTCAPTURE_EXPR_6]], align 4 +// IR-NEXT: %[[TMP10:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_6]], align 4 +// IR-NEXT: %[[SUB9:.+]] = sub i32 %[[TMP10]], -1 +// IR-NEXT: %[[DIV10:.+]] = udiv i32 %[[SUB9]], 2 +// IR-NEXT: %[[SUB11:.+]] = sub i32 %[[DIV10]], 1 +// IR-NEXT: store i32 %[[SUB11]], i32* %[[DOTCAPTURE_EXPR_8]], align 4 +// IR-NEXT: %[[TMP11:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_8]], align 4 +// IR-NEXT: %[[ADD13:.+]] = add i32 %[[TMP11]], 1 +// IR-NEXT: store i32 %[[ADD13]], i32* %[[DOTCAPTURE_EXPR_12]], align 4 +// IR-NEXT: %[[TMP12:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_12]], align 4 +// IR-NEXT: %[[SUB15:.+]] = sub i32 %[[TMP12]], -1 +// IR-NEXT: %[[DIV16:.+]] = udiv i32 %[[SUB15]], 2 +// IR-NEXT: %[[SUB17:.+]] = sub i32 %[[DIV16]], 1 +// IR-NEXT: store i32 %[[SUB17]], i32* %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: store i32 0, i32* %[[DOTUNROLLED_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: %[[TMP13:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_12]], align 4 +// IR-NEXT: %[[CMP:.+]] = icmp ult i32 0, %[[TMP13]] +// IR-NEXT: br i1 %[[CMP]], label %[[OMP_PRECOND_THEN:.+]], label %[[OMP_PRECOND_END:.+]] +// IR-EMPTY: +// IR-NEXT: [[OMP_PRECOND_THEN]]: +// IR-NEXT: store i32 0, i32* %[[DOTOMP_LB]], align 4 +// IR-NEXT: %[[TMP14:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: store i32 %[[TMP14]], i32* %[[DOTOMP_UB]], align 4 +// IR-NEXT: store i32 1, i32* %[[DOTOMP_STRIDE]], align 4 +// IR-NEXT: store i32 0, i32* %[[DOTOMP_IS_LAST]], align 4 +// IR-NEXT: call void @__kmpc_for_static_init_4u(%struct.ident_t* @1, i32 %[[TMP0]], i32 34, i32* %[[DOTOMP_IS_LAST]], i32* %[[DOTOMP_LB]], i32* %[[DOTOMP_UB]], i32* %[[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-NEXT: %[[TMP15:.+]] = load i32, i32* %[[DOTOMP_UB]], align 4 +// IR-NEXT: %[[TMP16:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: %[[CMP19:.+]] = icmp ugt i32 %[[TMP15]], %[[TMP16]] +// IR-NEXT: br i1 %[[CMP19]], label %[[COND_TRUE:.+]], label %[[COND_FALSE:.+]] +// IR-EMPTY: +// IR-NEXT: [[COND_TRUE]]: +// IR-NEXT: %[[TMP17:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_14]], align 4 +// IR-NEXT: br label %[[COND_END:.+]] +// IR-EMPTY: +// IR-NEXT: [[COND_FALSE]]: +// IR-NEXT: %[[TMP18:.+]] = load i32, i32* %[[DOTOMP_UB]], align 4 +// IR-NEXT: br label %[[COND_END]] +// IR-EMPTY: +// IR-NEXT: [[COND_END]]: +// IR-NEXT: %[[COND:.+]] = phi i32 [ %[[TMP17]], %[[COND_TRUE]] ], [ %[[TMP18]], %[[COND_FALSE]] ] +// IR-NEXT: store i32 %[[COND]], i32* %[[DOTOMP_UB]], align 4 +// IR-NEXT: %[[TMP19:.+]] = load i32, i32* %[[DOTOMP_LB]], align 4 +// IR-NEXT: store i32 %[[TMP19]], i32* %[[DOTOMP_IV]], align 4 +// IR-NEXT: br label %[[OMP_INNER_FOR_COND:.+]] +// IR-EMPTY: +// IR-NEXT: [[OMP_INNER_FOR_COND]]: +// IR-NEXT: %[[TMP20:.+]] = load i32, i32* %[[DOTOMP_IV]], align 4 +// IR-NEXT: %[[TMP21:.+]] = load i32, i32* %[[DOTOMP_UB]], align 4 +// IR-NEXT: %[[ADD20:.+]] = add i32 %[[TMP21]], 1 +// IR-NEXT: %[[CMP21:.+]] = icmp ult i32 %[[TMP20]], %[[ADD20]] +// IR-NEXT: br i1 %[[CMP21]], label %[[OMP_INNER_FOR_BODY:.+]], label %[[OMP_INNER_FOR_END:.+]] +// IR-EMPTY: +// IR-NEXT: [[OMP_INNER_FOR_BODY]]: +// IR-NEXT: %[[TMP22:.+]] = load i32, i32* %[[DOTOMP_IV]], align 4 +// IR-NEXT: %[[MUL:.+]] = mul i32 %[[TMP22]], 2 +// IR-NEXT: %[[ADD22:.+]] = add i32 0, %[[MUL]] +// IR-NEXT: store i32 %[[ADD22]], i32* %[[DOTUNROLLED_IV__UNROLLED_IV_I18]], align 4 +// IR-NEXT: %[[TMP23:.+]] = load i32, i32* %[[DOTUNROLLED_IV__UNROLLED_IV_I18]], align 4 +// IR-NEXT: store i32 %[[TMP23]], i32* %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: br label %[[FOR_COND:.+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_COND]]: +// IR-NEXT: %[[TMP24:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: %[[TMP25:.+]] = load i32, i32* %[[DOTUNROLLED_IV__UNROLLED_IV_I18]], align 4 +// IR-NEXT: %[[ADD23:.+]] = add i32 %[[TMP25]], 2 +// IR-NEXT: %[[CMP24:.+]] = icmp ule i32 %[[TMP24]], %[[ADD23]] +// IR-NEXT: br i1 %[[CMP24]], label %[[LAND_RHS:.+]], label %[[LAND_END:.+]] +// IR-EMPTY: +// IR-NEXT: [[LAND_RHS]]: +// IR-NEXT: %[[TMP26:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: %[[TMP27:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_8]], align 4 +// IR-NEXT: %[[ADD25:.+]] = add i32 %[[TMP27]], 1 +// IR-NEXT: %[[CMP26:.+]] = icmp ule i32 %[[TMP26]], %[[ADD25]] +// IR-NEXT: br label %[[LAND_END]] +// IR-EMPTY: +// IR-NEXT: [[LAND_END]]: +// IR-NEXT: %[[TMP28:.+]] = phi i1 [ false, %[[FOR_COND]] ], [ %[[CMP26]], %[[LAND_RHS]] ] +// IR-NEXT: br i1 %[[TMP28]], label %[[FOR_BODY:.+]], label %[[FOR_END41:.+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_BODY]]: +// IR-NEXT: %[[TMP29:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: %[[MUL27:.+]] = mul i32 %[[TMP29]], 2 +// IR-NEXT: %[[ADD28:.+]] = add i32 0, %[[MUL27]] +// IR-NEXT: store i32 %[[ADD28]], i32* %[[DOTUNROLLED_IV_I]], align 4 +// IR-NEXT: %[[TMP30:.+]] = load i32, i32* %[[DOTUNROLLED_IV_I]], align 4 +// IR-NEXT: store i32 %[[TMP30]], i32* %[[DOTUNROLL_INNER_IV_I]], align 4 +// IR-NEXT: br label %[[FOR_COND29:.+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_COND29]]: +// IR-NEXT: %[[TMP31:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV_I]], align 4 +// IR-NEXT: %[[TMP32:.+]] = load i32, i32* %[[DOTUNROLLED_IV_I]], align 4 +// IR-NEXT: %[[ADD30:.+]] = add i32 %[[TMP32]], 2 +// IR-NEXT: %[[CMP31:.+]] = icmp ule i32 %[[TMP31]], %[[ADD30]] +// IR-NEXT: br i1 %[[CMP31]], label %[[LAND_RHS32:.+]], label %[[LAND_END35:.+]] +// IR-EMPTY: +// IR-NEXT: [[LAND_RHS32]]: +// IR-NEXT: %[[TMP33:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV_I]], align 4 +// IR-NEXT: %[[TMP34:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_3]], align 4 +// IR-NEXT: %[[ADD33:.+]] = add i32 %[[TMP34]], 1 +// IR-NEXT: %[[CMP34:.+]] = icmp ule i32 %[[TMP33]], %[[ADD33]] +// IR-NEXT: br label %[[LAND_END35]] +// IR-EMPTY: +// IR-NEXT: [[LAND_END35]]: +// IR-NEXT: %[[TMP35:.+]] = phi i1 [ false, %[[FOR_COND29]] ], [ %[[CMP34]], %[[LAND_RHS32]] ] +// IR-NEXT: br i1 %[[TMP35]], label %[[FOR_BODY36:.+]], label %[[FOR_END:.+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_BODY36]]: +// IR-NEXT: %[[TMP36:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_]], align 4 +// IR-NEXT: %[[TMP37:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV_I]], align 4 +// IR-NEXT: %[[TMP38:.+]] = load i32, i32* %[[DOTCAPTURE_EXPR_2]], align 4 +// IR-NEXT: %[[MUL37:.+]] = mul i32 %[[TMP37]], %[[TMP38]] +// IR-NEXT: %[[ADD38:.+]] = add i32 %[[TMP36]], %[[MUL37]] +// IR-NEXT: store i32 %[[ADD38]], i32* %[[I]], align 4 +// IR-NEXT: %[[TMP39:.+]] = load i32, i32* %[[START_ADDR]], align 4 +// IR-NEXT: %[[TMP40:.+]] = load i32, i32* %[[END_ADDR]], align 4 +// IR-NEXT: %[[TMP41:.+]] = load i32, i32* %[[STEP_ADDR]], align 4 +// IR-NEXT: %[[TMP42:.+]] = load i32, i32* %[[I]], align 4 +// IR-NEXT: call void (...) @body(i32 %[[TMP39]], i32 %[[TMP40]], i32 %[[TMP41]], i32 %[[TMP42]]) +// IR-NEXT: br label %[[FOR_INC:.+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_INC]]: +// IR-NEXT: %[[TMP43:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV_I]], align 4 +// IR-NEXT: %[[INC:.+]] = add i32 %[[TMP43]], 1 +// IR-NEXT: store i32 %[[INC]], i32* %[[DOTUNROLL_INNER_IV_I]], align 4 +// IR-NEXT: br label %[[FOR_COND29]], !llvm.loop ![[LOOP2:[0-9]+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_END]]: +// IR-NEXT: br label %[[FOR_INC39:.+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_INC39]]: +// IR-NEXT: %[[TMP44:.+]] = load i32, i32* %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: %[[INC40:.+]] = add i32 %[[TMP44]], 1 +// IR-NEXT: store i32 %[[INC40]], i32* %[[DOTUNROLL_INNER_IV__UNROLLED_IV_I]], align 4 +// IR-NEXT: br label %[[FOR_COND]], !llvm.loop ![[LOOP5:[0-9]+]] +// IR-EMPTY: +// IR-NEXT: [[FOR_END41]]: +// IR-NEXT: br label %[[OMP_BODY_CONTINUE:.+]] +// IR-EMPTY: +// IR-NEXT: [[OMP_BODY_CONTINUE]]: +// IR-NEXT: br label %[[OMP_INNER_FOR_INC:.+]] +// IR-EMPTY: +// IR-NEXT: [[OMP_INNER_FOR_INC]]: +// IR-NEXT: %[[TMP45:.+]] = load i32, i32* %[[DOTOMP_IV]], align 4 +// IR-NEXT: %[[ADD42:.+]] = add i32 %[[TMP45]], 1 +// IR-NEXT: store i32 %[[ADD42]], i32* %[[DOTOMP_IV]], align 4 +// IR-NEXT: br label %[[OMP_INNER_FOR_COND]] +// IR-EMPTY: +// IR-NEXT: [[OMP_INNER_FOR_END]]: +// IR-NEXT: br label %[[OMP_LOOP_EXIT:.+]] +// IR-EMPTY: +// IR-NEXT: [[OMP_LOOP_EXIT]]: +// IR-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* @1, i32 %[[TMP0]]) +// IR-NEXT: br label %[[OMP_PRECOND_END]] +// IR-EMPTY: +// IR-NEXT: [[OMP_PRECOND_END]]: +// IR-NEXT: call void @__kmpc_barrier(%struct.ident_t* @3, i32 %[[TMP0]]) +// IR-NEXT: ret void +// IR-NEXT: } +extern "C" void func(int start, int end, int step) { + [[omp::sequence(directive(for), directive(unroll partial), directive(unroll partial))]] + for (int i = start; i < end; i+=step) + body(start, end, step, i); +} + +#endif /* HEADER */ + + +// IR: ![[LOOP2]] = distinct !{![[LOOP2]], ![[LOOPPROP3:[0-9]+]], ![[LOOPPROP4:[0-9]+]]} +// IR: ![[LOOPPROP3]] = !{!"llvm.loop.mustprogress"} +// IR: ![[LOOPPROP4]] = !{!"llvm.loop.unroll.count", i32 2} +// IR: ![[LOOP5]] = distinct !{![[LOOP5]], ![[LOOPPROP3]], ![[LOOPPROP4]]} diff --git a/clang/test/Sema/aix-attr-align.c b/clang/test/Sema/aix-attr-align.c new file mode 100644 index 0000000000000..ac70aab669004 --- /dev/null +++ b/clang/test/Sema/aix-attr-align.c @@ -0,0 +1,22 @@ +// off-no-diagnostics +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -verify -fsyntax-only %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -verify -fsyntax-only %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -verify=off -Wno-aix-compat -fsyntax-only %s +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -verify=off -Wno-aix-compat -fsyntax-only %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux -verify=off -fsyntax-only %s + +struct S { + int a[8] __attribute__((aligned(8))); // no-warning +}; + +struct T { + int a[4] __attribute__((aligned(16))); // expected-warning {{requesting an alignment of 16 bytes or greater for struct members is not binary compatible with AIX XL 16.1 and older}} +}; + +struct U { + int a[2] __attribute__((aligned(32))); // expected-warning {{requesting an alignment of 16 bytes or greater for struct members is not binary compatible with AIX XL 16.1 and older}} +}; + +int a[8] __attribute__((aligned(8))); // no-warning +int b[4] __attribute__((aligned(16))); // no-warning +int c[2] __attribute__((aligned(32))); // no-warning diff --git a/clang/test/Sema/bitfield.c b/clang/test/Sema/bitfield.c index 03b2a22d3ed9b..13b6c3e152d72 100644 --- a/clang/test/Sema/bitfield.c +++ b/clang/test/Sema/bitfield.c @@ -6,7 +6,7 @@ struct a { int a : -1; // expected-error{{bit-field 'a' has negative width}} // rdar://6081627 - int b : 33; // expected-error{{width of bit-field 'b' (33 bits) exceeds width of its type (32 bits)}} + int b : 33; // expected-error{{width of bit-field 'b' (33 bits) exceeds the width of its type (32 bits)}} int c : (1 + 0.25); // expected-error{{integer constant expression must have integer type}} int d : (int)(1 + 0.25); @@ -22,12 +22,12 @@ struct a { int g : (_Bool)1; // PR4017 - char : 10; // expected-error {{width of anonymous bit-field (10 bits) exceeds width of its type (8 bits)}} + char : 10; // expected-error {{width of anonymous bit-field (10 bits) exceeds the width of its type (8 bits)}} unsigned : -2; // expected-error {{anonymous bit-field has negative width (-2)}} float : 12; // expected-error {{anonymous bit-field has non-integral type 'float'}} - _Bool : 2; // expected-error {{width of anonymous bit-field (2 bits) exceeds width of its type (1 bit)}} - _Bool h : 5; // expected-error {{width of bit-field 'h' (5 bits) exceeds width of its type (1 bit)}} + _Bool : 2; // expected-error {{width of anonymous bit-field (2 bits) exceeds the width of its type (1 bit)}} + _Bool h : 5; // expected-error {{width of bit-field 'h' (5 bits) exceeds the width of its type (1 bit)}} }; struct b {unsigned x : 2;} x; diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp index 8ff709ddbbb25..98ee2aba4bc4c 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -120,7 +120,9 @@ void f(Yb& a) { char ch = a; // OK. calls Yb::operator char(); } -// Test conversion + copy construction. +// Test conversion + copy construction. This is a pure C++98 test. +// However we may extend implicit moves into C++98, we must make sure the +// result here is not changed. class AutoPtrRef { }; class AutoPtr { diff --git a/clang/test/SemaCXX/crash-auto-36064.cpp b/clang/test/SemaCXX/crash-auto-36064.cpp new file mode 100644 index 0000000000000..5678cd8b730b8 --- /dev/null +++ b/clang/test/SemaCXX/crash-auto-36064.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify +template // expected-error{{new expression for type 'auto' requires a constructor argument}} +struct b; +struct d { + static auto c = ; // expected-error{{expected expression}} + decltype(b); // expected-error{{expected '(' for function-style cast or type construction}} + // expected-note@-1{{while substituting prior template arguments into non-type template parameter [with A = auto]}} +}; diff --git a/clang/test/SemaCXX/ms_wide_bitfield.cpp b/clang/test/SemaCXX/ms_wide_bitfield.cpp index b634e78c70ce5..0dcc787928b0a 100644 --- a/clang/test/SemaCXX/ms_wide_bitfield.cpp +++ b/clang/test/SemaCXX/ms_wide_bitfield.cpp @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only -mms-bitfields -verify %s 2>&1 struct A { - char a : 9; // expected-error{{width of bit-field 'a' (9 bits) exceeds size of its type (8 bits)}} - int b : 33; // expected-error{{width of bit-field 'b' (33 bits) exceeds size of its type (32 bits)}} - bool c : 9; // expected-error{{width of bit-field 'c' (9 bits) exceeds size of its type (8 bits)}} + char a : 9; // expected-error{{width of bit-field 'a' (9 bits) exceeds the size of its type (8 bits)}} + int b : 33; // expected-error{{width of bit-field 'b' (33 bits) exceeds the size of its type (32 bits)}} + bool c : 9; // expected-error{{width of bit-field 'c' (9 bits) exceeds the size of its type (8 bits)}} bool d : 3; }; diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp index dfc06331e51f3..affc0c32a7a89 100644 --- a/clang/test/SemaCXX/static-assert.cpp +++ b/clang/test/SemaCXX/static-assert.cpp @@ -188,3 +188,14 @@ void foo4(T t) { } void callFoo4() { foo4(42); } // expected-note@-1{{in instantiation of function template specialization 'foo4' requested here}} + +static_assert(42, "message"); +static_assert(42.0, "message"); // expected-warning {{implicit conversion from 'double' to 'bool' changes value from 42 to true}} +constexpr int *p = 0; +static_assert(p, "message"); // expected-error {{static_assert failed}} + +struct NotBool { +} notBool; +constexpr NotBool constexprNotBool; +static_assert(notBool, "message"); // expected-error {{value of type 'struct NotBool' is not contextually convertible to 'bool'}} +static_assert(constexprNotBool, "message"); // expected-error {{value of type 'const NotBool' is not contextually convertible to 'bool'}} diff --git a/clang/test/SemaObjC/class-bitfield.m b/clang/test/SemaObjC/class-bitfield.m index 07d690a94a9d2..0e88c44ae0ffd 100644 --- a/clang/test/SemaObjC/class-bitfield.m +++ b/clang/test/SemaObjC/class-bitfield.m @@ -5,7 +5,7 @@ @interface X int a : -1; // expected-error{{bit-field 'a' has negative width}} // rdar://6081627 - int b : 33; // expected-error{{width of bit-field 'b' (33 bits) exceeds width of its type (32 bits)}} + int b : 33; // expected-error{{width of bit-field 'b' (33 bits) exceeds the width of its type (32 bits)}} int c : (1 + 0.25); // expected-error{{integer constant expression must have integer type}} int d : (int)(1 + 0.25); diff --git a/clang/test/SemaObjCXX/block-capture.mm b/clang/test/SemaObjCXX/block-capture.mm index 77a3907c6578c..c89c088a871ba 100644 --- a/clang/test/SemaObjCXX/block-capture.mm +++ b/clang/test/SemaObjCXX/block-capture.mm @@ -14,6 +14,10 @@ }; TEST(CopyOnly); // cxx2b-error {{no matching constructor}} +// Both ConstCopyOnly and NonConstCopyOnly are +// "pure" C++98 tests (pretend 'delete' means 'private'). +// However we may extend implicit moves into C++98, we must make sure the +// results in these are not changed. struct ConstCopyOnly { ConstCopyOnly(); ConstCopyOnly(ConstCopyOnly &) = delete; // cxx98-note {{marked deleted here}} @@ -31,51 +35,51 @@ struct CopyNoMove { CopyNoMove(); CopyNoMove(CopyNoMove &); - CopyNoMove(CopyNoMove &&) = delete; // cxx11_2b-note {{marked deleted here}} + CopyNoMove(CopyNoMove &&) = delete; // cxx98_2b-note {{marked deleted here}} }; -TEST(CopyNoMove); // cxx11_2b-error {{call to deleted constructor}} +TEST(CopyNoMove); // cxx98_2b-error {{call to deleted constructor}} struct MoveOnly { MoveOnly(); - MoveOnly(MoveOnly &) = delete; // cxx98-note {{marked deleted here}} + MoveOnly(MoveOnly &) = delete; MoveOnly(MoveOnly &&); }; -TEST(MoveOnly); // cxx98-error {{call to deleted constructor}} +TEST(MoveOnly); struct NoCopyNoMove { NoCopyNoMove(); - NoCopyNoMove(NoCopyNoMove &) = delete; // cxx98-note {{marked deleted here}} - NoCopyNoMove(NoCopyNoMove &&) = delete; // cxx11_2b-note {{marked deleted here}} + NoCopyNoMove(NoCopyNoMove &) = delete; + NoCopyNoMove(NoCopyNoMove &&) = delete; // cxx98_2b-note {{marked deleted here}} }; TEST(NoCopyNoMove); // cxx98_2b-error {{call to deleted constructor}} struct ConvertingRVRef { ConvertingRVRef(); - ConvertingRVRef(ConvertingRVRef &) = delete; // cxx98-note {{marked deleted here}} + ConvertingRVRef(ConvertingRVRef &) = delete; struct X {}; ConvertingRVRef(X &&); operator X() const & = delete; operator X() &&; }; -TEST(ConvertingRVRef); // cxx98-error {{call to deleted constructor}} +TEST(ConvertingRVRef); struct ConvertingCLVRef { ConvertingCLVRef(); ConvertingCLVRef(ConvertingCLVRef &); struct X {}; - ConvertingCLVRef(X &&); // cxx11_2b-note {{passing argument to parameter here}} + ConvertingCLVRef(X &&); // cxx98_2b-note {{passing argument to parameter here}} operator X() const &; - operator X() && = delete; // cxx11_2b-note {{marked deleted here}} + operator X() && = delete; // cxx98_2b-note {{marked deleted here}} }; -TEST(ConvertingCLVRef); // cxx11_2b-error {{invokes a deleted function}} +TEST(ConvertingCLVRef); // cxx98_2b-error {{invokes a deleted function}} struct SubSubMove {}; struct SubMove : SubSubMove { SubMove(); - SubMove(SubMove &) = delete; // cxx98-note {{marked deleted here}} + SubMove(SubMove &) = delete; SubMove(SubSubMove &&); }; -TEST(SubMove); // cxx98-error {{call to deleted constructor}} +TEST(SubMove); diff --git a/clang/test/SemaOpenCL/access-qualifier.cl b/clang/test/SemaOpenCL/access-qualifier.cl index 115944c9f3e79..c538e73253ce0 100644 --- a/clang/test/SemaOpenCL/access-qualifier.cl +++ b/clang/test/SemaOpenCL/access-qualifier.cl @@ -1,12 +1,14 @@ -// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s -cl-ext=-cl_khr_3d_image_writes -// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL2.0 %s +// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s -cl-ext=-cl_khr_3d_image_writes +// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL2.0 %s +// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL3.0 %s +// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL3.0 %s -cl-ext=-__opencl_c_read_write_images typedef image1d_t img1d_ro_default; // expected-note {{previously declared 'read_only' here}} typedef write_only image1d_t img1d_wo; // expected-note {{previously declared 'write_only' here}} typedef read_only image1d_t img1d_ro; -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images)) typedef read_write image1d_t img1d_rw; #endif @@ -17,10 +19,10 @@ typedef read_only int IntRO; // expected-error {{access qualifier can only be us void myWrite(write_only image1d_t); // expected-note {{passing argument to parameter here}} expected-note {{passing argument to parameter here}} void myRead(read_only image1d_t); // expected-note {{passing argument to parameter here}} -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images)) void myReadWrite(read_write image1d_t); #else -void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}} +void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' can not be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}} #endif @@ -36,7 +38,7 @@ kernel void k3(img1d_wo img) { myWrite(img); } -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images)) kernel void k4(img1d_rw img) { myReadWrite(img); } @@ -62,26 +64,26 @@ kernel void k11(read_only write_only image1d_t i){} // expected-error{{multiple kernel void k12(read_only read_only image1d_t i){} // expected-warning {{duplicate 'read_only' declaration specifier}} -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images)) kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}} #else -kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}} -#endif - -#if __OPENCL_C_VERSION__ >= 200 -void myPipeWrite(write_only pipe int); // expected-note {{passing argument to parameter here}} -kernel void k14(read_only pipe int p) { - myPipeWrite(p); // expected-error {{passing '__private read_only pipe int' to parameter of incompatible type 'write_only pipe int'}} -} +kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}} #endif #if __OPENCL_C_VERSION__ < 200 kernel void test_image3d_wo(write_only image3d_t img) {} // expected-error {{use of type '__write_only image3d_t' requires cl_khr_3d_image_writes support}} #endif -#if __OPENCL_C_VERSION__ >= 200 +#if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ == 300 && defined(__opencl_c_read_write_images)) kernel void read_write_twice_typedef(read_write img1d_rw i){} // expected-warning {{duplicate 'read_write' declaration specifier}} -// expected-note@-74 {{previously declared 'read_write' here}} +// expected-note@-67 {{previously declared 'read_write' here}} +#endif + +#if OPENCL_C_VERSION__ >= 200 +void myPipeWrite(write_only pipe int); // expected-note {{passing argument to parameter here}} +kernel void k14(read_only pipe int p) { + myPipeWrite(p); // expected-error {{passing '__private read_only pipe int' to parameter of incompatible type 'write_only pipe int'}} +} kernel void pipe_ro_twice(read_only read_only pipe int i){} // expected-warning{{duplicate 'read_only' declaration specifier}} // Conflicting access qualifiers @@ -94,7 +96,7 @@ kernel void pipe_ro_twice_typedef(read_only ROPipeInt i){} // expected-warning{{ kernel void pass_ro_typedef_to_wo(ROPipeInt p) { myPipeWrite(p); // expected-error {{passing '__private ROPipeInt' (aka '__private read_only pipe int') to parameter of incompatible type 'write_only pipe int'}} - // expected-note@-25 {{passing argument to parameter here}} + // expected-note@-16 {{passing argument to parameter here}} } #endif diff --git a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl index a5a8382413476..7531e742f0264 100644 --- a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl +++ b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl @@ -4,6 +4,9 @@ // RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=clc++ // RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=clc++ // RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=clc++ +// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space /* OpenCLC v2.0 adds a set of restrictions for conversions between pointers to * different address spaces, mainly described in Sections 6.5.5 and 6.5.6. @@ -17,6 +20,8 @@ * case), and __constant, that should cover all program paths for CL address * space conversions used in initialisations, assignments, casts, comparisons * and arithmetic operations. +* +* OpenCLC v3.0 supports generic address if __opencl_c_generic_address_space feature is supported */ #ifdef GENERIC diff --git a/clang/test/SemaOpenCL/address-spaces.cl b/clang/test/SemaOpenCL/address-spaces.cl index 0219503e66079..61a1c8ec73ee3 100644 --- a/clang/test/SemaOpenCL/address-spaces.cl +++ b/clang/test/SemaOpenCL/address-spaces.cl @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only // RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only +// RUN: %clang_cc1 %s -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space -verify -pedantic -fsyntax-only // RUN: %clang_cc1 %s -cl-std=clc++ -verify -pedantic -fsyntax-only __constant int ci = 1; diff --git a/clang/test/SemaOpenCL/storageclass.cl b/clang/test/SemaOpenCL/storageclass.cl index f35ab9c2e08c1..060aff2354d1d 100644 --- a/clang/test/SemaOpenCL/storageclass.cl +++ b/clang/test/SemaOpenCL/storageclass.cl @@ -1,28 +1,118 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 - +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,-__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=-__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL3.0 -cl-ext=+__opencl_c_program_scope_global_variables,+__opencl_c_generic_address_space static constant int G1 = 0; constant int G2 = 0; -int G3 = 0; // expected-error{{program scope variable must reside in constant address space}} -global int G4 = 0; // expected-error{{program scope variable must reside in constant address space}} -static float g_implicit_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} +int G3 = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + +global int G4 = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + +static float g_implicit_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + static constant float g_constant_static_var = 0; -static global float g_global_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static local float g_local_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static private float g_private_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static generic float g_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}} -extern float g_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}} +static global float g_global_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#endif + +static local float g_local_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#else +// expected-error@-4 {{program scope variable must reside in global or constant address space}} +#endif + +static private float g_private_static_var = 0; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{program scope variable must reside in constant address space}} +#else +// expected-error@-4 {{program scope variable must reside in global or constant address space}} +#endif + +static generic float g_generic_static_var = 0; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{program scope variable must reside in constant address space}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{program scope variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{program scope variable must reside in global or constant address space}} + #endif +#endif + +extern float g_implicit_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#endif + extern constant float g_constant_extern_var; -extern global float g_global_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern local float g_local_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern private float g_private_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern generic float g_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} + +extern global float g_global_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#endif + +extern local float g_local_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#else +// expected-error@-4 {{extern variable must reside in global or constant address space}} +#endif + +extern private float g_private_extern_var; +#ifndef __opencl_c_program_scope_global_variables +// expected-error@-2 {{extern variable must reside in constant address space}} +#else +// expected-error@-4 {{extern variable must reside in global or constant address space}} +#endif + +extern generic float g_generic_extern_var; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{extern variable must reside in constant address space}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{extern variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{extern variable must reside in global or constant address space}} + #endif +#endif void kernel foo(int x) { // static is not allowed at local scope before CL2.0 - static int S1 = 5; // expected-error{{variables in function scope cannot be declared static}} - static constant int S2 = 5; // expected-error{{variables in function scope cannot be declared static}} + static int S1 = 5; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#endif + + static constant int S2 = 5; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#endif constant int L1 = 0; local int L2; @@ -32,12 +122,13 @@ void kernel foo(int x) { constant int L1 = 42; // expected-error {{variables in the constant address space can only be declared in the outermost scope of a kernel function}} } - auto int L3 = 7; // expected-error{{OpenCL C version 1.2 does not support the 'auto' storage class specifier}} + auto int L3 = 7; // expected-error-re{{OpenCL C version {{1.2|3.0}} does not support the 'auto' storage class specifier}} global int L4; // expected-error{{function scope variable cannot be declared in global address space}} __attribute__((address_space(100))) int L5; // expected-error{{automatic variable qualified with an invalid address space}} constant int L6 = x; // expected-error {{initializer element is not a compile-time constant}} global int *constant L7 = &G4; + private int *constant L8 = &x; // expected-error {{initializer element is not a compile-time constant}} constant int *constant L9 = &L1; local int *constant L10 = &L2; // expected-error {{initializer element is not a compile-time constant}} @@ -59,17 +150,106 @@ void f() { __attribute__((address_space(100))) int L4; // expected-error{{automatic variable qualified with an invalid address space}} } - static float l_implicit_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static constant float l_constant_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static global float l_global_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static local float l_local_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static private float l_private_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static generic float l_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{variables in function scope cannot be declared static}} + static float l_implicit_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#endif + + static constant float l_constant_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#endif + + static global float l_global_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#endif + + static local float l_local_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{static local variable must reside in global or constant address space}} +#endif + + static private float l_private_static_var = 0; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{variables in function scope cannot be declared static}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{static local variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{static local variable must reside in global or constant address space}} +#endif + + static generic float l_generic_static_var = 0; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{variables in function scope cannot be declared static}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{static local variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{static local variable must reside in global or constant address space}} + #endif +#endif + + extern float l_implicit_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#endif - extern float l_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}} extern constant float l_constant_extern_var; - extern global float l_global_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern local float l_local_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern private float l_private_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern generic float l_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} + + extern global float l_global_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#endif + + extern local float l_local_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{extern variable must reside in global or constant address space}} +#endif + + extern private float l_private_extern_var; +#if __OPENCL_C_VERSION__ < 300 +// expected-error@-2 {{extern variable must reside in constant address space}} +#elif !defined(__opencl_c_program_scope_global_variables) +// expected-error@-4 {{extern variable must reside in constant address space}} +#elif defined(__opencl_c_program_scope_global_variables) +// expected-error@-6 {{extern variable must reside in global or constant address space}} +#endif + + extern generic float l_generic_extern_var; +#if (__OPENCL_C_VERSION__ < 300) +// expected-error@-2 {{OpenCL C version 1.2 does not support the 'generic' type qualifier}} +// expected-error@-3 {{extern variable must reside in constant address space}} +#elif (__OPENCL_C_VERSION__ == 300) + #if !defined(__opencl_c_generic_address_space) +// expected-error@-6 {{OpenCL C version 3.0 does not support the 'generic' type qualifier}} + #endif + #if !defined(__opencl_c_program_scope_global_variables) +// expected-error@-9 {{extern variable must reside in constant address space}} + #endif + #if defined(__opencl_c_generic_address_space) && defined(__opencl_c_program_scope_global_variables) +// expected-error@-12 {{extern variable must reside in global or constant address space}} + #endif +#endif } diff --git a/clang/test/SemaOpenCL/unsupported-image.cl b/clang/test/SemaOpenCL/unsupported-image.cl index 3aed9c1f13199..9ffbb1aef0c46 100644 --- a/clang/test/SemaOpenCL/unsupported-image.cl +++ b/clang/test/SemaOpenCL/unsupported-image.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -cl-std=CL3.0 -cl-ext=-__opencl_c_images %s +// RUN: %clang_cc1 -triple spir-unknown-unknown -verify -cl-std=CL3.0 -cl-ext=-__opencl_c_images,-__opencl_c_read_write_images %s // RUN: %clang_cc1 -triple spir-unknown-unknown -verify -cl-std=CL3.0 -cl-ext=+__opencl_c_images %s #ifdef __opencl_c_images diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in index f31ede2c39575..7b174e681bf34 100644 --- a/clang/test/lit.site.cfg.py.in +++ b/clang/test/lit.site.cfg.py.in @@ -34,6 +34,7 @@ config.python_executable = "@Python3_EXECUTABLE@" config.use_z3_solver = lit_config.params.get('USE_Z3_SOLVER', "@USE_Z3_SOLVER@") config.has_plugins = @LLVM_ENABLE_PLUGINS@ config.clang_vendor_uti = "@CLANG_VENDOR_UTI@" +config.llvm_external_lit = path(r"@LLVM_EXTERNAL_LIT@") # Support substitution of the tools and libs dirs with user parameters. This is # used when we can't determine the tool dir at configuration time. diff --git a/clang/test/utils/update_cc_test_checks/lit.local.cfg b/clang/test/utils/update_cc_test_checks/lit.local.cfg index cbcc05dff4ca7..14d1ba260bb4a 100644 --- a/clang/test/utils/update_cc_test_checks/lit.local.cfg +++ b/clang/test/utils/update_cc_test_checks/lit.local.cfg @@ -19,7 +19,7 @@ extra_args += ' --opt ' + shell_quote(opt_path) script_path = os.path.join(config.llvm_src_root, 'utils', 'update_cc_test_checks.py') assert os.path.isfile(script_path) -lit = shell_quote(os.path.join(config.llvm_src_root, 'utils', 'lit', 'lit.py')) +lit = config.llvm_external_lit if config.llvm_external_lit else shell_quote(os.path.join(config.llvm_src_root, 'utils', 'lit', 'lit.py')) python = shell_quote(config.python_executable) config.substitutions.append( ('%update_cc_test_checks', "%s %s %s" % ( diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index fa5d7a54f53b4..a5206319bbb6e 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -218,9 +218,10 @@ std::unique_ptr BuildCompilerInstance() { std::unique_ptr BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) { + auto &PP = CI.getPreprocessor(); auto AST = std::make_unique( CI.getLangOpts(), CI.getSourceManager(), - CI.getPreprocessor().getIdentifierTable(), ST, BC); + PP.getIdentifierTable(), ST, BC, PP.TUKind); AST->InitBuiltinTypes(CI.getTarget()); return AST; } diff --git a/clang/tools/clang-refactor/ClangRefactor.cpp b/clang/tools/clang-refactor/ClangRefactor.cpp index 01edad43164fb..eacd00a601dbe 100644 --- a/clang/tools/clang-refactor/ClangRefactor.cpp +++ b/clang/tools/clang-refactor/ClangRefactor.cpp @@ -38,11 +38,11 @@ namespace opts { static cl::OptionCategory CommonRefactorOptions("Refactoring options"); static cl::opt Verbose("v", cl::desc("Use verbose output"), - cl::cat(cl::GeneralCategory), + cl::cat(cl::getGeneralCategory()), cl::sub(*cl::AllSubCommands)); static cl::opt Inplace("i", cl::desc("Inplace edit s"), - cl::cat(cl::GeneralCategory), + cl::cat(cl::getGeneralCategory()), cl::sub(*cl::AllSubCommands)); } // end namespace opts @@ -613,7 +613,7 @@ int main(int argc, const char **argv) { ClangRefactorTool RefactorTool; auto ExpectedParser = CommonOptionsParser::create( - argc, argv, cl::GeneralCategory, cl::ZeroOrMore, + argc, argv, cl::getGeneralCategory(), cl::ZeroOrMore, "Clang-based refactoring tool for C, C++ and Objective-C"); if (!ExpectedParser) { llvm::errs() << ExpectedParser.takeError(); diff --git a/clang/unittests/AST/ASTPrint.h b/clang/unittests/AST/ASTPrint.h index c3b6b842316d9..58364499bcd9f 100644 --- a/clang/unittests/AST/ASTPrint.h +++ b/clang/unittests/AST/ASTPrint.h @@ -19,72 +19,95 @@ namespace clang { -using PolicyAdjusterType = - Optional>; - -static void PrintStmt(raw_ostream &Out, const ASTContext *Context, - const Stmt *S, PolicyAdjusterType PolicyAdjuster) { - assert(S != nullptr && "Expected non-null Stmt"); - PrintingPolicy Policy = Context->getPrintingPolicy(); - if (PolicyAdjuster) - (*PolicyAdjuster)(Policy); - S->printPretty(Out, /*Helper*/ nullptr, Policy); -} +using PrintingPolicyAdjuster = llvm::function_ref; + +template +using NodePrinter = + std::function; +template +using NodeFilter = std::function; + +template class PrintMatch : public ast_matchers::MatchFinder::MatchCallback { + using PrinterT = NodePrinter; + using FilterT = NodeFilter; + SmallString<1024> Printed; - unsigned NumFoundStmts; - PolicyAdjusterType PolicyAdjuster; + unsigned NumFoundNodes; + PrinterT Printer; + FilterT Filter; + PrintingPolicyAdjuster PolicyAdjuster; public: - PrintMatch(PolicyAdjusterType PolicyAdjuster) - : NumFoundStmts(0), PolicyAdjuster(PolicyAdjuster) {} + PrintMatch(PrinterT Printer, PrintingPolicyAdjuster PolicyAdjuster, + FilterT Filter) + : NumFoundNodes(0), Printer(std::move(Printer)), + Filter(std::move(Filter)), PolicyAdjuster(PolicyAdjuster) {} void run(const ast_matchers::MatchFinder::MatchResult &Result) override { - const Stmt *S = Result.Nodes.getNodeAs("id"); - if (!S) + const NodeType *N = Result.Nodes.getNodeAs("id"); + if (!N || !Filter(N)) return; - NumFoundStmts++; - if (NumFoundStmts > 1) + NumFoundNodes++; + if (NumFoundNodes > 1) return; llvm::raw_svector_ostream Out(Printed); - PrintStmt(Out, Result.Context, S, PolicyAdjuster); + Printer(Out, Result.Context, N, PolicyAdjuster); } StringRef getPrinted() const { return Printed; } - unsigned getNumFoundStmts() const { return NumFoundStmts; } + unsigned getNumFoundNodes() const { return NumFoundNodes; } }; -template -::testing::AssertionResult -PrintedStmtMatches(StringRef Code, const std::vector &Args, - const T &NodeMatch, StringRef ExpectedPrinted, - PolicyAdjusterType PolicyAdjuster = None) { +template bool NoNodeFilter(const NodeType *) { + return true; +} - PrintMatch Printer(PolicyAdjuster); +template +::testing::AssertionResult +PrintedNodeMatches(StringRef Code, const std::vector &Args, + const Matcher &NodeMatch, StringRef ExpectedPrinted, + StringRef FileName, NodePrinter Printer, + PrintingPolicyAdjuster PolicyAdjuster = nullptr, + bool AllowError = false, + // Would like to use a lambda for the default value, but that + // trips gcc 7 up. + NodeFilter Filter = &NoNodeFilter) { + + PrintMatch Callback(Printer, PolicyAdjuster, Filter); ast_matchers::MatchFinder Finder; - Finder.addMatcher(NodeMatch, &Printer); + Finder.addMatcher(NodeMatch, &Callback); std::unique_ptr Factory( tooling::newFrontendActionFactory(&Finder)); - if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args)) + bool ToolResult; + if (FileName.empty()) { + ToolResult = tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args); + } else { + ToolResult = + tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName); + } + if (!ToolResult && !AllowError) return testing::AssertionFailure() << "Parsing error in \"" << Code.str() << "\""; - if (Printer.getNumFoundStmts() == 0) - return testing::AssertionFailure() << "Matcher didn't find any statements"; + if (Callback.getNumFoundNodes() == 0) + return testing::AssertionFailure() << "Matcher didn't find any nodes"; - if (Printer.getNumFoundStmts() > 1) + if (Callback.getNumFoundNodes() > 1) return testing::AssertionFailure() - << "Matcher should match only one statement (found " - << Printer.getNumFoundStmts() << ")"; + << "Matcher should match only one node (found " + << Callback.getNumFoundNodes() << ")"; - if (Printer.getPrinted() != ExpectedPrinted) + if (Callback.getPrinted() != ExpectedPrinted) return ::testing::AssertionFailure() << "Expected \"" << ExpectedPrinted.str() << "\", got \"" - << Printer.getPrinted().str() << "\""; + << Callback.getPrinted().str() << "\""; return ::testing::AssertionSuccess(); } diff --git a/clang/unittests/AST/ASTVectorTest.cpp b/clang/unittests/AST/ASTVectorTest.cpp index 7953acb1b4db2..1c17eb9210ac3 100644 --- a/clang/unittests/AST/ASTVectorTest.cpp +++ b/clang/unittests/AST/ASTVectorTest.cpp @@ -29,7 +29,7 @@ class ASTVectorTest : public ::testing::Test { : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()), Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), Idents(LangOpts, nullptr), - Ctxt(LangOpts, SourceMgr, Idents, Sels, Builtins) {} + Ctxt(LangOpts, SourceMgr, Idents, Sels, Builtins, TU_Complete) {} FileSystemOptions FileMgrOpts; FileManager FileMgr; diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index e70d2bef72121..bdc23f33f39b0 100644 --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -18,6 +18,7 @@ // //===----------------------------------------------------------------------===// +#include "ASTPrint.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -32,10 +33,8 @@ using namespace tooling; namespace { -using PrintingPolicyModifier = void (*)(PrintingPolicy &policy); - void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D, - PrintingPolicyModifier PolicyModifier) { + PrintingPolicyAdjuster PolicyModifier) { PrintingPolicy Policy = Context->getPrintingPolicy(); Policy.TerseOutput = true; Policy.Indentation = 0; @@ -44,74 +43,23 @@ void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D, D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false); } -class PrintMatch : public MatchFinder::MatchCallback { - SmallString<1024> Printed; - unsigned NumFoundDecls; - PrintingPolicyModifier PolicyModifier; - -public: - PrintMatch(PrintingPolicyModifier PolicyModifier) - : NumFoundDecls(0), PolicyModifier(PolicyModifier) {} - - void run(const MatchFinder::MatchResult &Result) override { - const Decl *D = Result.Nodes.getNodeAs("id"); - if (!D || D->isImplicit()) - return; - NumFoundDecls++; - if (NumFoundDecls > 1) - return; - - llvm::raw_svector_ostream Out(Printed); - PrintDecl(Out, Result.Context, D, PolicyModifier); - } - - StringRef getPrinted() const { - return Printed; - } - - unsigned getNumFoundDecls() const { - return NumFoundDecls; - } -}; - ::testing::AssertionResult PrintedDeclMatches(StringRef Code, const std::vector &Args, const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, StringRef FileName, - PrintingPolicyModifier PolicyModifier = nullptr, + PrintingPolicyAdjuster PolicyModifier = nullptr, bool AllowError = false) { - PrintMatch Printer(PolicyModifier); - MatchFinder Finder; - Finder.addMatcher(NodeMatch, &Printer); - std::unique_ptr Factory( - newFrontendActionFactory(&Finder)); - - if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName) && - !AllowError) - return testing::AssertionFailure() - << "Parsing error in \"" << Code.str() << "\""; - - if (Printer.getNumFoundDecls() == 0) - return testing::AssertionFailure() - << "Matcher didn't find any declarations"; - - if (Printer.getNumFoundDecls() > 1) - return testing::AssertionFailure() - << "Matcher should match only one declaration " - "(found " << Printer.getNumFoundDecls() << ")"; - - if (Printer.getPrinted() != ExpectedPrinted) - return ::testing::AssertionFailure() - << "Expected \"" << ExpectedPrinted.str() << "\", " - "got \"" << Printer.getPrinted().str() << "\""; - - return ::testing::AssertionSuccess(); + return PrintedNodeMatches( + Code, Args, NodeMatch, ExpectedPrinted, FileName, PrintDecl, + PolicyModifier, AllowError, + // Filter out implicit decls + [](const Decl *D) { return !D->isImplicit(); }); } ::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName, StringRef ExpectedPrinted, - PrintingPolicyModifier PolicyModifier = nullptr) { + PrintingPolicyAdjuster PolicyModifier = nullptr) { std::vector Args(1, "-std=c++98"); return PrintedDeclMatches(Code, Args, namedDecl(hasName(DeclName)).bind("id"), ExpectedPrinted, "input.cc", PolicyModifier); @@ -120,7 +68,7 @@ PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName, ::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, - PrintingPolicyModifier PolicyModifier = nullptr) { + PrintingPolicyAdjuster PolicyModifier = nullptr) { std::vector Args(1, "-std=c++98"); return PrintedDeclMatches(Code, Args, @@ -165,7 +113,7 @@ ::testing::AssertionResult PrintedDeclCXX11nonMSCMatches( ::testing::AssertionResult PrintedDeclCXX17Matches(StringRef Code, const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, - PrintingPolicyModifier PolicyModifier = nullptr) { + PrintingPolicyAdjuster PolicyModifier = nullptr) { std::vector Args{"-std=c++17", "-fno-delayed-template-parsing"}; return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.cc", PolicyModifier); @@ -174,7 +122,7 @@ PrintedDeclCXX17Matches(StringRef Code, const DeclarationMatcher &NodeMatch, ::testing::AssertionResult PrintedDeclC11Matches(StringRef Code, const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, - PrintingPolicyModifier PolicyModifier = nullptr) { + PrintingPolicyAdjuster PolicyModifier = nullptr) { std::vector Args(1, "-std=c11"); return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.c", PolicyModifier); diff --git a/clang/unittests/AST/NamedDeclPrinterTest.cpp b/clang/unittests/AST/NamedDeclPrinterTest.cpp index 1042312e8a730..cd833725b448d 100644 --- a/clang/unittests/AST/NamedDeclPrinterTest.cpp +++ b/clang/unittests/AST/NamedDeclPrinterTest.cpp @@ -15,6 +15,7 @@ // //===----------------------------------------------------------------------===// +#include "ASTPrint.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/PrettyPrinter.h" @@ -66,31 +67,11 @@ ::testing::AssertionResult PrintedDeclMatches( const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, StringRef FileName, std::function Print) { - PrintMatch Printer(std::move(Print)); - MatchFinder Finder; - Finder.addMatcher(NodeMatch, &Printer); - std::unique_ptr Factory = - newFrontendActionFactory(&Finder); - - if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName)) - return testing::AssertionFailure() - << "Parsing error in \"" << Code.str() << "\""; - - if (Printer.getNumFoundDecls() == 0) - return testing::AssertionFailure() - << "Matcher didn't find any named declarations"; - - if (Printer.getNumFoundDecls() > 1) - return testing::AssertionFailure() - << "Matcher should match only one named declaration " - "(found " << Printer.getNumFoundDecls() << ")"; - - if (Printer.getPrinted() != ExpectedPrinted) - return ::testing::AssertionFailure() - << "Expected \"" << ExpectedPrinted.str() << "\", " - "got \"" << Printer.getPrinted().str() << "\""; - - return ::testing::AssertionSuccess(); + return PrintedNodeMatches( + Code, Args, NodeMatch, ExpectedPrinted, FileName, + [Print](llvm::raw_ostream &Out, const ASTContext *Context, + const NamedDecl *ND, + PrintingPolicyAdjuster PolicyAdjuster) { Print(Out, ND); }); } ::testing::AssertionResult diff --git a/clang/unittests/AST/StmtPrinterTest.cpp b/clang/unittests/AST/StmtPrinterTest.cpp index 29cdbf75a00c8..65dfec4cc5b4a 100644 --- a/clang/unittests/AST/StmtPrinterTest.cpp +++ b/clang/unittests/AST/StmtPrinterTest.cpp @@ -38,11 +38,29 @@ DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) { has(compoundStmt(has(stmt().bind("id"))))); } +static void PrintStmt(raw_ostream &Out, const ASTContext *Context, + const Stmt *S, PrintingPolicyAdjuster PolicyAdjuster) { + assert(S != nullptr && "Expected non-null Stmt"); + PrintingPolicy Policy = Context->getPrintingPolicy(); + if (PolicyAdjuster) + PolicyAdjuster(Policy); + S->printPretty(Out, /*Helper*/ nullptr, Policy); +} + +template +::testing::AssertionResult +PrintedStmtMatches(StringRef Code, const std::vector &Args, + const Matcher &NodeMatch, StringRef ExpectedPrinted, + PrintingPolicyAdjuster PolicyAdjuster = nullptr) { + return PrintedNodeMatches(Code, Args, NodeMatch, ExpectedPrinted, "", + PrintStmt, PolicyAdjuster); +} + template ::testing::AssertionResult PrintedStmtCXXMatches(StdVer Standard, StringRef Code, const T &NodeMatch, StringRef ExpectedPrinted, - PolicyAdjusterType PolicyAdjuster = None) { + PrintingPolicyAdjuster PolicyAdjuster = nullptr) { const char *StdOpt; switch (Standard) { case StdVer::CXX98: StdOpt = "-std=c++98"; break; @@ -64,7 +82,7 @@ template ::testing::AssertionResult PrintedStmtMSMatches(StringRef Code, const T &NodeMatch, StringRef ExpectedPrinted, - PolicyAdjusterType PolicyAdjuster = None) { + PrintingPolicyAdjuster PolicyAdjuster = nullptr) { std::vector Args = { "-std=c++98", "-target", "i686-pc-win32", @@ -79,7 +97,7 @@ template ::testing::AssertionResult PrintedStmtObjCMatches(StringRef Code, const T &NodeMatch, StringRef ExpectedPrinted, - PolicyAdjusterType PolicyAdjuster = None) { + PrintingPolicyAdjuster PolicyAdjuster = nullptr) { std::vector Args = { "-ObjC", "-fobjc-runtime=macosx-10.12.0", @@ -202,10 +220,10 @@ class A { }; )"; // No implicit 'this'. - ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11, - CPPSource, memberExpr(anything()).bind("id"), "field", - PolicyAdjusterType( - [](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; }))); + ASSERT_TRUE(PrintedStmtCXXMatches( + StdVer::CXX11, CPPSource, memberExpr(anything()).bind("id"), "field", + + [](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; })); // Print implicit 'this'. ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11, CPPSource, memberExpr(anything()).bind("id"), "this->field")); @@ -222,11 +240,10 @@ class A { @end )"; // No implicit 'self'. - ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"), - "return ivar;\n", - PolicyAdjusterType([](PrintingPolicy &PP) { - PP.SuppressImplicitBase = true; - }))); + ASSERT_TRUE(PrintedStmtObjCMatches( + ObjCSource, returnStmt().bind("id"), "return ivar;\n", + + [](PrintingPolicy &PP) { PP.SuppressImplicitBase = true; })); // Print implicit 'self'. ASSERT_TRUE(PrintedStmtObjCMatches(ObjCSource, returnStmt().bind("id"), "return self->ivar;\n")); @@ -243,5 +260,6 @@ TEST(StmtPrinter, TerseOutputWithLambdas) { // body not printed when TerseOutput is on. ASSERT_TRUE(PrintedStmtCXXMatches( StdVer::CXX11, CPPSource, lambdaExpr(anything()).bind("id"), "[] {}", - PolicyAdjusterType([](PrintingPolicy &PP) { PP.TerseOutput = true; }))); + + [](PrintingPolicy &PP) { PP.TerseOutput = true; })); } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 6747fe749a2fa..eed3ea4cdbe37 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -8209,6 +8209,16 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) { "}\n", Style); + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterFunction = true; + verifyFormat("int f(i);\n" // No break here. + "int\n" // Break here. + "f(i)\n" + "{\n" + " return i + 1;\n" + "}\n", + Style); + Style = getGNUStyle(); // Test for comments at the end of function declarations. diff --git a/clang/unittests/Interpreter/IncrementalProcessingTest.cpp b/clang/unittests/Interpreter/IncrementalProcessingTest.cpp index 7d58d9837b8f6..b7ad468e14c7a 100644 --- a/clang/unittests/Interpreter/IncrementalProcessingTest.cpp +++ b/clang/unittests/Interpreter/IncrementalProcessingTest.cpp @@ -55,23 +55,23 @@ TEST(IncrementalProcessing, EmitCXXGlobalInitFunc) { auto CI = llvm::cantFail(IncrementalCompilerBuilder::create(ClangArgv)); auto Interp = llvm::cantFail(Interpreter::create(std::move(CI))); - std::array Transactions; + std::array PTUs; - Transactions[0] = &llvm::cantFail(Interp->Parse(TestProgram1)); - ASSERT_TRUE(Transactions[0]->TheModule); - ASSERT_TRUE(Transactions[0]->TheModule->getFunction("funcForProg1")); + PTUs[0] = &llvm::cantFail(Interp->Parse(TestProgram1)); + ASSERT_TRUE(PTUs[0]->TheModule); + ASSERT_TRUE(PTUs[0]->TheModule->getFunction("funcForProg1")); - Transactions[1] = &llvm::cantFail(Interp->Parse(TestProgram2)); - ASSERT_TRUE(Transactions[1]->TheModule); - ASSERT_TRUE(Transactions[1]->TheModule->getFunction("funcForProg2")); + PTUs[1] = &llvm::cantFail(Interp->Parse(TestProgram2)); + ASSERT_TRUE(PTUs[1]->TheModule); + ASSERT_TRUE(PTUs[1]->TheModule->getFunction("funcForProg2")); // First code should not end up in second module: - ASSERT_FALSE(Transactions[1]->TheModule->getFunction("funcForProg1")); + ASSERT_FALSE(PTUs[1]->TheModule->getFunction("funcForProg1")); // Make sure global inits exist and are unique: - const Function *GlobalInit1 = getGlobalInit(Transactions[0]->TheModule.get()); + const Function *GlobalInit1 = getGlobalInit(PTUs[0]->TheModule.get()); ASSERT_TRUE(GlobalInit1); - const Function *GlobalInit2 = getGlobalInit(Transactions[1]->TheModule.get()); + const Function *GlobalInit2 = getGlobalInit(PTUs[1]->TheModule.get()); ASSERT_TRUE(GlobalInit2); ASSERT_FALSE(GlobalInit1->getName() == GlobalInit2->getName()); diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp index 984255c0a2290..6ce43748ae049 100644 --- a/clang/unittests/Interpreter/InterpreterTest.cpp +++ b/clang/unittests/Interpreter/InterpreterTest.cpp @@ -37,34 +37,41 @@ createInterpreter(const Args &ExtraArgs = {}, return cantFail(clang::Interpreter::create(std::move(CI))); } +static size_t DeclsSize(TranslationUnitDecl *PTUDecl) { + return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end()); +} + TEST(InterpreterTest, Sanity) { std::unique_ptr Interp = createInterpreter(); - Transaction &R1(cantFail(Interp->Parse("void g(); void g() {}"))); - EXPECT_EQ(2U, R1.Decls.size()); - Transaction &R2(cantFail(Interp->Parse("int i;"))); - EXPECT_EQ(1U, R2.Decls.size()); + using PTU = PartialTranslationUnit; + + PTU &R1(cantFail(Interp->Parse("void g(); void g() {}"))); + EXPECT_EQ(2U, DeclsSize(R1.TUPart)); + + PTU &R2(cantFail(Interp->Parse("int i;"))); + EXPECT_EQ(1U, DeclsSize(R2.TUPart)); } -static std::string DeclToString(DeclGroupRef DGR) { - return llvm::cast(DGR.getSingleDecl())->getQualifiedNameAsString(); +static std::string DeclToString(Decl *D) { + return llvm::cast(D)->getQualifiedNameAsString(); } TEST(InterpreterTest, IncrementalInputTopLevelDecls) { std::unique_ptr Interp = createInterpreter(); - auto R1OrErr = Interp->Parse("int var1 = 42; int f() { return var1; }"); + auto R1 = Interp->Parse("int var1 = 42; int f() { return var1; }"); // gtest doesn't expand into explicit bool conversions. - EXPECT_TRUE(!!R1OrErr); - auto R1 = R1OrErr->Decls; - EXPECT_EQ(2U, R1.size()); - EXPECT_EQ("var1", DeclToString(R1[0])); - EXPECT_EQ("f", DeclToString(R1[1])); - - auto R2OrErr = Interp->Parse("int var2 = f();"); - EXPECT_TRUE(!!R2OrErr); - auto R2 = R2OrErr->Decls; - EXPECT_EQ(1U, R2.size()); - EXPECT_EQ("var2", DeclToString(R2[0])); + EXPECT_TRUE(!!R1); + auto R1DeclRange = R1->TUPart->decls(); + EXPECT_EQ(2U, DeclsSize(R1->TUPart)); + EXPECT_EQ("var1", DeclToString(*R1DeclRange.begin())); + EXPECT_EQ("f", DeclToString(*(++R1DeclRange.begin()))); + + auto R2 = Interp->Parse("int var2 = f();"); + EXPECT_TRUE(!!R2); + auto R2DeclRange = R2->TUPart->decls(); + EXPECT_EQ(1U, DeclsSize(R2->TUPart)); + EXPECT_EQ("var2", DeclToString(*R2DeclRange.begin())); } TEST(InterpreterTest, Errors) { @@ -83,9 +90,8 @@ TEST(InterpreterTest, Errors) { HasSubstr("error: unknown type name 'intentional_error'")); EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err))); -#ifdef GTEST_HAS_DEATH_TEST - EXPECT_DEATH((void)Interp->Parse("int var1 = 42;"), ""); -#endif + auto RecoverErr = Interp->Parse("int var1 = 42;"); + EXPECT_TRUE(!!RecoverErr); } // Here we test whether the user can mix declarations and statements. The @@ -101,21 +107,21 @@ TEST(InterpreterTest, DeclsAndStatements) { DiagnosticsOS, new DiagnosticOptions()); auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get()); - auto R1OrErr = Interp->Parse( + auto R1 = Interp->Parse( "int var1 = 42; extern \"C\" int printf(const char*, ...);"); // gtest doesn't expand into explicit bool conversions. - EXPECT_TRUE(!!R1OrErr); + EXPECT_TRUE(!!R1); - auto R1 = R1OrErr->Decls; - EXPECT_EQ(2U, R1.size()); + auto *PTU1 = R1->TUPart; + EXPECT_EQ(2U, DeclsSize(PTU1)); // FIXME: Add support for wrapping and running statements. - auto R2OrErr = Interp->Parse("var1++; printf(\"var1 value %d\\n\", var1);"); - EXPECT_FALSE(!!R2OrErr); + auto R2 = Interp->Parse("var1++; printf(\"var1 value %d\\n\", var1);"); + EXPECT_FALSE(!!R2); using ::testing::HasSubstr; EXPECT_THAT(DiagnosticsOS.str(), HasSubstr("error: unknown type name 'var1'")); - auto Err = R2OrErr.takeError(); + auto Err = R2.takeError(); EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err))); } diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp index 4cdabe042cc83..319c63f6a50ba 100644 --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -25,6 +25,7 @@ #include "clang/Lex/PreprocessorOptions.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include #include namespace { @@ -65,7 +66,7 @@ class LexerTest : public ::testing::Test { std::vector Lex(StringRef Source) { TrivialModuleLoader ModLoader; - auto PP = CreatePP(Source, ModLoader); + PP = CreatePP(Source, ModLoader); std::vector toks; while (1) { @@ -109,6 +110,7 @@ class LexerTest : public ::testing::Test { LangOptions LangOpts; std::shared_ptr TargetOpts; IntrusiveRefCntPtr Target; + std::unique_ptr PP; }; TEST_F(LexerTest, GetSourceTextExpandsToMaximumInMacroArgument) { @@ -264,12 +266,14 @@ TEST_F(LexerTest, GetSourceTextExpandsRecursively) { TEST_F(LexerTest, LexAPI) { std::vector ExpectedTokens; + // Line 1 (after the #defines) ExpectedTokens.push_back(tok::l_square); ExpectedTokens.push_back(tok::identifier); ExpectedTokens.push_back(tok::r_square); ExpectedTokens.push_back(tok::l_square); ExpectedTokens.push_back(tok::identifier); ExpectedTokens.push_back(tok::r_square); + // Line 2 ExpectedTokens.push_back(tok::identifier); ExpectedTokens.push_back(tok::identifier); ExpectedTokens.push_back(tok::identifier); @@ -357,6 +361,65 @@ TEST_F(LexerTest, LexAPI) { EXPECT_EQ("N", Lexer::getImmediateMacroName(idLoc4, SourceMgr, LangOpts)); } +TEST_F(LexerTest, HandlesSplitTokens) { + std::vector ExpectedTokens; + // Line 1 (after the #defines) + ExpectedTokens.push_back(tok::identifier); + ExpectedTokens.push_back(tok::less); + ExpectedTokens.push_back(tok::identifier); + ExpectedTokens.push_back(tok::less); + ExpectedTokens.push_back(tok::greatergreater); + // Line 2 + ExpectedTokens.push_back(tok::identifier); + ExpectedTokens.push_back(tok::less); + ExpectedTokens.push_back(tok::identifier); + ExpectedTokens.push_back(tok::less); + ExpectedTokens.push_back(tok::greatergreater); + + std::vector toks = CheckLex("#define TY ty\n" + "#define RANGLE ty>\n" + "TY>\n" + "RANGLE", + ExpectedTokens); + + SourceLocation outerTyLoc = toks[0].getLocation(); + SourceLocation innerTyLoc = toks[2].getLocation(); + SourceLocation gtgtLoc = toks[4].getLocation(); + // Split the token to simulate the action of the parser and force creation of + // an `ExpansionTokenRange`. + SourceLocation rangleLoc = PP->SplitToken(gtgtLoc, 1); + + // Verify that it only captures the first greater-then and not the second one. + CharSourceRange range = Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(innerTyLoc, rangleLoc), SourceMgr, + LangOpts); + EXPECT_TRUE(range.isCharRange()); + EXPECT_EQ(range.getAsRange(), + SourceRange(innerTyLoc, gtgtLoc.getLocWithOffset(1))); + + // Verify case where range begins in a macro expansion. + range = Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(outerTyLoc, rangleLoc), SourceMgr, + LangOpts); + EXPECT_TRUE(range.isCharRange()); + EXPECT_EQ(range.getAsRange(), + SourceRange(SourceMgr.getExpansionLoc(outerTyLoc), + gtgtLoc.getLocWithOffset(1))); + + SourceLocation macroInnerTyLoc = toks[7].getLocation(); + SourceLocation macroGtgtLoc = toks[9].getLocation(); + // Split the token to simulate the action of the parser and force creation of + // an `ExpansionTokenRange`. + SourceLocation macroRAngleLoc = PP->SplitToken(macroGtgtLoc, 1); + + // Verify that it fails (because it only captures the first greater-then and + // not the second one, so it doesn't span the entire macro expansion). + range = Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(macroInnerTyLoc, macroRAngleLoc), + SourceMgr, LangOpts); + EXPECT_TRUE(range.isInvalid()); +} + TEST_F(LexerTest, DontMergeMacroArgsFromDifferentMacroFiles) { std::vector toks = Lex("#define helper1 0\n" diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index f92587af8dc5e..bb4098a1f98bd 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -323,7 +323,7 @@ class PPCallbacksTest : public ::testing::Test { // according to LangOptions, so we init Parser to register opencl // pragma handlers ASTContext Context(OpenCLLangOpts, SourceMgr, PP.getIdentifierTable(), - PP.getSelectorTable(), PP.getBuiltinInfo()); + PP.getSelectorTable(), PP.getBuiltinInfo(), PP.TUKind); Context.InitBuiltinTypes(*Target); ASTConsumer Consumer; diff --git a/clang/unittests/Serialization/CMakeLists.txt b/clang/unittests/Serialization/CMakeLists.txt index f143f28e12326..c0a79842525b2 100644 --- a/clang/unittests/Serialization/CMakeLists.txt +++ b/clang/unittests/Serialization/CMakeLists.txt @@ -6,12 +6,14 @@ set(LLVM_LINK_COMPONENTS add_clang_unittest(SerializationTests InMemoryModuleCacheTest.cpp + ModuleCacheTest.cpp ) clang_target_link_libraries(SerializationTests PRIVATE clangAST clangBasic + clangFrontend clangLex clangSema clangSerialization diff --git a/clang/unittests/Serialization/ModuleCacheTest.cpp b/clang/unittests/Serialization/ModuleCacheTest.cpp new file mode 100644 index 0000000000000..6cffbc2c12218 --- /dev/null +++ b/clang/unittests/Serialization/ModuleCacheTest.cpp @@ -0,0 +1,179 @@ +//===- unittests/Serialization/ModuleCacheTest.cpp - CI tests -------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/FileManager.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Lex/HeaderSearch.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +#include "gtest/gtest.h" + +using namespace llvm; +using namespace clang; + +namespace { + +class ModuleCacheTest : public ::testing::Test { + void SetUp() override { + ASSERT_FALSE(sys::fs::createUniqueDirectory("modulecache-test", TestDir)); + + ModuleCachePath = SmallString<256>(TestDir); + sys::path::append(ModuleCachePath, "mcp"); + ASSERT_FALSE(sys::fs::create_directories(ModuleCachePath)); + } + + void TearDown() override { sys::fs::remove_directories(TestDir); } + +public: + SmallString<256> TestDir; + SmallString<256> ModuleCachePath; + + void addFile(StringRef Path, StringRef Contents) { + ASSERT_FALSE(sys::path::is_absolute(Path)); + + SmallString<256> AbsPath(TestDir); + sys::path::append(AbsPath, Path); + + std::error_code EC; + ASSERT_FALSE( + sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath))); + llvm::raw_fd_ostream OS(AbsPath, EC); + ASSERT_FALSE(EC); + OS << Contents; + } + + void addDuplicateFrameworks() { + addFile("test.m", R"cpp( + @import Top; + )cpp"); + + addFile("frameworks/Top.framework/Headers/top.h", R"cpp( + @import M; + )cpp"); + addFile("frameworks/Top.framework/Modules/module.modulemap", R"cpp( + framework module Top [system] { + header "top.h" + export * + } + )cpp"); + + addFile("frameworks/M.framework/Headers/m.h", R"cpp( + void foo(); + )cpp"); + addFile("frameworks/M.framework/Modules/module.modulemap", R"cpp( + framework module M [system] { + header "m.h" + export * + } + )cpp"); + + addFile("frameworks2/M.framework/Headers/m.h", R"cpp( + void foo(); + )cpp"); + addFile("frameworks2/M.framework/Modules/module.modulemap", R"cpp( + framework module M [system] { + header "m.h" + export * + } + )cpp"); + } +}; + +TEST_F(ModuleCacheTest, CachedModuleNewPath) { + addDuplicateFrameworks(); + + SmallString<256> MCPArg("-fmodules-cache-path="); + MCPArg.append(ModuleCachePath); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(new DiagnosticOptions()); + + // First run should pass with no errors + const char *Args[] = {"clang", "-fmodules", "-Fframeworks", + MCPArg.c_str(), "-working-directory", TestDir.c_str(), + "test.m"}; + std::shared_ptr Invocation = + createInvocationFromCommandLine(Args, Diags); + ASSERT_TRUE(Invocation); + CompilerInstance Instance; + Instance.setDiagnostics(Diags.get()); + Instance.setInvocation(Invocation); + SyntaxOnlyAction Action; + ASSERT_TRUE(Instance.ExecuteAction(Action)); + ASSERT_FALSE(Diags->hasErrorOccurred()); + + // Now add `frameworks2` to the search path. `Top.pcm` will have a reference + // to the `M` from `frameworks`, but a search will find the `M` from + // `frameworks2` - causing a mismatch and it to be considered out of date. + // + // Normally this would be fine - `M` and the modules it depends on would be + // rebuilt. However, since we have a shared module cache and thus an already + // finalized `Top`, recompiling `Top` will cause the existing module to be + // removed from the cache, causing possible crashed if it is ever used. + // + // Make sure that an error occurs instead. + const char *Args2[] = {"clang", "-fmodules", "-Fframeworks2", + "-Fframeworks", MCPArg.c_str(), "-working-directory", + TestDir.c_str(), "test.m"}; + std::shared_ptr Invocation2 = + createInvocationFromCommandLine(Args2, Diags); + ASSERT_TRUE(Invocation2); + CompilerInstance Instance2(Instance.getPCHContainerOperations(), + &Instance.getModuleCache()); + Instance2.setDiagnostics(Diags.get()); + Instance2.setInvocation(Invocation2); + SyntaxOnlyAction Action2; + ASSERT_FALSE(Instance2.ExecuteAction(Action2)); + ASSERT_TRUE(Diags->hasErrorOccurred()); +} + +TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) { + addDuplicateFrameworks(); + + SmallString<256> MCPArg("-fmodules-cache-path="); + MCPArg.append(ModuleCachePath); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(new DiagnosticOptions()); + + // First run should pass with no errors + const char *Args[] = {"clang", "-fmodules", "-Fframeworks", + MCPArg.c_str(), "-working-directory", TestDir.c_str(), + "test.m"}; + std::shared_ptr Invocation = + createInvocationFromCommandLine(Args, Diags); + ASSERT_TRUE(Invocation); + CompilerInstance Instance; + Instance.setDiagnostics(Diags.get()); + Instance.setInvocation(Invocation); + SyntaxOnlyAction Action; + ASSERT_TRUE(Instance.ExecuteAction(Action)); + ASSERT_FALSE(Diags->hasErrorOccurred()); + + // Same as `CachedModuleNewPath` but while allowing errors. This is a hard + // failure where the module wasn't created, so it should still fail. + const char *Args2[] = { + "clang", "-fmodules", "-Fframeworks2", + "-Fframeworks", MCPArg.c_str(), "-working-directory", + TestDir.c_str(), "-Xclang", "-fallow-pcm-with-compiler-errors", + "test.m"}; + std::shared_ptr Invocation2 = + createInvocationFromCommandLine(Args2, Diags); + ASSERT_TRUE(Invocation2); + CompilerInstance Instance2(Instance.getPCHContainerOperations(), + &Instance.getModuleCache()); + Instance2.setDiagnostics(Diags.get()); + Instance2.setInvocation(Invocation2); + SyntaxOnlyAction Action2; + ASSERT_FALSE(Instance2.ExecuteAction(Action2)); + ASSERT_TRUE(Diags->hasErrorOccurred()); +} + +} // anonymous namespace diff --git a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp new file mode 100644 index 0000000000000..bc1b8edf05356 --- /dev/null +++ b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "Reusables.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" +#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +using namespace clang; +using namespace ento; +using namespace llvm; + +namespace { + +class InterestingnessTestChecker : public Checker { + BugType BT_TestBug; + + using HandlerFn = std::function; + + CallDescriptionMap Handlers = { + {{"setInteresting", 1}, &InterestingnessTestChecker::handleInteresting}, + {{"setNotInteresting", 1}, + &InterestingnessTestChecker::handleNotInteresting}, + {{"check", 1}, &InterestingnessTestChecker::handleCheck}, + {{"bug", 1}, &InterestingnessTestChecker::handleBug}, + }; + + void handleInteresting(const CallEvent &Call, CheckerContext &C) const; + void handleNotInteresting(const CallEvent &Call, CheckerContext &C) const; + void handleCheck(const CallEvent &Call, CheckerContext &C) const; + void handleBug(const CallEvent &Call, CheckerContext &C) const; + +public: + InterestingnessTestChecker() + : BT_TestBug(this, "InterestingnessTestBug", "Test") {} + + void checkPreCall(const CallEvent &Call, CheckerContext &C) const { + const HandlerFn *Handler = Handlers.lookup(Call); + if (!Handler) + return; + + (*Handler)(this, Call, C); + } +}; + +} // namespace + +void InterestingnessTestChecker::handleInteresting(const CallEvent &Call, + CheckerContext &C) const { + SymbolRef Sym = Call.getArgSVal(0).getAsSymbol(); + assert(Sym); + C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) { + BR.markInteresting(Sym); + return ""; + })); +} + +void InterestingnessTestChecker::handleNotInteresting(const CallEvent &Call, + CheckerContext &C) const { + SymbolRef Sym = Call.getArgSVal(0).getAsSymbol(); + assert(Sym); + C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) { + BR.markNotInteresting(Sym); + return ""; + })); +} + +void InterestingnessTestChecker::handleCheck(const CallEvent &Call, + CheckerContext &C) const { + SymbolRef Sym = Call.getArgSVal(0).getAsSymbol(); + assert(Sym); + C.addTransition(nullptr, C.getNoteTag([Sym](PathSensitiveBugReport &BR) { + if (BR.isInteresting(Sym)) + return "Interesting"; + else + return "NotInteresting"; + })); +} + +void InterestingnessTestChecker::handleBug(const CallEvent &Call, + CheckerContext &C) const { + ExplodedNode *N = C.generateErrorNode(); + C.emitReport( + std::make_unique(BT_TestBug, "test bug", N)); +} + +namespace { + +class TestAction : public ASTFrontendAction { + ExpectedDiagsTy ExpectedDiags; + +public: + TestAction(ExpectedDiagsTy &&ExpectedDiags) + : ExpectedDiags(std::move(ExpectedDiags)) {} + + std::unique_ptr CreateASTConsumer(CompilerInstance &Compiler, + StringRef File) override { + std::unique_ptr AnalysisConsumer = + CreateAnalysisConsumer(Compiler); + AnalysisConsumer->AddDiagnosticConsumer(new VerifyPathDiagnosticConsumer( + std::move(ExpectedDiags), Compiler.getSourceManager())); + AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) { + Registry.addChecker("test.Interestingness", + "Description", ""); + }); + Compiler.getAnalyzerOpts()->CheckersAndPackages = { + {"test.Interestingness", true}}; + return std::move(AnalysisConsumer); + } +}; + +} // namespace + +TEST(BugReportInterestingness, Symbols) { + EXPECT_TRUE(tooling::runToolOnCode( + std::make_unique(ExpectedDiagsTy{ + {{15, 7}, + "test bug", + "test bug", + "test.Interestingness", + "InterestingnessTestBug", + "Test", + { + {{8, 7}, "Interesting", {{{8, 7}, {8, 14}}}}, + {{10, 7}, "NotInteresting", {{{10, 7}, {10, 14}}}}, + {{12, 7}, "Interesting", {{{12, 7}, {12, 14}}}}, + {{14, 7}, "NotInteresting", {{{14, 7}, {14, 14}}}}, + {{15, 7}, "test bug", {{{15, 7}, {15, 12}}}}, + }}}), + R"( + void setInteresting(int); + void setNotInteresting(int); + void check(int); + void bug(int); + + void f(int A) { + check(A); + setInteresting(A); + check(A); + setNotInteresting(A); + check(A); + setInteresting(A); + check(A); + bug(A); + } + )", + "input.cpp")); +} diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index 4de6bec4d2167..d131e03057b5d 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS add_clang_unittest(StaticAnalysisTests AnalyzerOptionsTest.cpp + BugReportInterestingnessTest.cpp CallDescriptionTest.cpp CallEventTest.cpp FalsePositiveRefutationBRVisitorTest.cpp diff --git a/clang/unittests/StaticAnalyzer/Reusables.h b/clang/unittests/StaticAnalyzer/Reusables.h index 3f2fd61642008..609983e783ffd 100644 --- a/clang/unittests/StaticAnalyzer/Reusables.h +++ b/clang/unittests/StaticAnalyzer/Reusables.h @@ -10,9 +10,10 @@ #define LLVM_CLANG_UNITTESTS_STATICANALYZER_REUSABLES_H #include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Frontend/CompilerInstance.h" #include "clang/CrossTU/CrossTranslationUnit.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "gtest/gtest.h" namespace clang { namespace ento { @@ -66,6 +67,88 @@ class ExprEngineConsumer : public ASTConsumer { Eng(CTU, AMgr, &VisitedCallees, &FS, ExprEngine::Inline_Regular) {} }; +struct ExpectedLocationTy { + unsigned Line; + unsigned Column; + + void testEquality(SourceLocation L, SourceManager &SM) const { + EXPECT_EQ(SM.getSpellingLineNumber(L), Line); + EXPECT_EQ(SM.getSpellingColumnNumber(L), Column); + } +}; + +struct ExpectedRangeTy { + ExpectedLocationTy Begin; + ExpectedLocationTy End; + + void testEquality(SourceRange R, SourceManager &SM) const { + Begin.testEquality(R.getBegin(), SM); + End.testEquality(R.getEnd(), SM); + } +}; + +struct ExpectedPieceTy { + ExpectedLocationTy Loc; + std::string Text; + std::vector Ranges; + + void testEquality(const PathDiagnosticPiece &Piece, SourceManager &SM) { + Loc.testEquality(Piece.getLocation().asLocation(), SM); + EXPECT_EQ(Piece.getString(), Text); + EXPECT_EQ(Ranges.size(), Piece.getRanges().size()); + for (const auto &RangeItem : llvm::enumerate(Piece.getRanges())) + Ranges[RangeItem.index()].testEquality(RangeItem.value(), SM); + } +}; + +struct ExpectedDiagTy { + ExpectedLocationTy Loc; + std::string VerboseDescription; + std::string ShortDescription; + std::string CheckerName; + std::string BugType; + std::string Category; + std::vector Path; + + void testEquality(const PathDiagnostic &Diag, SourceManager &SM) { + Loc.testEquality(Diag.getLocation().asLocation(), SM); + EXPECT_EQ(Diag.getVerboseDescription(), VerboseDescription); + EXPECT_EQ(Diag.getShortDescription(), ShortDescription); + EXPECT_EQ(Diag.getCheckerName(), CheckerName); + EXPECT_EQ(Diag.getBugType(), BugType); + EXPECT_EQ(Diag.getCategory(), Category); + + EXPECT_EQ(Path.size(), Diag.path.size()); + for (const auto &PieceItem : llvm::enumerate(Diag.path)) { + if (PieceItem.index() < Path.size()) + Path[PieceItem.index()].testEquality(*PieceItem.value(), SM); + } + } +}; + +using ExpectedDiagsTy = std::vector; + +// A consumer to verify the generated diagnostics. +class VerifyPathDiagnosticConsumer : public PathDiagnosticConsumer { + ExpectedDiagsTy ExpectedDiags; + SourceManager &SM; + +public: + VerifyPathDiagnosticConsumer(ExpectedDiagsTy &&ExpectedDiags, + SourceManager &SM) + : ExpectedDiags(ExpectedDiags), SM(SM) {} + + StringRef getName() const override { return "verify test diagnostics"; } + + void FlushDiagnosticsImpl(std::vector &Diags, + FilesMade *filesMade) override { + EXPECT_EQ(Diags.size(), ExpectedDiags.size()); + for (const auto &Item : llvm::enumerate(Diags)) + if (Item.index() < ExpectedDiags.size()) + ExpectedDiags[Item.index()].testEquality(*Item.value(), SM); + } +}; + } // namespace ento } // namespace clang diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index ea855314baca7..caa3163ed16db 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -170,9 +170,10 @@ class RVVIntrinsic { public: RVVIntrinsic(StringRef Name, StringRef Suffix, StringRef MangledName, - StringRef IRName, bool HasSideEffects, bool IsMask, - bool HasMaskedOffOperand, bool HasVL, bool HasNoMaskedOverloaded, - bool HasAutoDef, StringRef ManualCodegen, const RVVTypes &Types, + StringRef MangledSuffix, StringRef IRName, bool HasSideEffects, + bool IsMask, bool HasMaskedOffOperand, bool HasVL, + bool HasNoMaskedOverloaded, bool HasAutoDef, + StringRef ManualCodegen, const RVVTypes &Types, const std::vector &IntrinsicTypes, StringRef RequiredExtension, unsigned NF); ~RVVIntrinsic() = default; @@ -751,8 +752,8 @@ void RVVType::applyModifier(StringRef Transformer) { // RVVIntrinsic implementation //===----------------------------------------------------------------------===// RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix, - StringRef NewMangledName, StringRef IRName, - bool HasSideEffects, bool IsMask, + StringRef NewMangledName, StringRef MangledSuffix, + StringRef IRName, bool HasSideEffects, bool IsMask, bool HasMaskedOffOperand, bool HasVL, bool HasNoMaskedOverloaded, bool HasAutoDef, StringRef ManualCodegen, const RVVTypes &OutInTypes, @@ -771,6 +772,8 @@ RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix, MangledName = NewMangledName.str(); if (!Suffix.empty()) Name += "_" + Suffix.str(); + if (!MangledSuffix.empty()) + MangledName += "_" + MangledSuffix.str(); if (IsMask) { Name += "_m"; } @@ -1073,6 +1076,7 @@ void RVVEmitter::createRVVIntrinsics( StringRef Name = R->getValueAsString("Name"); StringRef SuffixProto = R->getValueAsString("Suffix"); StringRef MangledName = R->getValueAsString("MangledName"); + StringRef MangledSuffixProto = R->getValueAsString("MangledSuffix"); StringRef Prototypes = R->getValueAsString("Prototype"); StringRef TypeRange = R->getValueAsString("TypeRange"); bool HasMask = R->getValueAsBit("HasMask"); @@ -1147,19 +1151,20 @@ void RVVEmitter::createRVVIntrinsics( continue; auto SuffixStr = getSuffixStr(I, Log2LMUL, SuffixProto); + auto MangledSuffixStr = getSuffixStr(I, Log2LMUL, MangledSuffixProto); // Create a non-mask intrinsic Out.push_back(std::make_unique( - Name, SuffixStr, MangledName, IRName, HasSideEffects, - /*IsMask=*/false, /*HasMaskedOffOperand=*/false, HasVL, - HasNoMaskedOverloaded, HasAutoDef, ManualCodegen, Types.getValue(), - IntrinsicTypes, RequiredExtension, NF)); + Name, SuffixStr, MangledName, MangledSuffixStr, IRName, + HasSideEffects, /*IsMask=*/false, /*HasMaskedOffOperand=*/false, + HasVL, HasNoMaskedOverloaded, HasAutoDef, ManualCodegen, + Types.getValue(), IntrinsicTypes, RequiredExtension, NF)); if (HasMask) { // Create a mask intrinsic Optional MaskTypes = computeTypes(I, Log2LMUL, NF, ProtoMaskSeq); Out.push_back(std::make_unique( - Name, SuffixStr, MangledName, IRNameMask, HasSideEffects, - /*IsMask=*/true, HasMaskedOffOperand, HasVL, + Name, SuffixStr, MangledName, MangledSuffixStr, IRNameMask, + HasSideEffects, /*IsMask=*/true, HasMaskedOffOperand, HasVL, HasNoMaskedOverloaded, HasAutoDef, ManualCodegenMask, MaskTypes.getValue(), IntrinsicTypes, RequiredExtension, NF)); } diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 8de688189e297..2ad2047f68d00 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1296,7 +1296,7 @@

C++2b implementation status

Narrowing contextual conversions to bool
P1401R5 - No + Clang 13 Trimming whitespaces before line splicing diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 782d34c610b8c..84429052af5e4 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -360,11 +360,14 @@ endif() append_list_if(COMPILER_RT_DEBUG -DSANITIZER_DEBUG=1 SANITIZER_COMMON_CFLAGS) if(CMAKE_CXX_COMPILER_ID MATCHES Clang) - list(APPEND SANITIZER_COMMON_CFLAGS + list(APPEND THREAD_SAFETY_FLAGS "-Werror=thread-safety" "-Werror=thread-safety-reference" "-Werror=thread-safety-beta" -) + ) + list(APPEND SANITIZER_COMMON_CFLAGS ${THREAD_SAFETY_FLAGS}) + string(REPLACE ";" " " thread_safety_flags_space_sep "${THREAD_SAFETY_FLAGS}") + string(APPEND COMPILER_RT_TEST_COMPILER_CFLAGS " ${thread_safety_flags_space_sep}") endif() # If we're using MSVC, diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index 1e9e7c58664b6..bc69ec95c4195 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -371,7 +371,7 @@ function(add_compiler_rt_runtime name type) add_custom_command(TARGET ${libname} POST_BUILD COMMAND codesign --sign - $ - WORKING_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR} + WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR} ) endif() endif() @@ -511,7 +511,7 @@ macro(add_compiler_rt_resource_file target_name file_name component) add_custom_target(${target_name} DEPENDS ${dst_file}) # Install in Clang resource directory. install(FILES ${file_name} - DESTINATION ${COMPILER_RT_INSTALL_PATH}/share + DESTINATION ${COMPILER_RT_INSTALL_DATA_DIR} COMPONENT ${component}) add_dependencies(${component} ${target_name}) @@ -528,7 +528,7 @@ macro(add_compiler_rt_script name) add_custom_target(${name} DEPENDS ${dst}) install(FILES ${dst} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin) + DESTINATION ${COMPILER_RT_INSTALL_BINARY_DIR}) endmacro(add_compiler_rt_script src name) # Builds custom version of libc++ and installs it in . diff --git a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake index a38ad8c55af03..380ae031a0fea 100644 --- a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake @@ -457,8 +457,8 @@ macro(darwin_add_builtin_libraries) PARENT_TARGET builtins LIPO_FLAGS ${${os}_cc_kext_lipo_flags} DEPENDS ${${os}_cc_kext_libs} - OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR} - INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR}) + OUTPUT_DIR ${COMPILER_RT_OUTPUT_LIBRARY_DIR} + INSTALL_DIR ${COMPILER_RT_INSTALL_LIBRARY_DIR}) endif() endforeach() @@ -467,8 +467,8 @@ macro(darwin_add_builtin_libraries) PARENT_TARGET builtins LIPO_FLAGS ${${os}_builtins_lipo_flags} DEPENDS ${${os}_builtins_libs} - OUTPUT_DIR ${COMPILER_RT_LIBRARY_OUTPUT_DIR} - INSTALL_DIR ${COMPILER_RT_LIBRARY_INSTALL_DIR}) + OUTPUT_DIR ${COMPILER_RT_OUTPUT_LIBRARY_DIR} + INSTALL_DIR ${COMPILER_RT_INSTALL_LIBRARY_DIR}) endforeach() darwin_add_embedded_builtin_libraries() endmacro() @@ -506,9 +506,9 @@ macro(darwin_add_embedded_builtin_libraries) set(DARWIN_macho_embedded_ARCHS armv6m armv7m armv7em armv7 i386 x86_64) set(DARWIN_macho_embedded_LIBRARY_OUTPUT_DIR - ${COMPILER_RT_OUTPUT_DIR}/lib/macho_embedded) + ${COMPILER_RT_OUTPUT_LIBRARY_DIR}/macho_embedded) set(DARWIN_macho_embedded_LIBRARY_INSTALL_DIR - ${COMPILER_RT_INSTALL_PATH}/lib/macho_embedded) + ${COMPILER_RT_INSTALL_LIBRARY_DIR}/macho_embedded) set(CFLAGS_armv7 "-target thumbv7-apple-darwin-eabi") set(CFLAGS_i386 "-march=pentium") diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index 88ee021fe68c9..5543e3c6afc62 100644 --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -498,18 +498,18 @@ endfunction() function(get_compiler_rt_install_dir arch install_dir) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) get_compiler_rt_target(${arch} target) - set(${install_dir} ${COMPILER_RT_INSTALL_PATH}/lib/${target} PARENT_SCOPE) + set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR}/${target} PARENT_SCOPE) else() - set(${install_dir} ${COMPILER_RT_LIBRARY_INSTALL_DIR} PARENT_SCOPE) + set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR} PARENT_SCOPE) endif() endfunction() function(get_compiler_rt_output_dir arch output_dir) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) get_compiler_rt_target(${arch} target) - set(${output_dir} ${COMPILER_RT_OUTPUT_DIR}/lib/${target} PARENT_SCOPE) + set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR}/${target} PARENT_SCOPE) else() - set(${output_dir} ${COMPILER_RT_LIBRARY_OUTPUT_DIR} PARENT_SCOPE) + set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR} PARENT_SCOPE) endif() endfunction() diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake index 1edab43e7c0dd..c11342e68813b 100644 --- a/compiler-rt/cmake/base-config-ix.cmake +++ b/compiler-rt/cmake/base-config-ix.cmake @@ -68,8 +68,8 @@ else() "Path where built compiler-rt libraries should be stored.") set(COMPILER_RT_EXEC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin CACHE PATH "Path where built compiler-rt executables should be stored.") - set(COMPILER_RT_INSTALL_PATH ${CMAKE_INSTALL_PREFIX} CACHE PATH - "Path where built compiler-rt libraries should be installed.") + set(COMPILER_RT_INSTALL_PATH "" CACHE PATH + "Prefix for directories where built compiler-rt artifacts should be installed.") option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests." OFF) option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" OFF) # Use a host compiler to compile/link tests. @@ -85,20 +85,45 @@ else() set(COMPILER_RT_TEST_COMPILER_ID GNU) endif() +function(extend_install_path joined_path current_segment) + if("${current_segment}" STREQUAL "") + set(temp_path "${COMPILER_RT_INSTALL_PATH}") + elseif("${COMPILER_RT_INSTALL_PATH}" STREQUAL "") + set(temp_path "${current_segment}") + elseif(IS_ABSOLUTE "${current_segment}") + message(WARNING "Since \"${current_segment}\" is absolute, it overrides COMPILER_RT_INSTALL_PATH: \"${COMPILER_RT_INSTALL_PATH}\".") + set(temp_path "${current_segment}") + else() + set(temp_path "${COMPILER_RT_INSTALL_PATH}/${current_segment}") + endif() + set(${joined_path} "${temp_path}" PARENT_SCOPE) +endfunction() + if(NOT DEFINED COMPILER_RT_OS_DIR) string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR) endif() if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(COMPILER_RT_LIBRARY_OUTPUT_DIR - ${COMPILER_RT_OUTPUT_DIR}) - set(COMPILER_RT_LIBRARY_INSTALL_DIR - ${COMPILER_RT_INSTALL_PATH}) -else(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) - set(COMPILER_RT_LIBRARY_OUTPUT_DIR + set(COMPILER_RT_OUTPUT_LIBRARY_DIR + ${COMPILER_RT_OUTPUT_DIR}/lib) + extend_install_path(default_install_path lib) + set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH + "Path where built compiler-rt libraries should be installed.") +else(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + set(COMPILER_RT_OUTPUT_LIBRARY_DIR ${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR}) - set(COMPILER_RT_LIBRARY_INSTALL_DIR - ${COMPILER_RT_INSTALL_PATH}/lib/${COMPILER_RT_OS_DIR}) + extend_install_path(default_install_path "lib/${COMPILER_RT_OS_DIR}") + set(COMPILER_RT_INSTALL_LIBRARY_DIR "${default_install_path}" CACHE PATH + "Path where built compiler-rt libraries should be installed.") endif() +extend_install_path(default_install_path bin) +set(COMPILER_RT_INSTALL_BINARY_DIR "${default_install_path}" CACHE PATH + "Path where built compiler-rt executables should be installed.") +extend_install_path(default_install_path include) +set(COMPILER_RT_INSTALL_INCLUDE_DIR "${default_install_path}" CACHE PATH + "Path where compiler-rt headers should be installed.") +extend_install_path(default_install_path share) +set(COMPILER_RT_INSTALL_DATA_DIR "${default_install_path}" CACHE PATH + "Path where compiler-rt data files should be installed.") if(APPLE) # On Darwin if /usr/include/c++ doesn't exist, the user probably has Xcode but diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 9b27631f4af9b..6f13acfa27579 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -329,7 +329,7 @@ set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64}) set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64} ${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9}) -set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64}) +set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64} ${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9}) set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}) diff --git a/compiler-rt/docs/BuildingCompilerRT.rst b/compiler-rt/docs/BuildingCompilerRT.rst new file mode 100644 index 0000000000000..2ab6f083fc6ab --- /dev/null +++ b/compiler-rt/docs/BuildingCompilerRT.rst @@ -0,0 +1,92 @@ +.. _BuildingCompilerRT: + +=============== +Building Compiler-RT +=============== + +.. contents:: + :local: + +.. _build instructions: + +The instructions on this page are aimed at vendors who ship Compiler-RT as part of an +operating system distribution, a toolchain or similar shipping vehicules. If you +are a user merely trying to use Compiler-RT in your program, you most likely want to +refer to your vendor's documentation, or to the general documentation for using +LLVM, Clang, the various santizers, etc. + +CMake Options +============= + +Here are some of the CMake variables that are used often, along with a +brief explanation and LLVM-specific notes. For full documentation, check the +CMake docs or execute ``cmake --help-variable VARIABLE_NAME``. + +**CMAKE_BUILD_TYPE**:STRING + Sets the build type for ``make`` based generators. Possible values are + Release, Debug, RelWithDebInfo and MinSizeRel. On systems like Visual Studio + the user sets the build type with the IDE settings. + +**CMAKE_INSTALL_PREFIX**:PATH + Path where LLVM will be installed if "make install" is invoked or the + "INSTALL" target is built. + +**CMAKE_CXX_COMPILER**:STRING + The C++ compiler to use when building and testing Compiler-RT. + + +.. _compiler-rt-specific options: + +Compiler-RT specific options +----------------------- + +.. option:: COMPILER_RT_INSTALL_PATH:PATH + + **Default**: ```` (empty relative path) + + Prefix for directories where built Compiler-RT artifacts should be installed. + Can be an absolute path, like the default empty string, in which case it is + relative ``CMAKE_INSTALL_PREFIX``. If setting a relative path, make sure to + include the ``:PATH`` with your ``-D``, i.e. use + ``-DCOMPILER_RT_INSTALL_PATH:PATH=...`` not + ``-DCOMPILER_RT_INSTALL_PATH=...``, otherwise CMake will convert the + path to an absolute path. + +.. option:: COMPILER_RT_INSTALL_LIBRARY_DIR:PATH + + **Default**: ``lib`` + + Path where built Compiler-RT libraries should be installed. If a relative + path, relative to ``COMPILER_RT_INSTALL_PATH``. + +.. option:: COMPILER_RT_INSTALL_BINARY_DIR:PATH + + **Default**: ``bin`` + + Path where built Compiler-RT executables should be installed. If a relative + path, relative to ``COMPILER_RT_INSTALL_PATH``. + +.. option:: COMPILER_RT_INSTALL_INCLUDE_DIR:PATH + + **Default**: ``include`` + + Path where Compiler-RT headers should be installed. If a relative + path, relative to ``COMPILER_RT_INSTALL_PATH``. + +.. option:: COMPILER_RT_INSTALL_DATA_DIR:PATH + + **Default**: ``share`` + + Path where Compiler-RT data should be installed. If a relative + path, relative to ``COMPILER_RT_INSTALL_PATH``. + +.. _LLVM-specific variables: + +LLVM-specific options +--------------------- + +.. option:: LLVM_LIBDIR_SUFFIX:STRING + + Extra suffix to append to the directory where libraries are to be + installed. On a 64-bit architecture, one could use ``-DLLVM_LIBDIR_SUFFIX=64`` + to install libraries to ``/usr/lib64``. diff --git a/compiler-rt/include/CMakeLists.txt b/compiler-rt/include/CMakeLists.txt index b00e8caa1ddd1..7b415f0b88a37 100644 --- a/compiler-rt/include/CMakeLists.txt +++ b/compiler-rt/include/CMakeLists.txt @@ -69,22 +69,22 @@ set_target_properties(compiler-rt-headers PROPERTIES FOLDER "Compiler-RT Misc") install(FILES ${SANITIZER_HEADERS} COMPONENT compiler-rt-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/sanitizer) + DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/sanitizer) # Install fuzzer headers. install(FILES ${FUZZER_HEADERS} COMPONENT compiler-rt-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/fuzzer) + DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/fuzzer) # Install xray headers. install(FILES ${XRAY_HEADERS} COMPONENT compiler-rt-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/xray) + DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/xray) # Install profile headers. install(FILES ${PROFILE_HEADERS} COMPONENT compiler-rt-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/profile) + DESTINATION ${COMPILER_RT_INSTALL_INCLUDE_DIR}/profile) if (NOT CMAKE_CONFIGURATION_TYPES) # don't add this for IDEs. add_custom_target(install-compiler-rt-headers diff --git a/compiler-rt/lib/dfsan/CMakeLists.txt b/compiler-rt/lib/dfsan/CMakeLists.txt index b06ae472f073d..45cb9c97e2eb5 100644 --- a/compiler-rt/lib/dfsan/CMakeLists.txt +++ b/compiler-rt/lib/dfsan/CMakeLists.txt @@ -65,4 +65,4 @@ add_custom_command(OUTPUT ${dfsan_abilist_filename} DEPENDS done_abilist.txt libc_ubuntu1404_abilist.txt) add_dependencies(dfsan dfsan_abilist) install(FILES ${dfsan_abilist_filename} - DESTINATION ${COMPILER_RT_INSTALL_PATH}/share) + DESTINATION ${COMPILER_RT_INSTALL_DATA_DIR}) diff --git a/compiler-rt/lib/gwp_asan/tests/backtrace.cpp b/compiler-rt/lib/gwp_asan/tests/backtrace.cpp index 4f6364891bfcc..a4eb8eb9b214d 100644 --- a/compiler-rt/lib/gwp_asan/tests/backtrace.cpp +++ b/compiler-rt/lib/gwp_asan/tests/backtrace.cpp @@ -46,6 +46,11 @@ TEST_F(BacktraceGuardedPoolAllocatorDeathTest, DoubleFree) { } TEST_F(BacktraceGuardedPoolAllocatorDeathTest, UseAfterFree) { +#if defined(__linux__) && __ARM_ARCH == 7 + // Incomplete backtrace on Armv7 Linux + GTEST_SKIP(); +#endif + void *Ptr = AllocateMemory(GPA); DeallocateMemory(GPA, Ptr); diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp index 8be2ff2ae2401..cbe0dee66dcda 100644 --- a/compiler-rt/lib/hwasan/hwasan.cpp +++ b/compiler-rt/lib/hwasan/hwasan.cpp @@ -50,6 +50,11 @@ bool hwasan_init_is_running; int hwasan_report_count = 0; +uptr kLowShadowStart; +uptr kLowShadowEnd; +uptr kHighShadowStart; +uptr kHighShadowEnd; + void Flags::SetDefaults() { #define HWASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; #include "hwasan_flags.inc" diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp index e53de53e46d5c..ef6d4d6c7678e 100644 --- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -80,12 +80,29 @@ void GetAllocatorStats(AllocatorStatCounters s) { allocator.GetStats(s); } +uptr GetAliasRegionStart() { +#if defined(HWASAN_ALIASING_MODE) + constexpr uptr kAliasRegionOffset = 1ULL << (kTaggableRegionCheckShift - 1); + uptr AliasRegionStart = + __hwasan_shadow_memory_dynamic_address + kAliasRegionOffset; + + CHECK_EQ(AliasRegionStart >> kTaggableRegionCheckShift, + __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); + CHECK_EQ( + (AliasRegionStart + kAliasRegionOffset - 1) >> kTaggableRegionCheckShift, + __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); + return AliasRegionStart; +#else + return 0; +#endif +} + void HwasanAllocatorInit() { atomic_store_relaxed(&hwasan_allocator_tagging_enabled, !flags()->disable_allocator_tagging); SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); allocator.Init(common_flags()->allocator_release_to_os_interval_ms, - kAliasRegionStart); + GetAliasRegionStart()); for (uptr i = 0; i < sizeof(tail_magic); i++) tail_magic[i] = GetCurrentThread()->GenerateRandomTag(); } diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp index 01d316c0a9ff9..e22723529f449 100644 --- a/compiler-rt/lib/hwasan/hwasan_linux.cpp +++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp @@ -69,15 +69,9 @@ static void ProtectGap(uptr addr, uptr size) { uptr kLowMemStart; uptr kLowMemEnd; -uptr kLowShadowEnd; -uptr kLowShadowStart; -uptr kHighShadowStart; -uptr kHighShadowEnd; uptr kHighMemStart; uptr kHighMemEnd; -uptr kAliasRegionStart; // Always 0 when aliases aren't used. - static void PrintRange(uptr start, uptr end, const char *name) { Printf("|| [%p, %p] || %.*s ||\n", (void *)start, (void *)end, 10, name); } @@ -198,18 +192,6 @@ bool InitShadow() { // High memory starts where allocated shadow allows. kHighMemStart = ShadowToMem(kHighShadowStart); -# if defined(HWASAN_ALIASING_MODE) - constexpr uptr kAliasRegionOffset = 1ULL << (kTaggableRegionCheckShift - 1); - kAliasRegionStart = - __hwasan_shadow_memory_dynamic_address + kAliasRegionOffset; - - CHECK_EQ(kAliasRegionStart >> kTaggableRegionCheckShift, - __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); - CHECK_EQ( - (kAliasRegionStart + kAliasRegionOffset - 1) >> kTaggableRegionCheckShift, - __hwasan_shadow_memory_dynamic_address >> kTaggableRegionCheckShift); -# endif - // Check the sanity of the defined memory ranges (there might be gaps). CHECK_EQ(kHighMemStart % GetMmapGranularity(), 0); CHECK_GT(kHighMemStart, kHighShadowEnd); diff --git a/compiler-rt/lib/hwasan/hwasan_mapping.h b/compiler-rt/lib/hwasan/hwasan_mapping.h index fae66d5719e51..79a143632f6ab 100644 --- a/compiler-rt/lib/hwasan/hwasan_mapping.h +++ b/compiler-rt/lib/hwasan/hwasan_mapping.h @@ -48,8 +48,6 @@ extern uptr kHighShadowEnd; extern uptr kHighMemStart; extern uptr kHighMemEnd; -extern uptr kAliasRegionStart; - inline uptr GetShadowOffset() { return SANITIZER_FUCHSIA ? 0 : __hwasan_shadow_memory_dynamic_address; } @@ -70,6 +68,8 @@ inline bool MemIsShadow(uptr p) { (kHighShadowStart <= p && p <= kHighShadowEnd); } +uptr GetAliasRegionStart(); + } // namespace __hwasan #endif // HWASAN_MAPPING_H diff --git a/compiler-rt/lib/orc/CMakeLists.txt b/compiler-rt/lib/orc/CMakeLists.txt index 417033a206216..0a83787d86232 100644 --- a/compiler-rt/lib/orc/CMakeLists.txt +++ b/compiler-rt/lib/orc/CMakeLists.txt @@ -3,6 +3,9 @@ # ORC runtime library implementation files. set(ORC_SOURCES extensible_rtti.cpp + log_error_to_stderr.cpp + macho_platform.cpp + run_program_wrapper.cpp ) # Implementation files for all ORC architectures. @@ -18,7 +21,9 @@ set(ORC_IMPL_HEADERS compiler.h endianness.h error.h + executor_address.h extensible_rtti.h + macho_platform.h simple_packed_serialization.h stl_extras.h wrapper_function_utils.h diff --git a/compiler-rt/lib/orc/c_api.h b/compiler-rt/lib/orc/c_api.h index 6da616c869aaa..6677da06ede52 100644 --- a/compiler-rt/lib/orc/c_api.h +++ b/compiler-rt/lib/orc/c_api.h @@ -49,7 +49,7 @@ ORC_RT_C_EXTERN_C_BEGIN typedef union { - const char *ValuePtr; + char *ValuePtr; char Value[sizeof(ValuePtr)]; } __orc_rt_CWrapperFunctionResultDataUnion; @@ -94,14 +94,12 @@ __orc_rt_CWrapperFunctionResultInit(__orc_rt_CWrapperFunctionResult *R) { static inline char * __orc_rt_CWrapperFunctionResultAllocate(__orc_rt_CWrapperFunctionResult *R, size_t Size) { - char *DataPtr; R->Size = Size; - if (Size > sizeof(R->Data.Value)) { - DataPtr = (char *)malloc(Size); - R->Data.ValuePtr = DataPtr; - } else - DataPtr = R->Data.Value; - return DataPtr; + if (Size <= sizeof(R->Data.Value)) + return R->Data.Value; + + R->Data.ValuePtr = (char *)malloc(Size); + return R->Data.ValuePtr; } /** @@ -158,7 +156,7 @@ static inline void __orc_rt_DisposeCWrapperFunctionResult(__orc_rt_CWrapperFunctionResult *R) { if (R->Size > sizeof(R->Data.Value) || (R->Size == 0 && R->Data.ValuePtr)) - free((void *)R->Data.ValuePtr); + free(R->Data.ValuePtr); } /** diff --git a/compiler-rt/lib/orc/common.h b/compiler-rt/lib/orc/common.h index 62ff12a365e61..6993d56cadeba 100644 --- a/compiler-rt/lib/orc/common.h +++ b/compiler-rt/lib/orc/common.h @@ -14,6 +14,7 @@ #define ORC_RT_COMMON_H #include "c_api.h" +#include "compiler.h" #include /// Opaque struct for external symbols. @@ -27,8 +28,7 @@ extern "C" void __orc_rt_log_error(const char *ErrMsg); /// This is declared for use by the runtime, but should be implemented in the /// executor or provided by a definition added to the JIT before the runtime /// is loaded. -extern "C" __orc_rt_Opaque __orc_rt_jit_dispatch_ctx - __attribute__((weak_import)); +extern "C" __orc_rt_Opaque __orc_rt_jit_dispatch_ctx WEAK_IMPORT; /// For dispatching calls to the JIT object. /// @@ -37,25 +37,6 @@ extern "C" __orc_rt_Opaque __orc_rt_jit_dispatch_ctx /// is loaded. extern "C" __orc_rt_CWrapperFunctionResult __orc_rt_jit_dispatch(__orc_rt_Opaque *DispatchCtx, const void *FnTag, - const char *Data, size_t Size) - __attribute__((weak_import)); - -namespace __orc_rt { - -/// Must be kept in sync with JITSymbol.h -using JITTargetAddress = uint64_t; - -/// Cast from JITTargetAddress to pointer. -template T jitTargetAddressToPointer(JITTargetAddress Addr) { - static_assert(std::is_pointer::value, "T must be a pointer type"); - return reinterpret_cast(static_cast(Addr)); -} - -/// Cast from pointer to JITTargetAddress. -template JITTargetAddress pointerToJITTargetAddress(T *Ptr) { - return static_cast(reinterpret_cast(Ptr)); -} - -} // end namespace __orc_rt + const char *Data, size_t Size) WEAK_IMPORT; #endif // ORC_RT_COMMON_H diff --git a/compiler-rt/lib/orc/compiler.h b/compiler-rt/lib/orc/compiler.h index fcc4f2011adb4..dfda45f7e16b0 100644 --- a/compiler-rt/lib/orc/compiler.h +++ b/compiler-rt/lib/orc/compiler.h @@ -18,6 +18,10 @@ #define ORC_RT_INTERFACE extern "C" __attribute__((visibility("default"))) #define ORC_RT_HIDDEN __attribute__((visibility("hidden"))) +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + // Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in // C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid. #ifndef ORC_RT_HAS_CPP_ATTRIBUTE @@ -52,4 +56,10 @@ #define ORC_RT_UNLIKELY(EXPR) (EXPR) #endif +#ifdef __APPLE__ +#define WEAK_IMPORT __attribute__((weak_import)) +#else +#define WEAK_IMPORT __attribute__((weak)) +#endif + #endif // ORC_RT_COMPILER_H diff --git a/compiler-rt/lib/orc/executor_address.h b/compiler-rt/lib/orc/executor_address.h new file mode 100644 index 0000000000000..cfe985bdb60f9 --- /dev/null +++ b/compiler-rt/lib/orc/executor_address.h @@ -0,0 +1,208 @@ +//===------ ExecutorAddress.h - Executing process address -------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Represents an address in the executing program. +// +// This file was derived from +// llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h. +// +//===----------------------------------------------------------------------===// + +#ifndef ORC_RT_EXECUTOR_ADDRESS_H +#define ORC_RT_EXECUTOR_ADDRESS_H + +#include "adt.h" +#include "simple_packed_serialization.h" + +#include +#include + +namespace __orc_rt { + +/// Represents the difference between two addresses in the executor process. +class ExecutorAddrDiff { +public: + ExecutorAddrDiff() = default; + explicit ExecutorAddrDiff(uint64_t Value) : Value(Value) {} + + uint64_t getValue() const { return Value; } + +private: + int64_t Value = 0; +}; + +/// Represents an address in the executor process. +class ExecutorAddress { +public: + ExecutorAddress() = default; + explicit ExecutorAddress(uint64_t Addr) : Addr(Addr) {} + + /// Create an ExecutorAddress from the given pointer. + /// Warning: This should only be used when JITing in-process. + template static ExecutorAddress fromPtr(T *Value) { + return ExecutorAddress( + static_cast(reinterpret_cast(Value))); + } + + /// Cast this ExecutorAddress to a pointer of the given type. + /// Warning: This should only be esude when JITing in-process. + template T toPtr() const { + static_assert(std::is_pointer::value, "T must be a pointer type"); + uintptr_t IntPtr = static_cast(Addr); + assert(IntPtr == Addr && + "JITTargetAddress value out of range for uintptr_t"); + return reinterpret_cast(IntPtr); + } + + uint64_t getValue() const { return Addr; } + void setValue(uint64_t Addr) { this->Addr = Addr; } + bool isNull() const { return Addr == 0; } + + explicit operator bool() const { return Addr != 0; } + + friend bool operator==(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr == RHS.Addr; + } + + friend bool operator!=(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr != RHS.Addr; + } + + friend bool operator<(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr < RHS.Addr; + } + + friend bool operator<=(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr <= RHS.Addr; + } + + friend bool operator>(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr > RHS.Addr; + } + + friend bool operator>=(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr >= RHS.Addr; + } + + ExecutorAddress &operator++() { + ++Addr; + return *this; + } + ExecutorAddress &operator--() { + --Addr; + return *this; + } + ExecutorAddress operator++(int) { return ExecutorAddress(Addr++); } + ExecutorAddress operator--(int) { return ExecutorAddress(Addr++); } + + ExecutorAddress &operator+=(const ExecutorAddrDiff Delta) { + Addr += Delta.getValue(); + return *this; + } + + ExecutorAddress &operator-=(const ExecutorAddrDiff Delta) { + Addr -= Delta.getValue(); + return *this; + } + +private: + uint64_t Addr = 0; +}; + +/// Subtracting two addresses yields an offset. +inline ExecutorAddrDiff operator-(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); +} + +/// Adding an offset and an address yields an address. +inline ExecutorAddress operator+(const ExecutorAddress &LHS, + const ExecutorAddrDiff &RHS) { + return ExecutorAddress(LHS.getValue() + RHS.getValue()); +} + +/// Adding an address and an offset yields an address. +inline ExecutorAddress operator+(const ExecutorAddrDiff &LHS, + const ExecutorAddress &RHS) { + return ExecutorAddress(LHS.getValue() + RHS.getValue()); +} + +/// Represents an address range in the exceutor process. +struct ExecutorAddressRange { + ExecutorAddressRange() = default; + ExecutorAddressRange(ExecutorAddress StartAddress, ExecutorAddress EndAddress) + : StartAddress(StartAddress), EndAddress(EndAddress) {} + + bool empty() const { return StartAddress == EndAddress; } + ExecutorAddrDiff size() const { return EndAddress - StartAddress; } + + template span toSpan() const { + assert(size().getValue() % sizeof(T) == 0 && + "AddressRange is not a multiple of sizeof(T)"); + return span(StartAddress.toPtr(), size().getValue() / sizeof(T)); + } + + ExecutorAddress StartAddress; + ExecutorAddress EndAddress; +}; + +/// SPS serializatior for ExecutorAddress. +template <> class SPSSerializationTraits { +public: + static size_t size(const ExecutorAddress &EA) { + return SPSArgList::size(EA.getValue()); + } + + static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddress &EA) { + return SPSArgList::serialize(BOB, EA.getValue()); + } + + static bool deserialize(SPSInputBuffer &BIB, ExecutorAddress &EA) { + uint64_t Tmp; + if (!SPSArgList::deserialize(BIB, Tmp)) + return false; + EA = ExecutorAddress(Tmp); + return true; + } +}; + +using SPSExecutorAddressRange = + SPSTuple; + +/// Serialization traits for address ranges. +template <> +class SPSSerializationTraits { +public: + static size_t size(const ExecutorAddressRange &Value) { + return SPSArgList::size( + Value.StartAddress, Value.EndAddress); + } + + static bool serialize(SPSOutputBuffer &BOB, + const ExecutorAddressRange &Value) { + return SPSArgList::serialize( + BOB, Value.StartAddress, Value.EndAddress); + } + + static bool deserialize(SPSInputBuffer &BIB, ExecutorAddressRange &Value) { + return SPSArgList::deserialize( + BIB, Value.StartAddress, Value.EndAddress); + } +}; + +using SPSExecutorAddressRangeSequence = SPSSequence; + +} // End namespace __orc_rt + +#endif // ORC_RT_EXECUTOR_ADDRESS_H diff --git a/compiler-rt/lib/orc/log_error_to_stderr.cpp b/compiler-rt/lib/orc/log_error_to_stderr.cpp new file mode 100644 index 0000000000000..4fabbc0d212a0 --- /dev/null +++ b/compiler-rt/lib/orc/log_error_to_stderr.cpp @@ -0,0 +1,19 @@ +//===-- log_error_to_stderr.cpp -------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of the ORC runtime support library. +// +//===----------------------------------------------------------------------===// + +#include "compiler.h" + +#include + +ORC_RT_INTERFACE void __orc_rt_log_error_to_stderr(const char *ErrMsg) { + fprintf(stderr, "orc runtime error: %s\n", ErrMsg); +} diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp new file mode 100644 index 0000000000000..c9792f3a7599a --- /dev/null +++ b/compiler-rt/lib/orc/macho_platform.cpp @@ -0,0 +1,480 @@ +//===- macho_platform.cpp -------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains code required to load the rest of the MachO runtime. +// +//===----------------------------------------------------------------------===// + +#include "macho_platform.h" +#include "common.h" +#include "error.h" +#include "wrapper_function_utils.h" + +#include +#include +#include +#include +#include + +using namespace __orc_rt; +using namespace __orc_rt::macho; + +// Declare function tags for functions in the JIT process. +extern "C" char __orc_rt_macho_get_initializers_tag; +char __orc_rt_macho_get_initializers_tag = 0; + +extern "C" char __orc_rt_macho_get_deinitializers_tag; +char __orc_rt_macho_get_deinitializers_tag = 0; + +extern "C" char __orc_rt_macho_symbol_lookup_tag; +char __orc_rt_macho_symbol_lookup_tag = 0; + +// eh-frame registration functions. +// We expect these to be available for all processes. +extern "C" void __register_frame(const void *); +extern "C" void __deregister_frame(const void *); + +namespace { + +template +void walkEHFrameSection(span EHFrameSection, + HandleFDEFn HandleFDE) { + const char *CurCFIRecord = EHFrameSection.data(); + uint64_t Size = *reinterpret_cast(CurCFIRecord); + + while (CurCFIRecord != EHFrameSection.end() && Size != 0) { + const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4); + if (Size == 0xffffffff) + Size = *reinterpret_cast(CurCFIRecord + 4) + 12; + else + Size += 4; + uint32_t Offset = *reinterpret_cast(OffsetField); + + if (Offset != 0) + HandleFDE(CurCFIRecord); + + CurCFIRecord += Size; + Size = *reinterpret_cast(CurCFIRecord); + } +} + +Error validatePointerSectionExtent(const char *SectionName, + const ExecutorAddressRange &SE) { + if (SE.size().getValue() % sizeof(uintptr_t)) { + std::ostringstream ErrMsg; + ErrMsg << std::hex << "Size of " << SectionName << " 0x" + << SE.StartAddress.getValue() << " -- 0x" << SE.EndAddress.getValue() + << " is not a pointer multiple"; + return make_error(ErrMsg.str()); + } + return Error::success(); +} + +Error runModInits(const std::vector &ModInitsSections, + const MachOJITDylibInitializers &MOJDIs) { + + for (const auto &ModInits : ModInitsSections) { + if (auto Err = validatePointerSectionExtent("__mod_inits", ModInits)) + return Err; + + using InitFunc = void (*)(); + for (auto *Init : ModInits.toSpan()) + (*Init)(); + } + + return Error::success(); +} + +class MachOPlatformRuntimeState { +private: + struct AtExitEntry { + void (*Func)(void *); + void *Arg; + }; + + using AtExitsVector = std::vector; + + struct PerJITDylibState { + void *Header = nullptr; + size_t RefCount = 0; + bool AllowReinitialization = false; + AtExitsVector AtExits; + }; + +public: + static void initialize(); + static MachOPlatformRuntimeState &get(); + static void destroy(); + + MachOPlatformRuntimeState() = default; + + // Delete copy and move constructors. + MachOPlatformRuntimeState(const MachOPlatformRuntimeState &) = delete; + MachOPlatformRuntimeState & + operator=(const MachOPlatformRuntimeState &) = delete; + MachOPlatformRuntimeState(MachOPlatformRuntimeState &&) = delete; + MachOPlatformRuntimeState &operator=(MachOPlatformRuntimeState &&) = delete; + + Error registerObjectSections(MachOPerObjectSectionsToRegister POSR); + Error deregisterObjectSections(MachOPerObjectSectionsToRegister POSR); + + const char *dlerror(); + void *dlopen(string_view Name, int Mode); + int dlclose(void *DSOHandle); + void *dlsym(void *DSOHandle, string_view Symbol); + + int registerAtExit(void (*F)(void *), void *Arg, void *DSOHandle); + void runAtExits(void *DSOHandle); + +private: + PerJITDylibState *getJITDylibStateByHeaderAddr(void *DSOHandle); + PerJITDylibState *getJITDylibStateByName(string_view Path); + PerJITDylibState &getOrCreateJITDylibState(MachOJITDylibInitializers &MOJDIs); + + Expected lookupSymbolInJITDylib(void *DSOHandle, + string_view Symbol); + + Expected + getJITDylibInitializersByName(string_view Path); + Expected dlopenInitialize(string_view Path, int Mode); + Error initializeJITDylib(MachOJITDylibInitializers &MOJDIs); + + static MachOPlatformRuntimeState *MOPS; + + using InitSectionHandler = + Error (*)(const std::vector &Sections, + const MachOJITDylibInitializers &MOJDIs); + const std::vector> InitSections = { + {"__DATA,__mod_init_func", runModInits}}; + + // FIXME: Move to thread-state. + std::string DLFcnError; + + std::recursive_mutex JDStatesMutex; + std::unordered_map JDStates; + std::unordered_map JDNameToHeader; +}; + +MachOPlatformRuntimeState *MachOPlatformRuntimeState::MOPS = nullptr; + +void MachOPlatformRuntimeState::initialize() { + assert(!MOPS && "MachOPlatformRuntimeState should be null"); + MOPS = new MachOPlatformRuntimeState(); +} + +MachOPlatformRuntimeState &MachOPlatformRuntimeState::get() { + assert(MOPS && "MachOPlatformRuntimeState not initialized"); + return *MOPS; +} + +void MachOPlatformRuntimeState::destroy() { + assert(MOPS && "MachOPlatformRuntimeState not initialized"); + delete MOPS; +} + +Error MachOPlatformRuntimeState::registerObjectSections( + MachOPerObjectSectionsToRegister POSR) { + if (POSR.EHFrameSection.StartAddress) + walkEHFrameSection(POSR.EHFrameSection.toSpan(), + __register_frame); + + return Error::success(); +} + +Error MachOPlatformRuntimeState::deregisterObjectSections( + MachOPerObjectSectionsToRegister POSR) { + if (POSR.EHFrameSection.StartAddress) + walkEHFrameSection(POSR.EHFrameSection.toSpan(), + __deregister_frame); + + return Error::success(); +} + +const char *MachOPlatformRuntimeState::dlerror() { return DLFcnError.c_str(); } + +void *MachOPlatformRuntimeState::dlopen(string_view Path, int Mode) { + std::lock_guard Lock(JDStatesMutex); + + // Use fast path if all JITDylibs are already loaded and don't require + // re-running initializers. + if (auto *JDS = getJITDylibStateByName(Path)) { + if (!JDS->AllowReinitialization) { + ++JDS->RefCount; + return JDS->Header; + } + } + + auto H = dlopenInitialize(Path, Mode); + if (!H) { + DLFcnError = toString(H.takeError()); + return nullptr; + } + + return *H; +} + +int MachOPlatformRuntimeState::dlclose(void *DSOHandle) { + runAtExits(DSOHandle); + return 0; +} + +void *MachOPlatformRuntimeState::dlsym(void *DSOHandle, string_view Symbol) { + auto Addr = lookupSymbolInJITDylib(DSOHandle, Symbol); + if (!Addr) { + DLFcnError = toString(Addr.takeError()); + return 0; + } + + return Addr->toPtr(); +} + +int MachOPlatformRuntimeState::registerAtExit(void (*F)(void *), void *Arg, + void *DSOHandle) { + // FIXME: Handle out-of-memory errors, returning -1 if OOM. + std::lock_guard Lock(JDStatesMutex); + auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle); + assert(JDS && "JITDylib state not initialized"); + JDS->AtExits.push_back({F, Arg}); + return 0; +} + +void MachOPlatformRuntimeState::runAtExits(void *DSOHandle) { + // FIXME: Should atexits be allowed to run concurrently with access to + // JDState? + AtExitsVector V; + { + std::lock_guard Lock(JDStatesMutex); + auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle); + assert(JDS && "JITDlybi state not initialized"); + std::swap(V, JDS->AtExits); + } + + while (!V.empty()) { + auto &AE = V.back(); + AE.Func(AE.Arg); + V.pop_back(); + } +} + +MachOPlatformRuntimeState::PerJITDylibState * +MachOPlatformRuntimeState::getJITDylibStateByHeaderAddr(void *DSOHandle) { + auto I = JDStates.find(DSOHandle); + if (I == JDStates.end()) + return nullptr; + return &I->second; +} + +MachOPlatformRuntimeState::PerJITDylibState * +MachOPlatformRuntimeState::getJITDylibStateByName(string_view Name) { + // FIXME: Avoid creating string copy here. + auto I = JDNameToHeader.find(std::string(Name.data(), Name.size())); + if (I == JDNameToHeader.end()) + return nullptr; + void *H = I->second; + auto J = JDStates.find(H); + assert(J != JDStates.end() && + "JITDylib has name map entry but no header map entry"); + return &J->second; +} + +MachOPlatformRuntimeState::PerJITDylibState & +MachOPlatformRuntimeState::getOrCreateJITDylibState( + MachOJITDylibInitializers &MOJDIs) { + void *Header = MOJDIs.MachOHeaderAddress.toPtr(); + + auto &JDS = JDStates[Header]; + + // If this entry hasn't been created yet. + if (!JDS.Header) { + assert(!JDNameToHeader.count(MOJDIs.Name) && + "JITDylib has header map entry but no name map entry"); + JDNameToHeader[MOJDIs.Name] = Header; + JDS.Header = Header; + } + + return JDS; +} + +Expected +MachOPlatformRuntimeState::lookupSymbolInJITDylib(void *DSOHandle, + string_view Sym) { + Expected Result((ExecutorAddress())); + if (auto Err = WrapperFunction( + SPSExecutorAddress, + SPSString)>::call(&__orc_rt_macho_symbol_lookup_tag, Result, + ExecutorAddress::fromPtr(DSOHandle), Sym)) + return std::move(Err); + return Result; +} + +Expected +MachOPlatformRuntimeState::getJITDylibInitializersByName(string_view Path) { + Expected Result( + (MachOJITDylibInitializerSequence())); + std::string PathStr(Path.data(), Path.size()); + if (auto Err = + WrapperFunction( + SPSString)>::call(&__orc_rt_macho_get_initializers_tag, Result, + Path)) + return std::move(Err); + return Result; +} + +Expected MachOPlatformRuntimeState::dlopenInitialize(string_view Path, + int Mode) { + // Either our JITDylib wasn't loaded, or it or one of its dependencies allows + // reinitialization. We need to call in to the JIT to see if there's any new + // work pending. + auto InitSeq = getJITDylibInitializersByName(Path); + if (!InitSeq) + return InitSeq.takeError(); + + // Init sequences should be non-empty. + if (InitSeq->empty()) + return make_error( + "__orc_rt_macho_get_initializers returned an " + "empty init sequence"); + + // Otherwise register and run initializers for each JITDylib. + for (auto &MOJDIs : *InitSeq) + if (auto Err = initializeJITDylib(MOJDIs)) + return std::move(Err); + + // Return the header for the last item in the list. + auto *JDS = getJITDylibStateByHeaderAddr( + InitSeq->back().MachOHeaderAddress.toPtr()); + assert(JDS && "Missing state entry for JD"); + return JDS->Header; +} + +Error MachOPlatformRuntimeState::initializeJITDylib( + MachOJITDylibInitializers &MOJDIs) { + + auto &JDS = getOrCreateJITDylibState(MOJDIs); + ++JDS.RefCount; + + for (auto &KV : InitSections) { + const auto &Name = KV.first; + const auto &Handler = KV.second; + // FIXME: Remove copy once we have C++17. + auto I = MOJDIs.InitSections.find(to_string(Name)); + if (I != MOJDIs.InitSections.end()) { + if (auto Err = Handler(I->second, MOJDIs)) + return Err; + } + } + + return Error::success(); +} + +} // end anonymous namespace + +//------------------------------------------------------------------------------ +// JIT entry points +//------------------------------------------------------------------------------ + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_macho_platform_bootstrap(char *ArgData, size_t ArgSize) { + MachOPlatformRuntimeState::initialize(); + return WrapperFunctionResult().release(); +} + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_macho_platform_shutdown(char *ArgData, size_t ArgSize) { + MachOPlatformRuntimeState::destroy(); + return WrapperFunctionResult().release(); +} + +/// Wrapper function for registering metadata on a per-object basis. +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_macho_register_object_sections(char *ArgData, size_t ArgSize) { + return WrapperFunction::handle( + ArgData, ArgSize, + [](MachOPerObjectSectionsToRegister &POSR) { + return MachOPlatformRuntimeState::get().registerObjectSections( + std::move(POSR)); + }) + .release(); +} + +/// Wrapper for releasing per-object metadat. +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_macho_deregister_object_sections(char *ArgData, size_t ArgSize) { + return WrapperFunction::handle( + ArgData, ArgSize, + [](MachOPerObjectSectionsToRegister &POSR) { + return MachOPlatformRuntimeState::get().deregisterObjectSections( + std::move(POSR)); + }) + .release(); +} + +//------------------------------------------------------------------------------ +// cxa_atexit support +//------------------------------------------------------------------------------ + +int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg, + void *dso_handle) { + return MachOPlatformRuntimeState::get().registerAtExit(func, arg, dso_handle); +} + +void __orc_rt_macho_cxa_finalize(void *dso_handle) { + MachOPlatformRuntimeState::get().runAtExits(dso_handle); +} + +//------------------------------------------------------------------------------ +// JIT'd dlfcn alternatives. +//------------------------------------------------------------------------------ + +const char *__orc_rt_macho_jit_dlerror() { + return MachOPlatformRuntimeState::get().dlerror(); +} + +void *__orc_rt_macho_jit_dlopen(const char *path, int mode) { + return MachOPlatformRuntimeState::get().dlopen(path, mode); +} + +int __orc_rt_macho_jit_dlclose(void *dso_handle) { + return MachOPlatformRuntimeState::get().dlclose(dso_handle); +} + +void *__orc_rt_macho_jit_dlsym(void *dso_handle, const char *symbol) { + return MachOPlatformRuntimeState::get().dlsym(dso_handle, symbol); +} + +//------------------------------------------------------------------------------ +// MachO Run Program +//------------------------------------------------------------------------------ + +ORC_RT_INTERFACE int64_t __orc_rt_macho_run_program(const char *JITDylibName, + const char *EntrySymbolName, + int argc, char *argv[]) { + using MainTy = int (*)(int, char *[]); + + void *H = __orc_rt_macho_jit_dlopen(JITDylibName, + __orc_rt::macho::ORC_RT_RTLD_LAZY); + if (!H) { + __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); + return -1; + } + + auto *Main = + reinterpret_cast(__orc_rt_macho_jit_dlsym(H, EntrySymbolName)); + + if (!Main) { + __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); + return -1; + } + + int Result = Main(argc, argv); + + if (__orc_rt_macho_jit_dlclose(H) == -1) + __orc_rt_log_error(__orc_rt_macho_jit_dlerror()); + + return Result; +} diff --git a/compiler-rt/lib/orc/macho_platform.h b/compiler-rt/lib/orc/macho_platform.h new file mode 100644 index 0000000000000..b4abb50e87341 --- /dev/null +++ b/compiler-rt/lib/orc/macho_platform.h @@ -0,0 +1,129 @@ +//===- macho_platform.h -----------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// ORC Runtime support for Darwin dynamic loading features. +// +//===----------------------------------------------------------------------===// + +#ifndef ORC_RT_MACHO_PLATFORM_H +#define ORC_RT_MACHO_PLATFORM_H + +#include "common.h" +#include "executor_address.h" + +// Atexit functions. +ORC_RT_INTERFACE int __orc_rt_macho_cxa_atexit(void (*func)(void *), void *arg, + void *dso_handle); +ORC_RT_INTERFACE void __orc_rt_macho_cxa_finalize(void *dso_handle); + +// dlfcn functions. +ORC_RT_INTERFACE const char *__orc_rt_macho_jit_dlerror(); +ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlopen(const char *path, int mode); +ORC_RT_INTERFACE int __orc_rt_macho_jit_dlclose(void *dso_handle); +ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlsym(void *dso_handle, + const char *symbol); + +namespace __orc_rt { +namespace macho { + +struct MachOPerObjectSectionsToRegister { + ExecutorAddressRange EHFrameSection; +}; + +struct MachOJITDylibInitializers { + using SectionList = std::vector; + + MachOJITDylibInitializers() = default; + MachOJITDylibInitializers(std::string Name, + ExecutorAddress MachOHeaderAddress) + : Name(std::move(Name)), + MachOHeaderAddress(std::move(MachOHeaderAddress)) {} + + std::string Name; + ExecutorAddress MachOHeaderAddress; + + std::unordered_map InitSections; +}; + +class MachOJITDylibDeinitializers {}; + +using MachOJITDylibInitializerSequence = std::vector; + +using MachOJITDylibDeinitializerSequence = + std::vector; + +enum dlopen_mode : int { + ORC_RT_RTLD_LAZY = 0x1, + ORC_RT_RTLD_NOW = 0x2, + ORC_RT_RTLD_LOCAL = 0x4, + ORC_RT_RTLD_GLOBAL = 0x8 +}; + +} // end namespace macho + +using SPSMachOPerObjectSectionsToRegister = SPSTuple; + +template <> +class SPSSerializationTraits { + +public: + static size_t size(const macho::MachOPerObjectSectionsToRegister &MOPOSR) { + return SPSMachOPerObjectSectionsToRegister::AsArgList::size( + MOPOSR.EHFrameSection); + } + + static bool serialize(SPSOutputBuffer &OB, + const macho::MachOPerObjectSectionsToRegister &MOPOSR) { + return SPSMachOPerObjectSectionsToRegister::AsArgList::serialize( + OB, MOPOSR.EHFrameSection); + } + + static bool deserialize(SPSInputBuffer &IB, + macho::MachOPerObjectSectionsToRegister &MOPOSR) { + return SPSMachOPerObjectSectionsToRegister::AsArgList::deserialize( + IB, MOPOSR.EHFrameSection); + } +}; + +using SPSNamedExecutorAddressRangeSequenceMap = + SPSSequence>; + +using SPSMachOJITDylibInitializers = + SPSTuple; + +using SPSMachOJITDylibInitializerSequence = + SPSSequence; + +/// Serialization traits for MachOJITDylibInitializers. +template <> +class SPSSerializationTraits { +public: + static size_t size(const macho::MachOJITDylibInitializers &MOJDIs) { + return SPSMachOJITDylibInitializers::AsArgList::size( + MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.InitSections); + } + + static bool serialize(SPSOutputBuffer &OB, + const macho::MachOJITDylibInitializers &MOJDIs) { + return SPSMachOJITDylibInitializers::AsArgList::serialize( + OB, MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.InitSections); + } + + static bool deserialize(SPSInputBuffer &IB, + macho::MachOJITDylibInitializers &MOJDIs) { + return SPSMachOJITDylibInitializers::AsArgList::deserialize( + IB, MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.InitSections); + } +}; + +} // end namespace __orc_rt + +#endif // ORC_RT_MACHO_PLATFORM_H diff --git a/compiler-rt/lib/orc/run_program_wrapper.cpp b/compiler-rt/lib/orc/run_program_wrapper.cpp new file mode 100644 index 0000000000000..d0f88534aa9c1 --- /dev/null +++ b/compiler-rt/lib/orc/run_program_wrapper.cpp @@ -0,0 +1,51 @@ +//===- run_program_wrapper.cpp --------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of the ORC runtime support library. +// +//===----------------------------------------------------------------------===// + +#include "adt.h" +#include "common.h" +#include "wrapper_function_utils.h" + +#include + +using namespace __orc_rt; + +extern "C" int64_t __orc_rt_run_program(const char *JITDylibName, + const char *EntrySymbolName, int argc, + char *argv[]); + +ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult +__orc_rt_run_program_wrapper(const char *ArgData, size_t ArgSize) { + return WrapperFunction)>:: + handle(ArgData, ArgSize, + [](const std::string &JITDylibName, + const std::string &EntrySymbolName, + const std::vector &Args) { + std::vector> ArgVStorage; + ArgVStorage.reserve(Args.size()); + for (auto &Arg : Args) { + ArgVStorage.push_back( + std::make_unique(Arg.size() + 1)); + memcpy(ArgVStorage.back().get(), Arg.data(), Arg.size()); + ArgVStorage.back()[Arg.size()] = '\0'; + } + std::vector ArgV; + ArgV.reserve(ArgVStorage.size() + 1); + for (auto &ArgStorage : ArgVStorage) + ArgV.push_back(ArgStorage.get()); + ArgV.push_back(nullptr); + return __orc_rt_run_program(JITDylibName.c_str(), + EntrySymbolName.c_str(), + ArgV.size() - 1, ArgV.data()); + }) + .release(); +} diff --git a/compiler-rt/lib/orc/simple_packed_serialization.h b/compiler-rt/lib/orc/simple_packed_serialization.h index a6e90f506d7ce..b561a19d8f048 100644 --- a/compiler-rt/lib/orc/simple_packed_serialization.h +++ b/compiler-rt/lib/orc/simple_packed_serialization.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,7 @@ class SPSInputBuffer { bool skip(size_t Size) { if (Size > Remaining) return false; + Buffer += Size; Remaining -= Size; return true; } @@ -170,17 +172,11 @@ class SPSSerializationTraits< } }; -// Any empty placeholder suitable as a substitute for void when deserializing +/// Any empty placeholder suitable as a substitute for void when deserializing class SPSEmpty {}; -/// SPS tag type for target addresses. -/// -/// SPSTagTargetAddresses should be serialized as a uint64_t value. -class SPSTagTargetAddress; - -template <> -class SPSSerializationTraits - : public SPSSerializationTraits {}; +/// Represents an address in the executor. +class SPSExecutorAddress {}; /// SPS tag type for tuples. /// @@ -290,6 +286,33 @@ class TrivialSPSSequenceDeserialization> { } }; +/// Trivial std::unordered_map -> SPSSequence> +/// serialization. +template +class TrivialSPSSequenceSerialization, + std::unordered_map> { +public: + static constexpr bool available = true; +}; + +/// Trivial SPSSequence> -> std::unordered_map +/// deserialization. +template +class TrivialSPSSequenceDeserialization, + std::unordered_map> { +public: + static constexpr bool available = true; + + using element_type = std::pair; + + static void reserve(std::unordered_map &M, uint64_t Size) { + M.reserve(Size); + } + static bool append(std::unordered_map &M, element_type E) { + return M.insert(std::move(E)).second; + } +}; + /// 'Trivial' sequence serialization: Sequence is serialized as a uint64_t size /// followed by a for-earch loop over the elements of the sequence to serialize /// each of them. diff --git a/compiler-rt/lib/orc/unittests/adt_test.cpp b/compiler-rt/lib/orc/unittests/adt_test.cpp index 3c34b87f68615..dec636e837ddd 100644 --- a/compiler-rt/lib/orc/unittests/adt_test.cpp +++ b/compiler-rt/lib/orc/unittests/adt_test.cpp @@ -72,7 +72,7 @@ TEST(ADTTest, StringViewConstructFromCharPtr) { EXPECT_FALSE(S.empty()) << "Span should be non-empty"; EXPECT_EQ(S.size(), StrLen) << "Span has unexpected size"; - EXPECT_EQ(std::distance(S.begin(), S.end()), StrLen) + EXPECT_EQ(static_cast(std::distance(S.begin(), S.end())), StrLen) << "Unexpected iterator range size"; EXPECT_EQ(S.data(), &Str[0]) << "Span data has unexpected value"; for (unsigned I = 0; I != S.size(); ++I) diff --git a/compiler-rt/lib/orc/wrapper_function_utils.h b/compiler-rt/lib/orc/wrapper_function_utils.h index cf027e7944b66..49faa03e5eb81 100644 --- a/compiler-rt/lib/orc/wrapper_function_utils.h +++ b/compiler-rt/lib/orc/wrapper_function_utils.h @@ -125,7 +125,7 @@ serializeViaSPSToWrapperFunctionResult(const ArgTs &...Args) { if (!SPSArgListT::serialize(OB, Args...)) return make_error( "Error serializing arguments to blob in call"); - return Result; + return std::move(Result); } template class WrapperFunctionHandlerCaller { @@ -305,9 +305,9 @@ class WrapperFunction { detail::ResultDeserializer::makeSafe(Result); if (ORC_RT_UNLIKELY(!&__orc_rt_jit_dispatch_ctx)) - return make_error("__orc_jtjit_dispatch_ctx not set"); + return make_error("__orc_rt_jit_dispatch_ctx not set"); if (ORC_RT_UNLIKELY(!&__orc_rt_jit_dispatch)) - return make_error("__orc_jtjit_dispatch not set"); + return make_error("__orc_rt_jit_dispatch not set"); auto ArgBuffer = detail::serializeViaSPSToWrapperFunctionResult>( diff --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c index 420e8246f4337..ec12f2ad9fb56 100644 --- a/compiler-rt/lib/profile/InstrProfilingFile.c +++ b/compiler-rt/lib/profile/InstrProfilingFile.c @@ -490,6 +490,8 @@ static void relocateCounters(void) { * __llvm_profile_get_size_for_buffer(). */ const __llvm_profile_data *DataBegin = __llvm_profile_begin_data(); const __llvm_profile_data *DataEnd = __llvm_profile_end_data(); + const uint64_t *CountersBegin = __llvm_profile_begin_counters(); + const uint64_t *CountersEnd = __llvm_profile_end_counters(); uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd); const uint64_t CountersOffset = sizeof(__llvm_profile_header) + (DataSize * sizeof(__llvm_profile_data)); @@ -542,8 +544,11 @@ static void relocateCounters(void) { } /* Update the profile fields based on the current mapping. */ - __llvm_profile_counter_bias = (intptr_t)Profile - - (uintptr_t)__llvm_profile_begin_counters() + CountersOffset; + __llvm_profile_counter_bias = + (intptr_t)Profile - (uintptr_t)CountersBegin + CountersOffset; + + /* Return the memory allocated for counters to OS. */ + lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd); } static void initializeProfileForContinuousMode(void) { diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c b/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c index 8bd5e969aa50c..368c0f81d7f0a 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformFuchsia.c @@ -192,9 +192,11 @@ void __llvm_profile_initialize(void) { lprofWrite("LLVM Profile: {{{dumpfile:%s:%s}}}\n", ProfileSinkName, VmoName); /* Update the profile fields based on the current mapping. */ - __llvm_profile_counter_bias = (intptr_t)Mapping - - (uintptr_t)__llvm_profile_begin_counters() + - CountersOffset; + __llvm_profile_counter_bias = + (intptr_t)Mapping - (uintptr_t)CountersBegin + CountersOffset; + + /* Return the memory allocated for counters to OS. */ + lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd); } #endif diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.c b/compiler-rt/lib/profile/InstrProfilingUtil.c index bf5a9670fe18c..4fa792b72eac8 100644 --- a/compiler-rt/lib/profile/InstrProfilingUtil.c +++ b/compiler-rt/lib/profile/InstrProfilingUtil.c @@ -12,12 +12,13 @@ #include #include "WindowsMMap.h" #else +#include +#include #include +#include #include #include #include -#include -#include #endif #ifdef COMPILER_RT_HAS_UNAME @@ -32,6 +33,10 @@ #include #endif +#if defined(__Fuchsia__) +#include +#endif + #include "InstrProfiling.h" #include "InstrProfilingUtil.h" @@ -330,3 +335,21 @@ COMPILER_RT_VISIBILITY void lprofRestoreSigKill() { prctl(PR_SET_PDEATHSIG, SIGKILL); #endif } + +COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin, + uintptr_t End) { + size_t PageSize = getpagesize(); + uintptr_t BeginAligned = lprofRoundUpTo((uintptr_t)Begin, PageSize); + uintptr_t EndAligned = lprofRoundDownTo((uintptr_t)End, PageSize); + if (BeginAligned < EndAligned) { +#if defined(__Fuchsia__) + return _zx_vmar_op_range(_zx_vmar_root_self(), ZX_VMAR_OP_DECOMMIT, + (zx_vaddr_t)BeginAligned, + EndAligned - BeginAligned, NULL, 0); +#else + return madvise((void *)BeginAligned, EndAligned - BeginAligned, + MADV_DONTNEED); +#endif + } + return 0; +} diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.h b/compiler-rt/lib/profile/InstrProfilingUtil.h index 5f5c85091fe87..183aff040f7e5 100644 --- a/compiler-rt/lib/profile/InstrProfilingUtil.h +++ b/compiler-rt/lib/profile/InstrProfilingUtil.h @@ -9,6 +9,7 @@ #ifndef PROFILE_INSTRPROFILINGUTIL_H #define PROFILE_INSTRPROFILINGUTIL_H +#include #include #include @@ -73,4 +74,14 @@ int lprofSuspendSigKill(); /* Restore previously suspended SIGKILL. */ void lprofRestoreSigKill(); +inline size_t lprofRoundUpTo(size_t x, size_t boundary) { + return (x + boundary - 1) & ~(boundary - 1); +} + +inline size_t lprofRoundDownTo(size_t x, size_t boundary) { + return x & ~(boundary - 1); +} + +int lprofReleaseMemoryPagesToOS(uintptr_t Begin, uintptr_t End); + #endif /* PROFILE_INSTRPROFILINGUTIL_H */ diff --git a/compiler-rt/lib/profile/WindowsMMap.c b/compiler-rt/lib/profile/WindowsMMap.c index 41cc67f41f1fd..07c0a689feaea 100644 --- a/compiler-rt/lib/profile/WindowsMMap.c +++ b/compiler-rt/lib/profile/WindowsMMap.c @@ -112,6 +112,18 @@ int msync(void *addr, size_t length, int flags) return 0; } +COMPILER_RT_VISIBILITY +int madvise(void *addr, size_t length, int advice) +{ + if (advice != MADV_DONTNEED) + return -1; /* Not supported. */ + + if (!VirtualUnlock(addr, length)) + return -1; + + return 0; +} + COMPILER_RT_VISIBILITY int lock(HANDLE handle, DWORD lockType, BOOL blocking) { DWORD flags = lockType; diff --git a/compiler-rt/lib/profile/WindowsMMap.h b/compiler-rt/lib/profile/WindowsMMap.h index c8d6250f41c1a..68b8de2398d60 100644 --- a/compiler-rt/lib/profile/WindowsMMap.h +++ b/compiler-rt/lib/profile/WindowsMMap.h @@ -36,6 +36,14 @@ #define MS_INVALIDATE 0x0002 /* invalidate all cached data */ #define MS_SYNC 0x0010 /* msync synchronously */ +/* + * madvise() flags + */ + +#define MADV_NORMAL 0 /* no special treatment */ +#define MADV_WILLNEED 3 /* expect access in the near future */ +#define MADV_DONTNEED 4 /* do not expect access in the near future */ + /* * flock() operations */ @@ -59,6 +67,8 @@ void munmap(void *addr, size_t length); int msync(void *addr, size_t length, int flags); +int madvise(void *addr, size_t length, int advice); + int flock(int fd, int operation); #endif /* _WIN32 */ diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index 66246006a7a45..543ed407c0e2d 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -16,6 +16,7 @@ set(SANITIZER_SOURCES_NOTERMINATION sanitizer_linux.cpp sanitizer_linux_s390.cpp sanitizer_mac.cpp + sanitizer_mutex.cpp sanitizer_netbsd.cpp sanitizer_persistent_allocator.cpp sanitizer_platform_limits_freebsd.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp index 3157b35ffaf80..bcb7370a79061 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp @@ -137,14 +137,6 @@ static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) { #endif // SANITIZER_GO || defined(SANITIZER_USE_MALLOC) -namespace { -const u64 kBlockMagic = 0x6A6CB03ABCEBC041ull; - -struct BlockHeader { - u64 magic; -}; -} // namespace - static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) { SetAllocatorOutOfMemory(); Report("FATAL: %s: internal allocator is out of memory trying to allocate " @@ -153,28 +145,17 @@ static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) { } void *InternalAlloc(uptr size, InternalAllocatorCache *cache, uptr alignment) { - uptr s = size + sizeof(BlockHeader); - if (s < size) - return nullptr; - BlockHeader *p = (BlockHeader *)RawInternalAlloc(s, cache, alignment); + void *p = RawInternalAlloc(size, cache, alignment); if (UNLIKELY(!p)) - ReportInternalAllocatorOutOfMemory(s); - p->magic = kBlockMagic; - return p + 1; + ReportInternalAllocatorOutOfMemory(size); + return p; } void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) { - if (!addr) - return InternalAlloc(size, cache); - uptr s = size + sizeof(BlockHeader); - if (s < size) - return nullptr; - BlockHeader *p = (BlockHeader *)addr - 1; - CHECK_EQ(kBlockMagic, p->magic); - p = (BlockHeader *)RawInternalRealloc(p, s, cache); + void *p = RawInternalRealloc(addr, size, cache); if (UNLIKELY(!p)) - ReportInternalAllocatorOutOfMemory(s); - return p + 1; + ReportInternalAllocatorOutOfMemory(size); + return p; } void *InternalReallocArray(void *addr, uptr count, uptr size, @@ -203,12 +184,7 @@ void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) { } void InternalFree(void *addr, InternalAllocatorCache *cache) { - if (!addr) - return; - BlockHeader *p = (BlockHeader *)addr - 1; - CHECK_EQ(kBlockMagic, p->magic); - p->magic = 0; - RawInternalFree(p, cache); + RawInternalFree(addr, cache); } // LowLevelAllocator diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h index 108dfc231a227..e495c56f03775 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h @@ -17,6 +17,7 @@ template struct SizeClassAllocator64LocalCache { typedef SizeClassAllocator Allocator; + typedef MemoryMapper MemoryMapperT; void Init(AllocatorGlobalStats *s) { stats_.Init(); @@ -53,7 +54,7 @@ struct SizeClassAllocator64LocalCache { PerClass *c = &per_class_[class_id]; InitCache(c); if (UNLIKELY(c->count == c->max_count)) - Drain(c, allocator, class_id, c->max_count / 2); + DrainHalfMax(c, allocator, class_id); CompactPtrT chunk = allocator->PointerToCompactPtr( allocator->GetRegionBeginBySizeClass(class_id), reinterpret_cast(p)); @@ -62,10 +63,10 @@ struct SizeClassAllocator64LocalCache { } void Drain(SizeClassAllocator *allocator) { + MemoryMapperT memory_mapper(*allocator); for (uptr i = 1; i < kNumClasses; i++) { PerClass *c = &per_class_[i]; - while (c->count > 0) - Drain(c, allocator, i, c->count); + while (c->count > 0) Drain(&memory_mapper, c, allocator, i, c->count); } } @@ -106,12 +107,18 @@ struct SizeClassAllocator64LocalCache { return true; } - NOINLINE void Drain(PerClass *c, SizeClassAllocator *allocator, uptr class_id, - uptr count) { + NOINLINE void DrainHalfMax(PerClass *c, SizeClassAllocator *allocator, + uptr class_id) { + MemoryMapperT memory_mapper(*allocator); + Drain(&memory_mapper, c, allocator, class_id, c->max_count / 2); + } + + void Drain(MemoryMapperT *memory_mapper, PerClass *c, + SizeClassAllocator *allocator, uptr class_id, uptr count) { CHECK_GE(c->count, count); const uptr first_idx_to_drain = c->count - count; c->count -= count; - allocator->ReturnToAllocator(&stats_, class_id, + allocator->ReturnToAllocator(memory_mapper, &stats_, class_id, &c->chunks[first_idx_to_drain], count); } }; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h index fb5394cd39c4c..38d2a7d117fbf 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary32.h @@ -237,13 +237,13 @@ class SizeClassAllocator32 { // ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone // introspection API. - void ForceLock() { + void ForceLock() NO_THREAD_SAFETY_ANALYSIS { for (uptr i = 0; i < kNumClasses; i++) { GetSizeClassInfo(i)->mutex.Lock(); } } - void ForceUnlock() { + void ForceUnlock() NO_THREAD_SAFETY_ANALYSIS { for (int i = kNumClasses - 1; i >= 0; i--) { GetSizeClassInfo(i)->mutex.Unlock(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h index 8bbed3c278c9a..b142ee0131b2b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h @@ -42,6 +42,44 @@ struct SizeClassAllocator64FlagMasks { // Bit masks. }; }; +template +class MemoryMapper { + public: + typedef typename Allocator::CompactPtrT CompactPtrT; + + explicit MemoryMapper(const Allocator &allocator) : allocator_(allocator) {} + + bool GetAndResetStats(uptr &ranges, uptr &bytes) { + ranges = released_ranges_count_; + released_ranges_count_ = 0; + bytes = released_bytes_; + released_bytes_ = 0; + return ranges != 0; + } + + u64 *MapPackedCounterArrayBuffer(uptr count) { + buffer_.clear(); + buffer_.resize(count); + return buffer_.data(); + } + + // Releases [from, to) range of pages back to OS. + void ReleasePageRangeToOS(uptr class_id, CompactPtrT from, CompactPtrT to) { + const uptr region_base = allocator_.GetRegionBeginBySizeClass(class_id); + const uptr from_page = allocator_.CompactPtrToPointer(region_base, from); + const uptr to_page = allocator_.CompactPtrToPointer(region_base, to); + ReleaseMemoryPagesToOS(from_page, to_page); + released_ranges_count_++; + released_bytes_ += to_page - from_page; + } + + private: + const Allocator &allocator_; + uptr released_ranges_count_ = 0; + uptr released_bytes_ = 0; + InternalMmapVector buffer_; +}; + template class SizeClassAllocator64 { public: @@ -57,6 +95,7 @@ class SizeClassAllocator64 { typedef SizeClassAllocator64 ThisT; typedef SizeClassAllocator64LocalCache AllocatorCache; + typedef MemoryMapper MemoryMapperT; // When we know the size class (the region base) we can represent a pointer // as a 4-byte integer (offset from the region start shifted right by 4). @@ -120,9 +159,10 @@ class SizeClassAllocator64 { } void ForceReleaseToOS() { + MemoryMapperT memory_mapper(*this); for (uptr class_id = 1; class_id < kNumClasses; class_id++) { BlockingMutexLock l(&GetRegionInfo(class_id)->mutex); - MaybeReleaseToOS(class_id, true /*force*/); + MaybeReleaseToOS(&memory_mapper, class_id, true /*force*/); } } @@ -131,7 +171,8 @@ class SizeClassAllocator64 { alignment <= SizeClassMap::kMaxSize; } - NOINLINE void ReturnToAllocator(AllocatorStats *stat, uptr class_id, + NOINLINE void ReturnToAllocator(MemoryMapperT *memory_mapper, + AllocatorStats *stat, uptr class_id, const CompactPtrT *chunks, uptr n_chunks) { RegionInfo *region = GetRegionInfo(class_id); uptr region_beg = GetRegionBeginBySizeClass(class_id); @@ -154,7 +195,7 @@ class SizeClassAllocator64 { region->num_freed_chunks = new_num_freed_chunks; region->stats.n_freed += n_chunks; - MaybeReleaseToOS(class_id, false /*force*/); + MaybeReleaseToOS(memory_mapper, class_id, false /*force*/); } NOINLINE bool GetFromAllocator(AllocatorStats *stat, uptr class_id, @@ -362,11 +403,11 @@ class SizeClassAllocator64 { // For the performance sake, none of the accessors check the validity of the // arguments, it is assumed that index is always in [0, n) range and the value // is not incremented past max_value. - template class PackedCounterArray { public: - PackedCounterArray(u64 num_counters, u64 max_value, MemoryMapperT *mapper) - : n(num_counters), memory_mapper(mapper) { + template + PackedCounterArray(u64 num_counters, u64 max_value, MemoryMapper *mapper) + : n(num_counters) { CHECK_GT(num_counters, 0); CHECK_GT(max_value, 0); constexpr u64 kMaxCounterBits = sizeof(*buffer) * 8ULL; @@ -383,16 +424,8 @@ class SizeClassAllocator64 { packing_ratio_log = Log2(packing_ratio); bit_offset_mask = packing_ratio - 1; - buffer_size = - (RoundUpTo(n, 1ULL << packing_ratio_log) >> packing_ratio_log) * - sizeof(*buffer); - buffer = reinterpret_cast( - memory_mapper->MapPackedCounterArrayBuffer(buffer_size)); - } - ~PackedCounterArray() { - if (buffer) { - memory_mapper->UnmapPackedCounterArrayBuffer(buffer, buffer_size); - } + buffer = mapper->MapPackedCounterArrayBuffer( + RoundUpTo(n, 1ULL << packing_ratio_log) >> packing_ratio_log); } bool IsAllocated() const { @@ -429,19 +462,16 @@ class SizeClassAllocator64 { u64 counter_mask; u64 packing_ratio_log; u64 bit_offset_mask; - - MemoryMapperT* const memory_mapper; - u64 buffer_size; u64* buffer; }; - template + template class FreePagesRangeTracker { public: - explicit FreePagesRangeTracker(MemoryMapperT* mapper) + FreePagesRangeTracker(MemoryMapperT *mapper, uptr class_id) : memory_mapper(mapper), - page_size_scaled_log(Log2(GetPageSizeCached() >> kCompactPtrScale)), - in_the_range(false), current_page(0), current_range_start_page(0) {} + class_id(class_id), + page_size_scaled_log(Log2(GetPageSizeCached() >> kCompactPtrScale)) {} void NextPage(bool freed) { if (freed) { @@ -463,28 +493,30 @@ class SizeClassAllocator64 { void CloseOpenedRange() { if (in_the_range) { memory_mapper->ReleasePageRangeToOS( - current_range_start_page << page_size_scaled_log, + class_id, current_range_start_page << page_size_scaled_log, current_page << page_size_scaled_log); in_the_range = false; } } - MemoryMapperT* const memory_mapper; - const uptr page_size_scaled_log; - bool in_the_range; - uptr current_page; - uptr current_range_start_page; + MemoryMapperT *const memory_mapper = nullptr; + const uptr class_id = 0; + const uptr page_size_scaled_log = 0; + bool in_the_range = false; + uptr current_page = 0; + uptr current_range_start_page = 0; }; // Iterates over the free_array to identify memory pages containing freed // chunks only and returns these pages back to OS. // allocated_pages_count is the total number of pages allocated for the // current bucket. - template + template static void ReleaseFreeMemoryToOS(CompactPtrT *free_array, uptr free_array_count, uptr chunk_size, uptr allocated_pages_count, - MemoryMapperT *memory_mapper) { + MemoryMapper *memory_mapper, + uptr class_id) { const uptr page_size = GetPageSizeCached(); // Figure out the number of chunks per page and whether we can take a fast @@ -520,9 +552,8 @@ class SizeClassAllocator64 { UNREACHABLE("All chunk_size/page_size ratios must be handled."); } - PackedCounterArray counters(allocated_pages_count, - full_pages_chunk_count_max, - memory_mapper); + PackedCounterArray counters(allocated_pages_count, + full_pages_chunk_count_max, memory_mapper); if (!counters.IsAllocated()) return; @@ -547,7 +578,7 @@ class SizeClassAllocator64 { // Iterate over pages detecting ranges of pages with chunk counters equal // to the expected number of chunks for the particular page. - FreePagesRangeTracker range_tracker(memory_mapper); + FreePagesRangeTracker range_tracker(memory_mapper, class_id); if (same_chunk_count_per_page) { // Fast path, every page has the same number of chunks affecting it. for (uptr i = 0; i < counters.GetCount(); i++) @@ -586,7 +617,7 @@ class SizeClassAllocator64 { } private: - friend class MemoryMapper; + friend class MemoryMapper; ReservedAddressRange address_range; @@ -820,57 +851,13 @@ class SizeClassAllocator64 { return true; } - class MemoryMapper { - public: - MemoryMapper(const ThisT& base_allocator, uptr class_id) - : allocator(base_allocator), - region_base(base_allocator.GetRegionBeginBySizeClass(class_id)), - released_ranges_count(0), - released_bytes(0) { - } - - uptr GetReleasedRangesCount() const { - return released_ranges_count; - } - - uptr GetReleasedBytes() const { - return released_bytes; - } - - void *MapPackedCounterArrayBuffer(uptr buffer_size) { - // TODO(alekseyshl): The idea to explore is to check if we have enough - // space between num_freed_chunks*sizeof(CompactPtrT) and - // mapped_free_array to fit buffer_size bytes and use that space instead - // of mapping a temporary one. - return MmapOrDieOnFatalError(buffer_size, "ReleaseToOSPageCounters"); - } - - void UnmapPackedCounterArrayBuffer(void *buffer, uptr buffer_size) { - UnmapOrDie(buffer, buffer_size); - } - - // Releases [from, to) range of pages back to OS. - void ReleasePageRangeToOS(CompactPtrT from, CompactPtrT to) { - const uptr from_page = allocator.CompactPtrToPointer(region_base, from); - const uptr to_page = allocator.CompactPtrToPointer(region_base, to); - ReleaseMemoryPagesToOS(from_page, to_page); - released_ranges_count++; - released_bytes += to_page - from_page; - } - - private: - const ThisT& allocator; - const uptr region_base; - uptr released_ranges_count; - uptr released_bytes; - }; - // Attempts to release RAM occupied by freed chunks back to OS. The region is // expected to be locked. // // TODO(morehouse): Support a callback on memory release so HWASan can release // aliases as well. - void MaybeReleaseToOS(uptr class_id, bool force) { + void MaybeReleaseToOS(MemoryMapperT *memory_mapper, uptr class_id, + bool force) { RegionInfo *region = GetRegionInfo(class_id); const uptr chunk_size = ClassIdToSize(class_id); const uptr page_size = GetPageSizeCached(); @@ -894,17 +881,16 @@ class SizeClassAllocator64 { } } - MemoryMapper memory_mapper(*this, class_id); - - ReleaseFreeMemoryToOS( + ReleaseFreeMemoryToOS( GetFreeArray(GetRegionBeginBySizeClass(class_id)), n, chunk_size, - RoundUpTo(region->allocated_user, page_size) / page_size, - &memory_mapper); + RoundUpTo(region->allocated_user, page_size) / page_size, memory_mapper, + class_id); - if (memory_mapper.GetReleasedRangesCount() > 0) { + uptr ranges, bytes; + if (memory_mapper->GetAndResetStats(ranges, bytes)) { region->rtoi.n_freed_at_last_release = region->stats.n_freed; - region->rtoi.num_releases += memory_mapper.GetReleasedRangesCount(); - region->rtoi.last_released_bytes = memory_mapper.GetReleasedBytes(); + region->rtoi.num_releases += ranges; + region->rtoi.last_released_bytes = bytes; } region->rtoi.last_release_at_ns = MonotonicNanoTime(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 64c15f1ec64eb..cbdbb0c4c4bd4 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -237,10 +237,16 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)); // Lock sanitizer error reporting and protects against nested errors. class ScopedErrorReportLock { public: - ScopedErrorReportLock(); - ~ScopedErrorReportLock(); + ScopedErrorReportLock() ACQUIRE(mutex_) { Lock(); } + ~ScopedErrorReportLock() RELEASE(mutex_) { Unlock(); } - static void CheckLocked(); + static void Lock() ACQUIRE(mutex_); + static void Unlock() RELEASE(mutex_); + static void CheckLocked() CHECK_LOCKED(mutex_); + + private: + static atomic_uintptr_t reporting_thread_; + static StaticSpinMutex mutex_; }; extern uptr stoptheworld_tracer_pid; @@ -1057,6 +1063,13 @@ class ArrayRef { T *end_ = nullptr; }; +#define PRINTF_128(v) \ + (*((u8 *)&v + 0)), (*((u8 *)&v + 1)), (*((u8 *)&v + 2)), (*((u8 *)&v + 3)), \ + (*((u8 *)&v + 4)), (*((u8 *)&v + 5)), (*((u8 *)&v + 6)), \ + (*((u8 *)&v + 7)), (*((u8 *)&v + 8)), (*((u8 *)&v + 9)), \ + (*((u8 *)&v + 10)), (*((u8 *)&v + 11)), (*((u8 *)&v + 12)), \ + (*((u8 *)&v + 13)), (*((u8 *)&v + 14)), (*((u8 *)&v + 15)) + } // namespace __sanitizer inline void *operator new(__sanitizer::operator_new_size_type size, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 7867fccde3907..d099978e21173 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -134,11 +134,11 @@ extern const short *_tolower_tab_; // Platform-specific options. #if SANITIZER_MAC -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false +#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 #elif SANITIZER_WINDOWS64 -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false +#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 #else -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true +#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 #endif // SANITIZER_MAC #ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE @@ -823,11 +823,11 @@ INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) { // N.B.: If we switch this to internal_ we'll have to use internal_memmove // due to memcpy being an alias of memmove on OS X. void *ctx; - if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { +#if PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size); - } else { +#else COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size); - } +#endif } #define INIT_MEMCPY \ @@ -957,6 +957,7 @@ INTERCEPTOR(double, frexp, double x, int *exp) { // Assuming frexp() always writes to |exp|. COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); double res = REAL(frexp)(x, exp); + COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp)); return res; } @@ -969,22 +970,18 @@ INTERCEPTOR(double, frexp, double x, int *exp) { INTERCEPTOR(float, frexpf, float x, int *exp) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp); - // FIXME: under ASan the call below may write to freed memory and corrupt - // its metadata. See - // https://github.com/google/sanitizers/issues/321. - float res = REAL(frexpf)(x, exp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); + float res = REAL(frexpf)(x, exp); + COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp)); return res; } INTERCEPTOR(long double, frexpl, long double x, int *exp) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp); - // FIXME: under ASan the call below may write to freed memory and corrupt - // its metadata. See - // https://github.com/google/sanitizers/issues/321. - long double res = REAL(frexpl)(x, exp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp)); + long double res = REAL(frexpl)(x, exp); + COMMON_INTERCEPTOR_INITIALIZE_RANGE(exp, sizeof(*exp)); return res; } @@ -5303,6 +5300,12 @@ INTERCEPTOR(__sanitizer_clock_t, times, void *tms) { #define INIT_TIMES #endif +#if SANITIZER_S390 && \ + (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET) +extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); +DEFINE_REAL(uptr, __tls_get_offset, void *arg) +#endif + #if SANITIZER_INTERCEPT_TLS_GET_ADDR #if !SANITIZER_S390 #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr) @@ -5342,11 +5345,7 @@ void *__tls_get_addr_opt(void *arg); // descriptor offset as an argument instead of a pointer. GOT address // is passed in r12, so it's necessary to write it in assembly. This is // the function used by the compiler. -extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg)); #define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset) -DEFINE_REAL(uptr, __tls_get_offset, void *arg) -extern "C" uptr __tls_get_offset(void *arg); -extern "C" uptr __interceptor___tls_get_offset(void *arg); INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg); @@ -5362,6 +5361,15 @@ INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { } return res; } +#endif // SANITIZER_S390 +#else +#define INIT_TLS_GET_ADDR +#endif + +#if SANITIZER_S390 && \ + (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET) +extern "C" uptr __tls_get_offset(void *arg); +extern "C" uptr __interceptor___tls_get_offset(void *arg); // We need a hidden symbol aliasing the above, so that we can jump // directly to it from the assembly below. extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"), @@ -5400,9 +5408,6 @@ asm( "br %r3\n" ".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n" ); -#endif // SANITIZER_S390 -#else -#define INIT_TLS_GET_ADDR #endif #if SANITIZER_INTERCEPT_LISTXATTR @@ -6463,7 +6468,7 @@ INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) { INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s); - int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s); + int res = REAL(sem_trywait)(s); if (res == 0) { COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp index 50ccfe5589711..65bc398656c93 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -100,6 +100,18 @@ bool SignalContext::IsStackOverflow() const { return false; } void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); } const char *SignalContext::Describe() const { UNIMPLEMENTED(); } +void FutexWait(atomic_uint32_t *p, u32 cmp) { + zx_status_t status = _zx_futex_wait(reinterpret_cast(p), cmp, + ZX_HANDLE_INVALID, ZX_TIME_INFINITE); + if (status != ZX_ERR_BAD_STATE) // Normal race. + CHECK_EQ(status, ZX_OK); +} + +void FutexWake(atomic_uint32_t *p, u32 count) { + zx_status_t status = _zx_futex_wake(reinterpret_cast(p), count); + CHECK_EQ(status, ZX_OK); +} + enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; BlockingMutex::BlockingMutex() { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index cc4dfd7dfe06d..9b7d87eb85e1a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -639,6 +639,26 @@ char **GetEnviron() { } #if !SANITIZER_SOLARIS +void FutexWait(atomic_uint32_t *p, u32 cmp) { +# if SANITIZER_FREEBSD + _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0); +# elif SANITIZER_NETBSD + sched_yield(); /* No userspace futex-like synchronization */ +# else + internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAIT_PRIVATE, cmp, 0, 0, 0); +# endif +} + +void FutexWake(atomic_uint32_t *p, u32 count) { +# if SANITIZER_FREEBSD + _umtx_op(p, UMTX_OP_WAKE, count, 0, 0); +# elif SANITIZER_NETBSD + /* No userspace futex-like synchronization */ +# else + internal_syscall(SYSCALL(futex), (uptr)p, FUTEX_WAKE_PRIVATE, count, 0, 0, 0); +# endif +} + enum { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 }; BlockingMutex::BlockingMutex() { @@ -878,7 +898,7 @@ void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); - k_set->sig[idx] &= ~(1 << bit); + k_set->sig[idx] &= ~((uptr)1 << bit); } bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { @@ -888,7 +908,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); - return k_set->sig[idx] & (1 << bit); + return k_set->sig[idx] & ((uptr)1 << bit); } #elif SANITIZER_FREEBSD void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index f1d9e625d755e..7ce9e25da342d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -317,21 +317,44 @@ struct TlsBlock { }; } // namespace +#ifdef __s390__ +extern "C" uptr __tls_get_offset(void *arg); + +static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) { + // The __tls_get_offset ABI requires %r12 to point to GOT and %r2 to be an + // offset of a struct tls_index inside GOT. We don't possess either of the + // two, so violate the letter of the "ELF Handling For Thread-Local + // Storage" document and assume that the implementation just dereferences + // %r2 + %r12. + uptr tls_index[2] = {ti_module, ti_offset}; + register uptr r2 asm("2") = 0; + register void *r12 asm("12") = tls_index; + asm("basr %%r14, %[__tls_get_offset]" + : "+r"(r2) + : [__tls_get_offset] "r"(__tls_get_offset), "r"(r12) + : "memory", "cc", "0", "1", "3", "4", "5", "14"); + return r2; +} +#else extern "C" void *__tls_get_addr(size_t *); +#endif static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size, void *data) { if (!info->dlpi_tls_modid) return 0; uptr begin = (uptr)info->dlpi_tls_data; -#ifndef __s390__ if (!g_use_dlpi_tls_data) { // Call __tls_get_addr as a fallback. This forces TLS allocation on glibc // and FreeBSD. +#ifdef __s390__ + begin = (uptr)__builtin_thread_pointer() + + TlsGetOffset(info->dlpi_tls_modid, 0); +#else size_t mod_and_off[2] = {info->dlpi_tls_modid, 0}; begin = (uptr)__tls_get_addr(mod_and_off); - } #endif + } for (unsigned i = 0; i != info->dlpi_phnum; ++i) if (info->dlpi_phdr[i].p_type == PT_TLS) { static_cast *>(data)->push_back( diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp index cf1b1250ae217..125ecac8b1287 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -509,6 +509,13 @@ void MprotectMallocZones(void *addr, int prot) { } } +void FutexWait(atomic_uint32_t *p, u32 cmp) { + // FIXME: implement actual blocking. + sched_yield(); +} + +void FutexWake(atomic_uint32_t *p, u32 count) {} + BlockingMutex::BlockingMutex() { internal_memset(this, 0, sizeof(*this)); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp new file mode 100644 index 0000000000000..bc2d83c42c1a3 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp @@ -0,0 +1,39 @@ +//===-- sanitizer_mutex.cpp -----------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is shared between AddressSanitizer and ThreadSanitizer +// run-time libraries. +//===----------------------------------------------------------------------===// + +#include "sanitizer_mutex.h" + +#include "sanitizer_common.h" + +namespace __sanitizer { + +void Semaphore::Wait() { + u32 count = atomic_load(&state_, memory_order_relaxed); + for (;;) { + if (count == 0) { + FutexWait(&state_, 0); + count = atomic_load(&state_, memory_order_relaxed); + continue; + } + if (atomic_compare_exchange_weak(&state_, &count, count - 1, + memory_order_acquire)) + break; + } +} + +void Semaphore::Post(u32 count) { + CHECK_NE(count, 0); + atomic_fetch_add(&state_, count, memory_order_release); + FutexWake(&state_, count); +} + +} // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h index 122a7a8d5a3d7..c9d9aa03bd306 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.h @@ -38,7 +38,7 @@ class MUTEX StaticSpinMutex { void Unlock() RELEASE() { atomic_store(&state_, 0, memory_order_release); } - void CheckLocked() const CHECK_LOCKED { + void CheckLocked() const CHECK_LOCKED() { CHECK_EQ(atomic_load(&state_, memory_order_relaxed), 1); } @@ -69,6 +69,25 @@ class MUTEX SpinMutex : public StaticSpinMutex { void operator=(const SpinMutex &) = delete; }; +// Semaphore provides an OS-dependent way to park/unpark threads. +// The last thread returned from Wait can destroy the object +// (destruction-safety). +class Semaphore { + public: + constexpr Semaphore() {} + Semaphore(const Semaphore &) = delete; + void operator=(const Semaphore &) = delete; + + void Wait(); + void Post(u32 count = 1); + + private: + atomic_uint32_t state_ = {0}; +}; + +void FutexWait(atomic_uint32_t *p, u32 cmp); +void FutexWake(atomic_uint32_t *p, u32 count); + class MUTEX BlockingMutex { public: explicit constexpr BlockingMutex(LinkerInitialized) @@ -84,7 +103,7 @@ class MUTEX BlockingMutex { // maintaining complex state to work around those situations, the check only // checks that the mutex is owned, and assumes callers to be generally // well-behaved. - void CheckLocked() const CHECK_LOCKED; + void CheckLocked() const CHECK_LOCKED(); private: // Solaris mutex_t has a member that requires 64-bit alignment. @@ -131,7 +150,7 @@ class MUTEX RWMutex { (void)prev; } - void CheckLocked() const CHECK_LOCKED { + void CheckLocked() const CHECK_LOCKED() { CHECK_NE(atomic_load(&state_, memory_order_relaxed), kUnlocked); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 8a156b7fcb80a..4dd27644ed116 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -650,14 +650,14 @@ struct __sanitizer_sigaction { #endif // !SANITIZER_ANDROID #if defined(__mips__) -struct __sanitizer_kernel_sigset_t { - uptr sig[2]; -}; +#define __SANITIZER_KERNEL_NSIG 128 #else +#define __SANITIZER_KERNEL_NSIG 64 +#endif + struct __sanitizer_kernel_sigset_t { - u8 sig[8]; + uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)]; }; -#endif // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros. #if SANITIZER_MIPS diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp index 5d16dfde67865..b913c92e16f10 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp @@ -20,6 +20,10 @@ #include #include +#if defined(__x86_64__) +# include +#endif + #if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 && \ !defined(va_copy) # define va_copy(dst, src) ((dst) = (src)) @@ -128,7 +132,7 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) { int VSNPrintf(char *buff, int buff_length, const char *format, va_list args) { static const char *kPrintfFormatsHelp = - "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; " + "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X,V}; %p; " "%[-]([0-9]*)?(\\.\\*)?s; %c\n"; RAW_CHECK(format); RAW_CHECK(buff_length > 0); @@ -162,17 +166,15 @@ int VSNPrintf(char *buff, int buff_length, cur += have_z; bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l'); cur += have_ll * 2; - s64 dval; - u64 uval; const bool have_length = have_z || have_ll; const bool have_flags = have_width || have_length; // At the moment only %s supports precision and left-justification. CHECK(!((precision >= 0 || left_justified) && *cur != 's')); switch (*cur) { case 'd': { - dval = have_ll ? va_arg(args, s64) - : have_z ? va_arg(args, sptr) - : va_arg(args, int); + s64 dval = have_ll ? va_arg(args, s64) + : have_z ? va_arg(args, sptr) + : va_arg(args, int); result += AppendSignedDecimal(&buff, buff_end, dval, width, pad_with_zero); break; @@ -180,14 +182,21 @@ int VSNPrintf(char *buff, int buff_length, case 'u': case 'x': case 'X': { - uval = have_ll ? va_arg(args, u64) - : have_z ? va_arg(args, uptr) - : va_arg(args, unsigned); + u64 uval = have_ll ? va_arg(args, u64) + : have_z ? va_arg(args, uptr) + : va_arg(args, unsigned); bool uppercase = (*cur == 'X'); result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16, width, pad_with_zero, uppercase); break; } + case 'V': { + for (uptr i = 0; i < 16; i++) { + unsigned x = va_arg(args, unsigned); + result += AppendUnsigned(&buff, buff_end, x, 16, 2, true, false); + } + break; + } case 'p': { RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendPointer(&buff, buff_end, va_arg(args, uptr)); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp index c43c26dc615f6..cb53eab8da150 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp @@ -160,6 +160,13 @@ DECLARE__REAL_AND_INTERNAL(uptr, sched_yield, void) { return sched_yield(); } +DECLARE__REAL_AND_INTERNAL(void, usleep, u64 useconds) { + struct timespec ts; + ts.tv_sec = useconds / 1000000; + ts.tv_nsec = (useconds % 1000000) * 1000; + nanosleep(&ts, nullptr); +} + DECLARE__REAL_AND_INTERNAL(uptr, execve, const char *filename, char *const argv[], char *const envp[]) { return _REAL(execve)(filename, argv, envp); @@ -211,6 +218,13 @@ uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { } // ----------------- sanitizer_common.h +void FutexWait(atomic_uint32_t *p, u32 cmp) { + // FIXME: implement actual blocking. + sched_yield(); +} + +void FutexWake(atomic_uint32_t *p, u32 count) {} + BlockingMutex::BlockingMutex() { CHECK(sizeof(mutex_t) <= sizeof(opaque_storage_)); internal_memset(this, 0, sizeof(*this)); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index 6b2a687a990ca..ea330f36f7d79 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -196,5 +196,26 @@ static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) { uptr local_stack; \ uptr sp = (uptr)&local_stack +// GET_CURRENT_PC() is equivalent to StackTrace::GetCurrentPc(). +// Optimized x86 version is faster than GetCurrentPc because +// it does not involve a function call, instead it reads RIP register. +// Reads of RIP by an instruction return RIP pointing to the next +// instruction, which is exactly what we want here, thus 0 offset. +// It needs to be a macro because otherwise we will get the name +// of this function on the top of most stacks. Attribute artificial +// does not do what it claims to do, unfortunatley. And attribute +// __nodebug__ is clang-only. If we would have an attribute that +// would remove this function from debug info, we could simply make +// StackTrace::GetCurrentPc() faster. +#if defined(__x86_64__) +# define GET_CURRENT_PC() \ + ({ \ + uptr pc; \ + asm("lea 0(%%rip), %0" : "=r"(pc)); \ + pc; \ + }) +#else +# define GET_CURRENT_PC() StackTrace::GetCurrentPc() +#endif #endif // SANITIZER_STACKTRACE_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp index 1f65a6aef7105..f330ed36640a9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -250,17 +250,17 @@ void HandleDeadlySignal(void *siginfo, void *context, u32 tid, #endif // !SANITIZER_FUCHSIA && !SANITIZER_GO -static atomic_uintptr_t reporting_thread = {0}; -static StaticSpinMutex CommonSanitizerReportMutex; +atomic_uintptr_t ScopedErrorReportLock::reporting_thread_ = {0}; +StaticSpinMutex ScopedErrorReportLock::mutex_; -ScopedErrorReportLock::ScopedErrorReportLock() { +void ScopedErrorReportLock::Lock() { uptr current = GetThreadSelf(); for (;;) { uptr expected = 0; - if (atomic_compare_exchange_strong(&reporting_thread, &expected, current, + if (atomic_compare_exchange_strong(&reporting_thread_, &expected, current, memory_order_relaxed)) { // We've claimed reporting_thread so proceed. - CommonSanitizerReportMutex.Lock(); + mutex_.Lock(); return; } @@ -282,13 +282,11 @@ ScopedErrorReportLock::ScopedErrorReportLock() { } } -ScopedErrorReportLock::~ScopedErrorReportLock() { - CommonSanitizerReportMutex.Unlock(); - atomic_store_relaxed(&reporting_thread, 0); +void ScopedErrorReportLock::Unlock() { + mutex_.Unlock(); + atomic_store_relaxed(&reporting_thread_, 0); } -void ScopedErrorReportLock::CheckLocked() { - CommonSanitizerReportMutex.CheckLocked(); -} +void ScopedErrorReportLock::CheckLocked() { mutex_.CheckLocked(); } } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h b/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h index ded9e3af14065..0b28bbe6ddf6e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.h @@ -95,12 +95,12 @@ class MUTEX ThreadRegistry { uptr GetMaxAliveThreads(); void Lock() ACQUIRE() { mtx_.Lock(); } - void CheckLocked() const CHECK_LOCKED { mtx_.CheckLocked(); } + void CheckLocked() const CHECK_LOCKED() { mtx_.CheckLocked(); } void Unlock() RELEASE() { mtx_.Unlock(); } // Should be guarded by ThreadRegistryLock. ThreadContextBase *GetThreadLocked(u32 tid) { - return threads_[tid]; + return threads_.empty() ? nullptr : threads_[tid]; } u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_thread_safety.h b/compiler-rt/lib/sanitizer_common/sanitizer_thread_safety.h index 949b98f4c1ad0..52b25edaa7a3e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_thread_safety.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_thread_safety.h @@ -36,7 +36,7 @@ #define RELEASE_SHARED(...) \ THREAD_ANNOTATION(release_shared_capability(__VA_ARGS__)) #define EXCLUDES(...) THREAD_ANNOTATION(locks_excluded(__VA_ARGS__)) -#define CHECK_LOCKED THREAD_ANNOTATION(assert_capability(this)) +#define CHECK_LOCKED(...) THREAD_ANNOTATION(assert_capability(__VA_ARGS__)) #define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION(no_thread_safety_analysis) #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp index 93700bde04a96..dddd885a45dd2 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -44,6 +44,9 @@ TRACELOGGING_DEFINE_PROVIDER(g_asan_provider, "AddressSanitizerLoggingProvider", #define TraceLoggingUnregister(x) #endif +// For WaitOnAddress +# pragma comment(lib, "synchronization.lib") + // A macro to tell the compiler that this part of the code cannot be reached, // if the compiler supports this feature. Since we're using this in // code that is called when terminating the process, the expansion of the @@ -813,6 +816,17 @@ uptr GetRSS() { void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; } void internal_join_thread(void *th) { } +void FutexWait(atomic_uint32_t *p, u32 cmp) { + WaitOnAddress(p, &cmp, sizeof(cmp), INFINITE); +} + +void FutexWake(atomic_uint32_t *p, u32 count) { + if (count == 1) + WakeByAddressSingle(p); + else + WakeByAddressAll(p); +} + // ---------------------- BlockingMutex ---------------- {{{1 BlockingMutex::BlockingMutex() { diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp index 58f1ef404ba69..8952fa4da0533 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp @@ -1149,15 +1149,12 @@ TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) { class NoMemoryMapper { public: - uptr last_request_buffer_size; + uptr last_request_buffer_size = 0; - NoMemoryMapper() : last_request_buffer_size(0) {} - - void *MapPackedCounterArrayBuffer(uptr buffer_size) { - last_request_buffer_size = buffer_size; + u64 *MapPackedCounterArrayBuffer(uptr buffer_size) { + last_request_buffer_size = buffer_size * sizeof(u64); return nullptr; } - void UnmapPackedCounterArrayBuffer(void *buffer, uptr buffer_size) {} }; class RedZoneMemoryMapper { @@ -1168,19 +1165,17 @@ class RedZoneMemoryMapper { MprotectNoAccess(reinterpret_cast(buffer), page_size); MprotectNoAccess(reinterpret_cast(buffer) + page_size * 2, page_size); } - ~RedZoneMemoryMapper() { - UnmapOrDie(buffer, 3 * GetPageSize()); - } + ~RedZoneMemoryMapper() { UnmapOrDie(buffer, 3 * GetPageSize()); } - void *MapPackedCounterArrayBuffer(uptr buffer_size) { + u64 *MapPackedCounterArrayBuffer(uptr buffer_size) { + buffer_size *= sizeof(u64); const auto page_size = GetPageSize(); CHECK_EQ(buffer_size, page_size); - void *p = - reinterpret_cast(reinterpret_cast(buffer) + page_size); + u64 *p = + reinterpret_cast(reinterpret_cast(buffer) + page_size); memset(p, 0, page_size); return p; } - void UnmapPackedCounterArrayBuffer(void *buffer, uptr buffer_size) {} private: void *buffer; @@ -1188,35 +1183,31 @@ class RedZoneMemoryMapper { TEST(SanitizerCommon, SizeClassAllocator64PackedCounterArray) { NoMemoryMapper no_memory_mapper; - typedef Allocator64::PackedCounterArray - NoMemoryPackedCounterArray; - for (int i = 0; i < 64; i++) { // Various valid counter's max values packed into one word. - NoMemoryPackedCounterArray counters_2n(1, 1ULL << i, &no_memory_mapper); + Allocator64::PackedCounterArray counters_2n(1, 1ULL << i, + &no_memory_mapper); EXPECT_EQ(8ULL, no_memory_mapper.last_request_buffer_size); // Check the "all bit set" values too. - NoMemoryPackedCounterArray counters_2n1_1(1, ~0ULL >> i, &no_memory_mapper); + Allocator64::PackedCounterArray counters_2n1_1(1, ~0ULL >> i, + &no_memory_mapper); EXPECT_EQ(8ULL, no_memory_mapper.last_request_buffer_size); // Verify the packing ratio, the counter is expected to be packed into the // closest power of 2 bits. - NoMemoryPackedCounterArray counters(64, 1ULL << i, &no_memory_mapper); + Allocator64::PackedCounterArray counters(64, 1ULL << i, &no_memory_mapper); EXPECT_EQ(8ULL * RoundUpToPowerOfTwo(i + 1), no_memory_mapper.last_request_buffer_size); } RedZoneMemoryMapper memory_mapper; - typedef Allocator64::PackedCounterArray - RedZonePackedCounterArray; // Go through 1, 2, 4, 8, .. 64 bits per counter. for (int i = 0; i < 7; i++) { // Make sure counters request one memory page for the buffer. const u64 kNumCounters = (GetPageSize() / 8) * (64 >> i); - RedZonePackedCounterArray counters(kNumCounters, - 1ULL << ((1 << i) - 1), - &memory_mapper); + Allocator64::PackedCounterArray counters( + kNumCounters, 1ULL << ((1 << i) - 1), &memory_mapper); counters.Inc(0); for (u64 c = 1; c < kNumCounters - 1; c++) { ASSERT_EQ(0ULL, counters.Get(c)); @@ -1243,7 +1234,7 @@ class RangeRecorder { Log2(GetPageSizeCached() >> Allocator64::kCompactPtrScale)), last_page_reported(0) {} - void ReleasePageRangeToOS(u32 from, u32 to) { + void ReleasePageRangeToOS(u32 class_id, u32 from, u32 to) { from >>= page_size_scaled_log; to >>= page_size_scaled_log; ASSERT_LT(from, to); @@ -1253,6 +1244,7 @@ class RangeRecorder { reported_pages.append(to - from, 'x'); last_page_reported = to; } + private: const uptr page_size_scaled_log; u32 last_page_reported; @@ -1282,7 +1274,7 @@ TEST(SanitizerCommon, SizeClassAllocator64FreePagesRangeTracker) { for (auto test_case : test_cases) { RangeRecorder range_recorder; - RangeTracker tracker(&range_recorder); + RangeTracker tracker(&range_recorder, 1); for (int i = 0; test_case[i] != 0; i++) tracker.NextPage(test_case[i] == 'x'); tracker.Done(); @@ -1299,16 +1291,14 @@ TEST(SanitizerCommon, SizeClassAllocator64FreePagesRangeTracker) { class ReleasedPagesTrackingMemoryMapper { public: std::set reported_pages; + std::vector buffer; - void *MapPackedCounterArrayBuffer(uptr buffer_size) { + u64 *MapPackedCounterArrayBuffer(uptr buffer_size) { reported_pages.clear(); - return calloc(1, buffer_size); - } - void UnmapPackedCounterArrayBuffer(void *buffer, uptr buffer_size) { - free(buffer); + buffer.assign(buffer_size, 0); + return buffer.data(); } - - void ReleasePageRangeToOS(u32 from, u32 to) { + void ReleasePageRangeToOS(u32 class_id, u32 from, u32 to) { uptr page_size_scaled = GetPageSizeCached() >> Allocator64::kCompactPtrScale; for (u32 i = from; i < to; i += page_size_scaled) @@ -1352,7 +1342,7 @@ void TestReleaseFreeMemoryToOS() { Allocator::ReleaseFreeMemoryToOS(&free_array[0], free_array.size(), chunk_size, kAllocatedPagesCount, - &memory_mapper); + &memory_mapper, class_id); // Verify that there are no released pages touched by used chunks and all // ranges of free chunks big enough to contain the entire memory pages had diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp index 2cfbaae6317a0..beaad9c19345b 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_mutex_test.cpp @@ -133,4 +133,34 @@ TEST(SanitizerCommon, BlockingMutex) { check_locked(mtx); } +struct SemaphoreData { + Semaphore *sem; + bool done; +}; + +void *SemaphoreThread(void *arg) { + auto data = static_cast(arg); + data->sem->Wait(); + data->done = true; + return nullptr; +} + +TEST(SanitizerCommon, Semaphore) { + Semaphore sem; + sem.Post(1); + sem.Wait(); + sem.Post(3); + sem.Wait(); + sem.Wait(); + sem.Wait(); + + SemaphoreData data = {&sem, false}; + pthread_t thread; + PTHREAD_CREATE(&thread, nullptr, SemaphoreThread, &data); + internal_sleep(1); + CHECK(!data.done); + sem.Post(1); + PTHREAD_JOIN(thread, nullptr); +} + } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cpp index 956ed65450196..7a3724c3ab39f 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_printf_test.cpp @@ -16,6 +16,10 @@ #include #include +#ifdef __x86_64__ +# include +#endif + namespace __sanitizer { TEST(Printf, Basic) { @@ -154,4 +158,18 @@ TEST(Printf, Precision) { EXPECT_STREQ("12345 ", buf); } +#ifdef __x86_64__ +TEST(Printf, M128) { + __m128i v = _mm_set_epi32(0x12345678, 0x0a0a0a0a, 0xb0b0b0b0, 0xaabbccdd); + char buf[128]; + internal_snprintf(buf, sizeof(buf), "%V", PRINTF_128(v)); + EXPECT_STREQ("ddccbbaab0b0b0b00a0a0a0a78563412", buf); + v = _mm_cvtsi32_si128(0x12345678); + internal_snprintf(buf, sizeof(buf), "%V", PRINTF_128(v)); + EXPECT_STREQ("78563412000000000000000000000000", buf); + internal_snprintf(buf, sizeof(buf), "%d %V", 0, PRINTF_128(v)); + EXPECT_STREQ("0 78563412000000000000000000000000", buf); +} +#endif + } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp index 30cc197bb2429..72023ea432da2 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cpp @@ -271,6 +271,30 @@ TEST(SlowUnwindTest, ShortStackTrace) { EXPECT_EQ(bp, stack.top_frame_bp); } +TEST(GetCurrentPc, Basic) { + // Test that PCs obtained via GET_CURRENT_PC() + // and StackTrace::GetCurrentPc() are all different + // and are close to the function start. + struct Local { + static NOINLINE void Test() { + const uptr pcs[] = { + (uptr)&Local::Test, + GET_CURRENT_PC(), + StackTrace::GetCurrentPc(), + StackTrace::GetCurrentPc(), + }; + for (uptr i = 0; i < ARRAY_SIZE(pcs); i++) + Printf("pc%zu: %p\n", i, pcs[i]); + for (uptr i = 1; i < ARRAY_SIZE(pcs); i++) { + EXPECT_GT(pcs[i], pcs[0]); + EXPECT_LT(pcs[i], pcs[0] + 1000); + for (uptr j = 0; j < i; j++) EXPECT_NE(pcs[i], pcs[j]); + } + } + }; + Local::Test(); +} + // Dummy implementation. This should never be called, but is required to link // non-optimized builds of this test. void BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context, diff --git a/compiler-rt/lib/scudo/scudo_tsd_exclusive.inc b/compiler-rt/lib/scudo/scudo_tsd_exclusive.inc index 6e781c11cc7a5..29db8a2eff1a0 100644 --- a/compiler-rt/lib/scudo/scudo_tsd_exclusive.inc +++ b/compiler-rt/lib/scudo/scudo_tsd_exclusive.inc @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// #ifndef SCUDO_TSD_H_ -# error "This file must be included inside scudo_tsd.h." -#endif // SCUDO_TSD_H_ +#error "This file must be included inside scudo_tsd.h." +#endif // SCUDO_TSD_H_ #if SCUDO_TSD_EXCLUSIVE @@ -21,10 +21,9 @@ enum ThreadState : u8 { ThreadInitialized, ThreadTornDown, }; -__attribute__((tls_model("initial-exec"))) -extern THREADLOCAL ThreadState ScudoThreadState; -__attribute__((tls_model("initial-exec"))) -extern THREADLOCAL ScudoTSD TSD; +__attribute__(( + tls_model("initial-exec"))) extern THREADLOCAL ThreadState ScudoThreadState; +__attribute__((tls_model("initial-exec"))) extern THREADLOCAL ScudoTSD TSD; extern ScudoTSD FallbackTSD; @@ -34,7 +33,8 @@ ALWAYS_INLINE void initThreadMaybe(bool MinimalInit = false) { initThread(MinimalInit); } -ALWAYS_INLINE ScudoTSD *getTSDAndLock(bool *UnlockRequired) NO_THREAD_SAFETY_ANALYSIS { +ALWAYS_INLINE ScudoTSD * +getTSDAndLock(bool *UnlockRequired) NO_THREAD_SAFETY_ANALYSIS { if (UNLIKELY(ScudoThreadState != ThreadInitialized)) { FallbackTSD.lock(); *UnlockRequired = true; @@ -44,4 +44,4 @@ ALWAYS_INLINE ScudoTSD *getTSDAndLock(bool *UnlockRequired) NO_THREAD_SAFETY_ANA return &TSD; } -#endif // SCUDO_TSD_EXCLUSIVE +#endif // SCUDO_TSD_EXCLUSIVE diff --git a/compiler-rt/lib/scudo/scudo_tsd_shared.cpp b/compiler-rt/lib/scudo/scudo_tsd_shared.cpp index 59ad2549998cc..fd85a7c4017f8 100644 --- a/compiler-rt/lib/scudo/scudo_tsd_shared.cpp +++ b/compiler-rt/lib/scudo/scudo_tsd_shared.cpp @@ -64,7 +64,7 @@ void initThread(bool MinimalInit) { setCurrentTSD(&TSDs[Index % NumberOfTSDs]); } -ScudoTSD *getTSDAndLockSlow(ScudoTSD *TSD) { +ScudoTSD *getTSDAndLockSlow(ScudoTSD *TSD) NO_THREAD_SAFETY_ANALYSIS { if (NumberOfTSDs > 1) { // Use the Precedence of the current TSD as our random seed. Since we are in // the slow path, it means that tryLock failed, and as a result it's very diff --git a/compiler-rt/lib/scudo/scudo_tsd_shared.inc b/compiler-rt/lib/scudo/scudo_tsd_shared.inc index 8f3362dd3d710..e46b044a81f81 100644 --- a/compiler-rt/lib/scudo/scudo_tsd_shared.inc +++ b/compiler-rt/lib/scudo/scudo_tsd_shared.inc @@ -41,7 +41,8 @@ ALWAYS_INLINE void initThreadMaybe(bool MinimalInit = false) { ScudoTSD *getTSDAndLockSlow(ScudoTSD *TSD); -ALWAYS_INLINE ScudoTSD *getTSDAndLock(bool *UnlockRequired) { +ALWAYS_INLINE ScudoTSD * +getTSDAndLock(bool *UnlockRequired) NO_THREAD_SAFETY_ANALYSIS { ScudoTSD *TSD = getCurrentTSD(); DCHECK(TSD && "No TSD associated with the current thread!"); *UnlockRequired = true; diff --git a/compiler-rt/lib/scudo/standalone/memtag.h b/compiler-rt/lib/scudo/standalone/memtag.h index cd8d95a3f7563..c48e228fbe44f 100644 --- a/compiler-rt/lib/scudo/standalone/memtag.h +++ b/compiler-rt/lib/scudo/standalone/memtag.h @@ -319,7 +319,8 @@ inline void *addFixedTag(void *Ptr, uptr Tag) { template inline constexpr bool allocatorSupportsMemoryTagging() { - return archSupportsMemoryTagging() && Config::MaySupportMemoryTagging; + return archSupportsMemoryTagging() && Config::MaySupportMemoryTagging && + (1 << SCUDO_MIN_ALIGNMENT_LOG) >= archMemoryTagGranuleSize(); } } // namespace scudo diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt index b77137633171f..c1fa34fdf2053 100644 --- a/compiler-rt/lib/tsan/CMakeLists.txt +++ b/compiler-rt/lib/tsan/CMakeLists.txt @@ -219,6 +219,20 @@ else() add_asm_sources(TSAN_ASM_SOURCES rtl/tsan_rtl_mips64.S ) + elseif(arch MATCHES "s390x") + add_asm_sources(TSAN_ASM_SOURCES + rtl/tsan_rtl_s390x.S + ) + # Sanity check for Go runtime. + set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh) + add_custom_target(GotsanRuntimeCheck + COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" + EXTRA_CFLAGS=${EXTRA_CFLAGS} + IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT} + DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go + COMMENT "Checking TSan Go runtime..." + VERBATIM) else() set(TSAN_ASM_SOURCES) endif() diff --git a/compiler-rt/lib/tsan/go/build.bat b/compiler-rt/lib/tsan/go/build.bat index 0755688e5bd3e..5e2ebb84aecf2 100644 --- a/compiler-rt/lib/tsan/go/build.bat +++ b/compiler-rt/lib/tsan/go/build.bat @@ -33,6 +33,7 @@ type ^ ..\..\sanitizer_common\sanitizer_termination.cpp ^ ..\..\sanitizer_common\sanitizer_file.cpp ^ ..\..\sanitizer_common\sanitizer_symbolizer_report.cpp ^ + ..\..\sanitizer_common\sanitizer_mutex.cpp ^ ..\rtl\tsan_external.cpp ^ > gotsan.cpp diff --git a/compiler-rt/lib/tsan/go/buildgo.sh b/compiler-rt/lib/tsan/go/buildgo.sh index 0902d10f4f152..b57bb4e695253 100755 --- a/compiler-rt/lib/tsan/go/buildgo.sh +++ b/compiler-rt/lib/tsan/go/buildgo.sh @@ -28,6 +28,7 @@ SRCS=" ../../sanitizer_common/sanitizer_flag_parser.cpp ../../sanitizer_common/sanitizer_flags.cpp ../../sanitizer_common/sanitizer_libc.cpp + ../../sanitizer_common/sanitizer_mutex.cpp ../../sanitizer_common/sanitizer_persistent_allocator.cpp ../../sanitizer_common/sanitizer_printf.cpp ../../sanitizer_common/sanitizer_suppressions.cpp @@ -72,6 +73,10 @@ if [ "`uname -a | grep Linux`" != "" ]; then SUFFIX="linux_mips64" ARCHCFLAGS="-mips64 -EB" fi + elif [ "`uname -a | grep s390x`" != "" ]; then + SRCS="$SRCS ../../sanitizer_common/sanitizer_linux_s390.cpp" + SUFFIX="linux_s390x" + ARCHCFLAGS="" fi elif [ "`uname -a | grep FreeBSD`" != "" ]; then # The resulting object still depends on libc. diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.h b/compiler-rt/lib/tsan/rtl/tsan_interceptors.h index 29576ea2d49ad..c5716f53a323a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.h +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.h @@ -30,14 +30,14 @@ inline bool in_symbolizer() { } // namespace __tsan -#define SCOPED_INTERCEPTOR_RAW(func, ...) \ - cur_thread_init(); \ - ThreadState *thr = cur_thread(); \ - const uptr caller_pc = GET_CALLER_PC(); \ - ScopedInterceptor si(thr, #func, caller_pc); \ - const uptr pc = StackTrace::GetCurrentPc(); \ - (void)pc; \ -/**/ +#define SCOPED_INTERCEPTOR_RAW(func, ...) \ + cur_thread_init(); \ + ThreadState *thr = cur_thread(); \ + const uptr caller_pc = GET_CALLER_PC(); \ + ScopedInterceptor si(thr, #func, caller_pc); \ + const uptr pc = GET_CURRENT_PC(); \ + (void)pc; \ + /**/ #define SCOPED_TSAN_INTERCEPTOR(func, ...) \ SCOPED_INTERCEPTOR_RAW(func, __VA_ARGS__); \ diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp index ed10fccc980a4..2d400c7e7098d 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_mac.cpp @@ -44,8 +44,9 @@ namespace __tsan { // actually aliases of each other, and we cannot have different interceptors for // them, because they're actually the same function. Thus, we have to stay // conservative and treat the non-barrier versions as mo_acq_rel. -static const morder kMacOrderBarrier = mo_acq_rel; -static const morder kMacOrderNonBarrier = mo_acq_rel; +static constexpr morder kMacOrderBarrier = mo_acq_rel; +static constexpr morder kMacOrderNonBarrier = mo_acq_rel; +static constexpr morder kMacFailureOrder = mo_relaxed; #define OSATOMIC_INTERCEPTOR(return_t, t, tsan_t, f, tsan_atomic_f, mo) \ TSAN_INTERCEPTOR(return_t, f, t x, volatile t *ptr) { \ @@ -110,7 +111,7 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, SCOPED_TSAN_INTERCEPTOR(f, old_value, new_value, ptr); \ return tsan_atomic_f##_compare_exchange_strong( \ (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ - kMacOrderNonBarrier, kMacOrderNonBarrier); \ + kMacOrderNonBarrier, kMacFailureOrder); \ } \ \ TSAN_INTERCEPTOR(bool, f##Barrier, t old_value, t new_value, \ @@ -118,7 +119,7 @@ OSATOMIC_INTERCEPTORS_BITWISE(OSAtomicXor, fetch_xor, SCOPED_TSAN_INTERCEPTOR(f##Barrier, old_value, new_value, ptr); \ return tsan_atomic_f##_compare_exchange_strong( \ (volatile tsan_t *)ptr, (tsan_t *)&old_value, (tsan_t)new_value, \ - kMacOrderBarrier, kMacOrderNonBarrier); \ + kMacOrderBarrier, kMacFailureOrder); \ } OSATOMIC_INTERCEPTORS_CAS(OSAtomicCompareAndSwapInt, __tsan_atomic32, a32, int) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 2651e22c39fa9..6808f2e0e2d3d 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -71,7 +71,8 @@ struct ucontext_t { }; #endif -#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 +#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \ + defined(__s390x__) #define PTHREAD_ABI_BASE "GLIBC_2.3.2" #elif defined(__aarch64__) || SANITIZER_PPC64V2 #define PTHREAD_ABI_BASE "GLIBC_2.17" @@ -2270,6 +2271,7 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, #define NEED_TLS_GET_ADDR #endif #undef SANITIZER_INTERCEPT_TLS_GET_ADDR +#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1 #undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) @@ -2585,6 +2587,20 @@ static void syscall_post_fork(uptr pc, int pid) { #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" #ifdef NEED_TLS_GET_ADDR + +static void handle_tls_addr(void *arg, void *res) { + ThreadState *thr = cur_thread(); + if (!thr) + return; + DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, + thr->tls_addr + thr->tls_size); + if (!dtv) + return; + // New DTLS block has been allocated. + MemoryResetRange(thr, 0, dtv->beg, dtv->size); +} + +#if !SANITIZER_S390 // Define own interceptor instead of sanitizer_common's for three reasons: // 1. It must not process pending signals. // Signal handlers may contain MOVDQA instruction (see below). @@ -2597,18 +2613,18 @@ static void syscall_post_fork(uptr pc, int pid) { // execute MOVDQA with stack addresses. TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) { void *res = REAL(__tls_get_addr)(arg); - ThreadState *thr = cur_thread(); - if (!thr) - return res; - DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr, - thr->tls_addr + thr->tls_size); - if (!dtv) - return res; - // New DTLS block has been allocated. - MemoryResetRange(thr, 0, dtv->beg, dtv->size); + handle_tls_addr(arg, res); + return res; +} +#else // SANITIZER_S390 +TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) { + uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset)); + char *tp = static_cast(__builtin_thread_pointer()); + handle_tls_addr(arg, res + tp); return res; } #endif +#endif #if SANITIZER_NETBSD TSAN_INTERCEPTOR(void, _lwp_exit) { @@ -2830,7 +2846,12 @@ void InitializeInterceptors() { TSAN_INTERCEPT(_exit); #ifdef NEED_TLS_GET_ADDR +#if !SANITIZER_S390 TSAN_INTERCEPT(__tls_get_addr); +#else + TSAN_INTERCEPT(__tls_get_addr_internal); + TSAN_INTERCEPT(__tls_get_offset); +#endif #endif TSAN_MAYBE_INTERCEPT__LWP_EXIT; diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface.h b/compiler-rt/lib/tsan/rtl/tsan_interface.h index 6e022b56850cf..124aa2fd21431 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface.h +++ b/compiler-rt/lib/tsan/rtl/tsan_interface.h @@ -196,7 +196,8 @@ typedef unsigned short a16; typedef unsigned int a32; typedef unsigned long long a64; #if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \ - || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64) + || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \ + !defined(__mips64) && !defined(__s390x__) __extension__ typedef __int128 a128; # define __TSAN_HAS_INT128 1 #else diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index 101522d8fa4aa..8bd218e25fd6f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -365,6 +365,38 @@ struct Mapping47 { // Indicates the runtime will define the memory regions at runtime. #define TSAN_RUNTIME_VMA 1 +#elif defined(__s390x__) +/* +C/C++ on linux/s390x +While the kernel provides a 64-bit address space, we have to restrict ourselves +to 48 bits due to how e.g. SyncVar::GetId() works. +0000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB +0e00 0000 0000 - 4000 0000 0000: - +4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) +8000 0000 0000 - 9000 0000 0000: - +9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) +9800 0000 0000 - a000 0000 0000: - +a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) +b000 0000 0000 - be00 0000 0000: - +be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator) +*/ +struct Mapping { + static const uptr kMetaShadowBeg = 0x900000000000ull; + static const uptr kMetaShadowEnd = 0x980000000000ull; + static const uptr kTraceMemBeg = 0xa00000000000ull; + static const uptr kTraceMemEnd = 0xb00000000000ull; + static const uptr kShadowBeg = 0x400000000000ull; + static const uptr kShadowEnd = 0x800000000000ull; + static const uptr kHeapMemBeg = 0xbe0000000000ull; + static const uptr kHeapMemEnd = 0xc00000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x0e0000000000ull; + static const uptr kHiAppMemBeg = 0xc00000004000ull; + static const uptr kHiAppMemEnd = 0xc00000004000ull; + static const uptr kAppMemMsk = 0xb00000000000ull; + static const uptr kAppMemXor = 0x100000000000ull; + static const uptr kVdsoBeg = 0xfffffffff000ull; +}; #endif #elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE @@ -528,6 +560,28 @@ struct Mapping47 { #define TSAN_RUNTIME_VMA 1 +#elif SANITIZER_GO && defined(__s390x__) +/* +Go on linux/s390x +0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB +1000 0000 0000 - 4000 0000 0000: - +4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app) +8000 0000 0000 - 9000 0000 0000: - +9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app) +9800 0000 0000 - a000 0000 0000: - +a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads) +*/ +struct Mapping { + static const uptr kMetaShadowBeg = 0x900000000000ull; + static const uptr kMetaShadowEnd = 0x980000000000ull; + static const uptr kTraceMemBeg = 0xa00000000000ull; + static const uptr kTraceMemEnd = 0xb00000000000ull; + static const uptr kShadowBeg = 0x400000000000ull; + static const uptr kShadowEnd = 0x800000000000ull; + static const uptr kAppMemBeg = 0x000000001000ull; + static const uptr kAppMemEnd = 0x100000000000ull; +}; + #else # error "Unknown platform" #endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp index e5b6690edfd01..cfe597e5380e5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp @@ -391,6 +391,10 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { return mangled_sp ^ xor_key; #elif defined(__mips__) return mangled_sp; +#elif defined(__s390x__) + // tcbhead_t.stack_guard + uptr xor_key = ((uptr *)__builtin_thread_pointer())[5]; + return mangled_sp ^ xor_key; #else #error "Unknown platform" #endif @@ -411,6 +415,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { # define LONG_JMP_SP_ENV_SLOT 13 # elif defined(__mips64) # define LONG_JMP_SP_ENV_SLOT 1 +# elif defined(__s390x__) +# define LONG_JMP_SP_ENV_SLOT 9 # else # define LONG_JMP_SP_ENV_SLOT 6 # endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp index 73e1d4577c2c2..1c6198cefcd78 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp @@ -72,11 +72,15 @@ void InitializeShadowMemory() { InitializeShadowMemoryPlatform(); } -static void ProtectRange(uptr beg, uptr end) { +static bool TryProtectRange(uptr beg, uptr end) { CHECK_LE(beg, end); if (beg == end) - return; - if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) { + return true; + return beg == (uptr)MmapFixedNoAccess(beg, end - beg); +} + +static void ProtectRange(uptr beg, uptr end) { + if (!TryProtectRange(beg, end)) { Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); Printf("FATAL: Make sure you are not using unlimited stack\n"); Die(); @@ -118,6 +122,16 @@ void CheckAndProtect() { ProtectRange(TraceMemEnd(), HeapMemBeg()); ProtectRange(HeapEnd(), HiAppMemBeg()); #endif + +#if defined(__s390x__) + // Protect the rest of the address space. + const uptr user_addr_max_l4 = 0x0020000000000000ull; + const uptr user_addr_max_l5 = 0xfffffffffffff000ull; + // All the maintained s390x kernels support at least 4-level page tables. + ProtectRange(HiAppMemEnd(), user_addr_max_l4); + // Older s390x kernels may not support 5-level page tables. + TryProtectRange(user_addr_max_l4, user_addr_max_l5); +#endif } #endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp index e704cbde1dbe9..2d49b9a39a547 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -77,7 +77,7 @@ void OnInitialize() { } #endif -static char thread_registry_placeholder[sizeof(ThreadRegistry)]; +static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)]; static ThreadContextBase *CreateThreadContext(u32 tid) { // Map thread trace when context is created. @@ -534,6 +534,7 @@ int Finalize(ThreadState *thr) { void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { ctx->thread_registry->Lock(); ctx->report_mtx.Lock(); + ScopedErrorReportLock::Lock(); // Suppress all reports in the pthread_atfork callbacks. // Reports will deadlock on the report_mtx. // We could ignore sync operations as well, @@ -548,6 +549,7 @@ void ForkBefore(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { thr->suppress_reports--; // Enabled in ForkBefore. thr->ignore_interceptors--; + ScopedErrorReportLock::Unlock(); ctx->report_mtx.Unlock(); ctx->thread_registry->Unlock(); } @@ -555,6 +557,7 @@ void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { void ForkChildAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { thr->suppress_reports--; // Enabled in ForkBefore. thr->ignore_interceptors--; + ScopedErrorReportLock::Unlock(); ctx->report_mtx.Unlock(); ctx->thread_registry->Unlock(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S new file mode 100644 index 0000000000000..fcff35fbc7e07 --- /dev/null +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S @@ -0,0 +1,47 @@ +#include "sanitizer_common/sanitizer_asm.h" + +#define CFA_OFFSET 160 +#define R2_REL_OFFSET 16 +#define R3_REL_OFFSET 24 +#define R14_REL_OFFSET 112 +#define R15_REL_OFFSET 120 +#define FRAME_SIZE 160 + +.text + +ASM_HIDDEN(__tsan_setjmp) + +.macro intercept symbol, real +.comm \real, 8, 8 +.globl ASM_SYMBOL_INTERCEPTOR(\symbol) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(\symbol)) +ASM_SYMBOL_INTERCEPTOR(\symbol): + CFI_STARTPROC + stmg %r2, %r3, R2_REL_OFFSET(%r15) + CFI_REL_OFFSET(%r2, R2_REL_OFFSET) + CFI_REL_OFFSET(%r3, R3_REL_OFFSET) + stmg %r14, %r15, R14_REL_OFFSET(%r15) + CFI_REL_OFFSET(%r14, R14_REL_OFFSET) + CFI_REL_OFFSET(%r15, R15_REL_OFFSET) + aghi %r15, -FRAME_SIZE + CFI_ADJUST_CFA_OFFSET(FRAME_SIZE) + la %r2, FRAME_SIZE(%r15) + brasl %r14, ASM_SYMBOL(__tsan_setjmp) + lmg %r14, %r15, FRAME_SIZE + R14_REL_OFFSET(%r15) + CFI_RESTORE(%r14) + CFI_RESTORE(%r15) + CFI_DEF_CFA_OFFSET(CFA_OFFSET) + lmg %r2, %r3, R2_REL_OFFSET(%r15) + CFI_RESTORE(%r2) + CFI_RESTORE(%r3) + larl %r1, \real + lg %r1, 0(%r1) + br %r1 + CFI_ENDPROC + ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(\symbol)) +.endm + +intercept setjmp, _ZN14__interception11real_setjmpE +intercept _setjmp, _ZN14__interception12real__setjmpE +intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE +intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE diff --git a/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c b/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c index 15eb8edf07a9d..cbbbe27f5d9f8 100644 --- a/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c +++ b/compiler-rt/test/asan/TestCases/Darwin/dead-strip.c @@ -8,7 +8,7 @@ // REQUIRES: osx-ld64-live_support // RUN: %clang_asan %min_macos_deployment_target=10.11 -Xlinker -dead_strip -o %t %s -// RUN: llvm-nm -format=posix %t | FileCheck --check-prefix NM-CHECK %s +// RUN: llvm-nm --format=posix %t | FileCheck --check-prefix NM-CHECK %s // RUN: not %run %t 2>&1 | FileCheck --check-prefix ASAN-CHECK %s int alive[1] = {}; diff --git a/compiler-rt/test/asan/TestCases/Darwin/linked-only.cpp b/compiler-rt/test/asan/TestCases/Darwin/linked-only.cpp index bb19ea8535e27..d404af6ff05fb 100644 --- a/compiler-rt/test/asan/TestCases/Darwin/linked-only.cpp +++ b/compiler-rt/test/asan/TestCases/Darwin/linked-only.cpp @@ -10,6 +10,9 @@ #include #include "sanitizer/asan_interface.h" +#if __has_feature(ptrauth_calls) +# include +#endif void test_shadow(char *p, size_t size) { fprintf(stderr, "p = %p\n", p); @@ -23,7 +26,13 @@ int main(int argc, char *argv[]) { free(p); // CHECK: =-1= - test_shadow((char *)&main, 1); + char *mainptr; +#if __has_feature(ptrauth_calls) + mainptr = (char *)ptrauth_strip((void *)&main, ptrauth_key_return_address); +#else + mainptr = (char *)&main; +#endif + test_shadow(mainptr, 1); // CHECK: =-1= test_shadow((char *)&p, 1); diff --git a/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp b/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp index 81cd2d389c3b4..33981bd048582 100644 --- a/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp @@ -1,6 +1,6 @@ // Build an executable with ASan, then extract the DLLs that it depends on. // RUN: %clang_cl_asan %s -Fe%t.exe -// RUN: llvm-readobj -coff-imports %t.exe | grep Name: | sed -e 's/ *Name: *//' > %t +// RUN: llvm-readobj --coff-imports %t.exe | grep Name: | sed -e 's/ *Name: *//' > %t // // Make sure the binary doesn't depend on dbghelp directly. // RUN: not grep dbghelp.dll %t @@ -9,7 +9,7 @@ // static build, there won't be any clang_rt DLLs. // RUN: not grep cl""ang_rt %t || \ // RUN: grep cl""ang_rt %t | xargs which | \ -// RUN: xargs llvm-readobj -coff-imports | not grep dbghelp.dll %t +// RUN: xargs llvm-readobj --coff-imports | not grep dbghelp.dll %t extern "C" int puts(const char *); diff --git a/compiler-rt/test/asan/TestCases/frexpf_interceptor.cpp b/compiler-rt/test/asan/TestCases/frexpf_interceptor.cpp new file mode 100644 index 0000000000000..91da09a6880cf --- /dev/null +++ b/compiler-rt/test/asan/TestCases/frexpf_interceptor.cpp @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// Test the frexpf() interceptor. + +#include +#include +#include +int main() { + float x = 3.14; + int *exp = (int *)malloc(sizeof(int)); + free(exp); + double y = frexpf(x, exp); + // CHECK: use-after-free + // CHECK: SUMMARY + return 0; +} diff --git a/compiler-rt/test/asan/TestCases/frexpl_interceptor.cpp b/compiler-rt/test/asan/TestCases/frexpl_interceptor.cpp new file mode 100644 index 0000000000000..46bb6a282bea1 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/frexpl_interceptor.cpp @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// Test the frexpl() interceptor. + +#include +#include +#include +int main() { + long double x = 3.14; + int *exp = (int *)malloc(sizeof(int)); + free(exp); + double y = frexpl(x, exp); + // CHECK: use-after-free + // CHECK: SUMMARY + return 0; +} diff --git a/compiler-rt/test/gwp_asan/backtrace.c b/compiler-rt/test/gwp_asan/backtrace.c index 9d9fc7db096be..f4be7305bfb7e 100644 --- a/compiler-rt/test/gwp_asan/backtrace.c +++ b/compiler-rt/test/gwp_asan/backtrace.c @@ -7,6 +7,9 @@ // RUN: %clang_gwp_asan -fomit-frame-pointer -momit-leaf-frame-pointer %s -g -o %t // RUN: %expect_crash %t +// Incomplete backtrace on Armv7 +// UNSUPPORTED: armhf-linux + #include __attribute__((noinline)) void *allocate_mem() { return malloc(1); } diff --git a/compiler-rt/test/hwasan/TestCases/longjmp.c b/compiler-rt/test/hwasan/TestCases/longjmp.c index 86fff7a0a23a4..700a1cbee329c 100644 --- a/compiler-rt/test/hwasan/TestCases/longjmp.c +++ b/compiler-rt/test/hwasan/TestCases/longjmp.c @@ -3,34 +3,24 @@ // REQUIRES: stable-runtime, pointer-tagging -#include #include #include #include -#include - -static int *volatile p; __attribute__((noinline)) -int f(jmp_buf buf) { +int f(void *caller_frame) { int z = 0; - p = &z; + int *volatile p = &z; // Tag of local is never zero. assert(__hwasan_tag_pointer(p, 0) != p); #ifndef NEGATIVE - // This will destroy shadow of "z", the p[0] in main will crash. - longjmp(buf, 1); + // This will destroy shadow of "z", and the following load will crash. + __hwasan_handle_longjmp(caller_frame); #endif return p[0]; } int main() { - jmp_buf buf; - if (setjmp(buf)) { - return p[0]; - } else { - f(buf); - } - return 0; - // CHECK: READ of size 4 at {{.*}} tags: {{.*}}/00 (ptr/mem) + return f(__builtin_frame_address(0)); + // CHECK: READ of size 8 at {{.*}} tags: {{.*}}/00 (ptr/mem) } diff --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/placeholder_test.S b/compiler-rt/test/orc/TestCases/Darwin/x86-64/placeholder_test.S deleted file mode 100644 index a794e10152e16..0000000000000 --- a/compiler-rt/test/orc/TestCases/Darwin/x86-64/placeholder_test.S +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %clang -c -o %t %s -// RUN: %llvm_jitlink %t - - .section __TEXT,__text,regular,pure_instructions - .build_version macos, 11, 0 sdk_version 11, 3 - - .globl _main - .p2align 4, 0x90 -_main: - xorl %eax, %eax - retq - -.subsections_via_symbols diff --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-cxa-atexit.S b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-cxa-atexit.S new file mode 100644 index 0000000000000..f04af5e3f2a5f --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-cxa-atexit.S @@ -0,0 +1,38 @@ +// Test that the runtime correctly interposes ___cxa_atexit. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .section __TEXT,__text,regular,pure_instructions + .build_version macos, 11, 0 sdk_version 11, 3 + +// OnExit destructor resets the test result override to zero. + .globl __ZN6OnExitD1Ev + .weak_def_can_be_hidden __ZN6OnExitD1Ev + .p2align 4, 0x90 +__ZN6OnExitD1Ev: + xorl %edi, %edi + jmp _llvm_jitlink_setTestResultOverride + +// main registers the atexit and sets the test result to one. + .globl _main + .p2align 4, 0x90 +_main: + pushq %rbp + movq %rsp, %rbp + + movq __ZN6OnExitD1Ev@GOTPCREL(%rip), %rdi + leaq _onExit(%rip), %rsi + leaq ___dso_handle(%rip), %rdx + callq ___cxa_atexit + + movl $1, %edi + callq _llvm_jitlink_setTestResultOverride + xorl %eax, %eax + popq %rbp + retq + + .globl _onExit +.zerofill __DATA,__common,_onExit,1,0 + +.subsections_via_symbols diff --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-static-initializer.S b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-static-initializer.S new file mode 100644 index 0000000000000..a90c67c544a08 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/trivial-static-initializer.S @@ -0,0 +1,37 @@ +// Test that basic MachO static initializers work. The main function in this +// test returns the value of 'x', which is initially 1 in the data section, +// and reset to 0 if the _static_init function is run. If the static initializer +// does not run then main will return 1, causing the test to be treated as a +// failure. +// +// RUN: %clang -c -o %t %s +// RUN: %llvm_jitlink %t + + .section __TEXT,__text,regular,pure_instructions + .build_version macos, 11, 0 + +# main returns the value of 'x', which is defined as 1 in the data section.. + .globl _main + .p2align 4, 0x90 +_main: + movl _x(%rip), %eax + retq + +# static initializer sets the value of 'x' to zero. + .section __TEXT,__StaticInit,regular,pure_instructions + .p2align 4, 0x90 +_static_init: + movl $0, _x(%rip) + retq + + .section __DATA,__data + .globl _x + .p2align 2 +_x: + .long 1 + + .section __DATA,__mod_init_func,mod_init_funcs + .p2align 3 + .quad _static_init + +.subsections_via_symbols diff --git a/compiler-rt/test/sanitizer_common/android_commands/android_common.py b/compiler-rt/test/sanitizer_common/android_commands/android_common.py index eb15c34ed52f0..81caae8741c2d 100644 --- a/compiler-rt/test/sanitizer_common/android_commands/android_common.py +++ b/compiler-rt/test/sanitizer_common/android_commands/android_common.py @@ -15,7 +15,7 @@ def host_to_device_path(path): def adb(args, attempts = 1, timeout_sec = 600): if verbose: - print args + print(args) tmpname = tempfile.mktemp() out = open(tmpname, 'w') ret = 255 @@ -23,11 +23,11 @@ def adb(args, attempts = 1, timeout_sec = 600): attempts -= 1 ret = subprocess.call(['timeout', str(timeout_sec), ADB] + args, stdout=out, stderr=subprocess.STDOUT) if ret != 0: - print "adb command failed", args - print tmpname + print("adb command failed", args) + print(tmpname) out.close() out = open(tmpname, 'r') - print out.read() + print(out.read()) out.close() os.unlink(tmpname) return ret diff --git a/compiler-rt/test/sanitizer_common/android_commands/android_compile.py b/compiler-rt/test/sanitizer_common/android_commands/android_compile.py index a57bc311bd522..8f657d32be562 100755 --- a/compiler-rt/test/sanitizer_common/android_commands/android_compile.py +++ b/compiler-rt/test/sanitizer_common/android_commands/android_compile.py @@ -21,7 +21,7 @@ output = args.pop(0) if output == None: - print "No output file name!" + print("No output file name!") sys.exit(1) ret = subprocess.call(sys.argv[1:]) diff --git a/compiler-rt/test/sanitizer_common/android_commands/android_run.py b/compiler-rt/test/sanitizer_common/android_commands/android_run.py index 8f2e40152de7c..6f454ab3a4d38 100755 --- a/compiler-rt/test/sanitizer_common/android_commands/android_run.py +++ b/compiler-rt/test/sanitizer_common/android_commands/android_run.py @@ -11,12 +11,12 @@ def build_env(): args = [] # Android linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir. args.append('LD_LIBRARY_PATH=%s' % (ANDROID_TMPDIR,)) - for (key, value) in os.environ.items(): + for (key, value) in list(os.environ.items()): if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or key.endswith('SAN_OPTIONS'): args.append('%s="%s"' % (key, value.replace('"', '\\"'))) return ' '.join(args) -is_64bit = (subprocess.check_output(['file', sys.argv[0] + '.real']).find('64-bit') != -1) +is_64bit = str(subprocess.check_output(['file', sys.argv[0] + '.real'])).find('64-bit') != -1 device_env = build_env() device_args = ' '.join(sys.argv[1:]) # FIXME: escape? diff --git a/compiler-rt/test/sanitizer_common/ios_commands/iossim_run.py b/compiler-rt/test/sanitizer_common/ios_commands/iossim_run.py index 6af8de53a0db0..16b3434a741b4 100755 --- a/compiler-rt/test/sanitizer_common/ios_commands/iossim_run.py +++ b/compiler-rt/test/sanitizer_common/ios_commands/iossim_run.py @@ -7,7 +7,14 @@ if not device_id: raise EnvironmentError("Specify SANITIZER_IOSSIM_TEST_DEVICE_IDENTIFIER to select which simulator to use.") -for e in ["ASAN_OPTIONS", "TSAN_OPTIONS", "UBSAN_OPTIONS", "APPLE_ASAN_INIT_FOR_DLOPEN", "ASAN_ACTIVATION_OPTIONS"]: +for e in [ + "ASAN_OPTIONS", + "TSAN_OPTIONS", + "UBSAN_OPTIONS", + "APPLE_ASAN_INIT_FOR_DLOPEN", + "ASAN_ACTIVATION_OPTIONS", + "MallocNanoZone", +]: if e in os.environ: os.environ["SIMCTL_CHILD_" + e] = os.environ[e] diff --git a/compiler-rt/test/tsan/CMakeLists.txt b/compiler-rt/test/tsan/CMakeLists.txt index c8f8eba50dfc7..318a91f73ef7e 100644 --- a/compiler-rt/test/tsan/CMakeLists.txt +++ b/compiler-rt/test/tsan/CMakeLists.txt @@ -1,7 +1,7 @@ set(TSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "x86_64") +if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "(x86_64|s390x)") list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck) endif() if(NOT COMPILER_RT_STANDALONE_BUILD) diff --git a/compiler-rt/test/tsan/ignore_lib0.cpp b/compiler-rt/test/tsan/ignore_lib0.cpp index 1d375336b1c02..d6d6acdbc370c 100644 --- a/compiler-rt/test/tsan/ignore_lib0.cpp +++ b/compiler-rt/test/tsan/ignore_lib0.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t-dir // RUN: mkdir %t-dir -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so +// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so // RUN: %clangxx_tsan -O1 %s -L%t-dir -lignore_lib0 %link_libcxx_tsan -o %t // RUN: echo running w/o suppressions: // RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP diff --git a/compiler-rt/test/tsan/ignore_lib1.cpp b/compiler-rt/test/tsan/ignore_lib1.cpp index 2a708eaab4015..01139519e491b 100644 --- a/compiler-rt/test/tsan/ignore_lib1.cpp +++ b/compiler-rt/test/tsan/ignore_lib1.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t-dir // RUN: mkdir %t-dir -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so +// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable // RUN: echo running w/o suppressions: // RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP diff --git a/compiler-rt/test/tsan/ignore_lib5.cpp b/compiler-rt/test/tsan/ignore_lib5.cpp index 81a1840c95517..a71d560ab913c 100644 --- a/compiler-rt/test/tsan/ignore_lib5.cpp +++ b/compiler-rt/test/tsan/ignore_lib5.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t-dir // RUN: mkdir %t-dir -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so +// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable // RUN: echo running w/o suppressions: // RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP diff --git a/compiler-rt/test/tsan/map32bit.cpp b/compiler-rt/test/tsan/map32bit.cpp index 8aef27bc1900d..0f8236292be7a 100644 --- a/compiler-rt/test/tsan/map32bit.cpp +++ b/compiler-rt/test/tsan/map32bit.cpp @@ -11,6 +11,7 @@ // XFAIL: mips // XFAIL: aarch64 // XFAIL: powerpc64 +// XFAIL: s390x // MAP_32BIT doesn't exist on OS X and NetBSD. // UNSUPPORTED: darwin,netbsd diff --git a/compiler-rt/test/tsan/mmap_large.cpp b/compiler-rt/test/tsan/mmap_large.cpp index c8d258e804d7f..1d4c73252832a 100644 --- a/compiler-rt/test/tsan/mmap_large.cpp +++ b/compiler-rt/test/tsan/mmap_large.cpp @@ -21,6 +21,8 @@ int main() { const size_t kLog2Size = 32; #elif defined(__powerpc64__) const size_t kLog2Size = 39; +#elif defined(__s390x__) + const size_t kLog2Size = 43; #endif const uintptr_t kLocation = 0x40ULL << kLog2Size; void *p = mmap( diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index bc6d4a3766636..e8e5ca991f14f 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -931,7 +931,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPAtomicConstruct &) { // 3. Checks on clauses which are not in 'struct OmpClause' from parse-tree.h. void OmpStructureChecker::Leave(const parser::OmpClauseList &) { - // 2.7 Loop Construct Restriction + // 2.7.1 Loop Construct Restriction if (llvm::omp::doSet.test(GetContext().directive)) { if (auto *clause{FindClause(llvm::omp::Clause::OMPC_schedule)}) { // only one schedule clause is allowed diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt index 905d491708eb4..738e00cdd1e28 100644 --- a/flang/test/CMakeLists.txt +++ b/flang/test/CMakeLists.txt @@ -32,11 +32,9 @@ set(FLANG_TEST_PARAMS flang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py) set(FLANG_TEST_DEPENDS - f18 FileCheck count not module_files fir-opt + f18 FileCheck count not module_files fir-opt tco ) -list(APPEND FLANG_TEST_DEPENDS tco) - if (FLANG_BUILD_NEW_DRIVER) list(APPEND FLANG_TEST_DEPENDS flang-new) endif() diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 index fe0bcf8f4e854..79d3c1d6c2f9a 100644 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -7,8 +7,6 @@ ! 2.7.1 Loop construct ! ... -! TODO: all the internal errors - integer :: b = 128 integer :: z, c = 32 integer, parameter :: num = 16 @@ -87,7 +85,7 @@ do i = 1, N z = 2 enddo - !$omp end target data + !$omp end target data !ERROR: SCHEDULE clause is not allowed on the PARALLEL directive !$omp parallel schedule(static) @@ -177,7 +175,7 @@ exit outofparallel end do inner end do outer - !$end omp do + !$omp end do !$omp end parallel end do outofparallel diff --git a/flang/test/Semantics/omp-taskloop-simd01.f90 b/flang/test/Semantics/omp-taskloop-simd01.f90 index d7b2960d58823..7cfa384ab2d49 100644 --- a/flang/test/Semantics/omp-taskloop-simd01.f90 +++ b/flang/test/Semantics/omp-taskloop-simd01.f90 @@ -1,18 +1,15 @@ ! RUN: %S/test_errors.sh %s %t %flang -fopenmp -! XFAIL: * +! REQUIRES: shell -! OpenMP Version 4.5 -! 2.9.3 taskloop simd Construct -! No reduction clause may be specified for !$omp taskloop simd. +! OpenMP Version 5.0 +! 2.10.3 taskloop simd Construct program omp_taskloop_simd integer i , j , k - !ERROR: Unexpected clause specified for !$OMP taskloop simd !$omp taskloop simd reduction(+:k) do i=1,10000 do j=1,i - call loop_body(i, j) k = k + 1 end do end do diff --git a/flang/tools/f18/flang.in b/flang/tools/f18/flang.in index 603f43c1ac228..eb953c58d91a9 100755 --- a/flang/tools/f18/flang.in +++ b/flang/tools/f18/flang.in @@ -264,11 +264,12 @@ preprocess() { } # === get_relocatable_name ====================================================== -# -# Generate a name for the output object file based on the source file, e.g. +# This method generates the name of the output file for the compilation phase +# (triggered with `-c`). If the user of this script is only interested in +# compilation (`flang -c`), use $OUTPUT_FILE provided that it was defined. +# Otherwise, use the usual heuristics: # * file.f --> file.o # * file.c --> file.o -# If OUTPUT_FILE is defined, use that instead. # # INPUTS: # $1 - input source file for which to generate the output name @@ -276,7 +277,7 @@ preprocess() { get_relocatable_name() { local -r src_file=$1 - if [[ ! -z ${OUTPUT_FILE:+x} ]]; then + if [[ $COMPILE_ONLY == "True" ]] && [[ ! -z ${OUTPUT_FILE:+x} ]]; then out_file="$OUTPUT_FILE" else current_ext=${src_file##*.} @@ -324,7 +325,13 @@ main() { local -r wd=$(cd "$(dirname "$0")/.." && pwd) # STEP 1: Unparse - local -r unparsed_file="flang_unparsed_source_file" + # Base-name for the unparsed files. These are just temporary files that are + # first generated and then deleted by this script. + # NOTE: We need to make sure that the base-name is unique to every + # invocation. Otherwise we can't use this script in parallel. + local -r unique_id=$(uuidgen | cut -b25-36) + local -r unparsed_file_base="flang_unparsed_file_$unique_id" + flang_options+=("-module-suffix") flang_options+=(".f18.mod") flang_options+=("-fdebug-unparse") @@ -333,10 +340,13 @@ main() { [[ ! -z ${MODULE_DIR} ]] && flang_options+=("-module-dir ${MODULE_DIR}") [[ ! -z ${INTRINSICS_MOD_DIR} ]] && flang_options+=("-intrinsics-module-directory ${INTRINSICS_MOD_DIR}") for idx in "${!fortran_source_files[@]}"; do - if ! "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${flang_options[@]}" "${fortran_source_files[$idx]}" -o "${unparsed_file}_${idx}.f90" - then status=$? - echo flang: in "$PWD", @FLANG_DEFAULT_DRIVER@ failed with exit status $status: "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${flang_options[@]}" "$@" >&2 - exit $status + set +e + "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${flang_options[@]}" "${fortran_source_files[$idx]}" -o "${unparsed_file_base}_${idx}.f90" + ret_status=$? + set -e + if [[ $ret_status != 0 ]]; then + echo flang: in "$PWD", @FLANG_DEFAULT_DRIVER@ failed with exit status "$ret_status": "$wd/bin/@FLANG_DEFAULT_DRIVER@" "${flang_options[@]}" "$@" >&2 + exit "$ret_status" fi done @@ -348,17 +358,20 @@ main() { # below. As a result, we cannot rely on the compiler-generated output name. out_obj_file=$(get_relocatable_name "${fortran_source_files[$idx]}") - if ! $ext_fc "-c" "${ext_fc_options[@]}" "${unparsed_file}_${idx}.f90" "-o" "${out_obj_file}" - then status=$? - echo flang: in "$PWD", "$ext_fc" failed with exit status $status: "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit $status + set +e + $ext_fc "-c" "${ext_fc_options[@]}" "${unparsed_file_base}_${idx}.f90" "-o" "${out_obj_file}" + ret_status=$? + set -e + if [[ $ret_status != 0 ]]; then + echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 + exit "$ret_status" fi object_files+=(${out_obj_file}) done # Delete the unparsed files for idx in "${!fortran_source_files[@]}"; do - rm "${unparsed_file}_${idx}.f90" + rm "${unparsed_file_base}_${idx}.f90" done # STEP 3: Compile Other Source Files @@ -368,10 +381,13 @@ main() { # $ext_fc_options). Hence we need to use `get_relocatable_name`. out_obj_file=$(get_relocatable_name "${other_source_files[$idx]}") - if ! $ext_fc "-c" "${ext_fc_options[@]}" "${other_source_files[${idx}]}" "-o" "${out_obj_file}" - then status=$? - echo flang: in "$PWD", "$ext_fc" failed with exit status $status: "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit $status + set +e + $ext_fc "-c" "${ext_fc_options[@]}" "${other_source_files[${idx}]}" "-o" "${out_obj_file}" + ret_status=$? + set -e + if [[ $ret_status != 0 ]]; then + echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 + exit "$ret_status" fi object_files+=(${out_obj_file}) done @@ -389,10 +405,13 @@ main() { output_definition="" fi - if ! $ext_fc "${ext_fc_options[@]}" "${object_files[@]}" "${lib_files[@]}" ${output_definition:+$output_definition} - then status=$? - echo flang: in "$PWD", "$ext_fc" failed with exit status $status: "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 - exit $status + set +e + $ext_fc "${ext_fc_options[@]}" "${object_files[@]}" "${lib_files[@]}" ${output_definition:+$output_definition} + ret_status=$? + set -e + if [[ $ret_status != 0 ]]; then + echo flang: in "$PWD", "$ext_fc" failed with exit status "$ret_status": "$ext_fc" "${ext_fc_options[@]}" "$@" >&2 + exit "$ret_status" fi fi diff --git a/flang/unittests/RuntimeGTest/Transformational.cpp b/flang/unittests/RuntimeGTest/Transformational.cpp index 00495fc04a94d..90c1fa36d9941 100644 --- a/flang/unittests/RuntimeGTest/Transformational.cpp +++ b/flang/unittests/RuntimeGTest/Transformational.cpp @@ -150,6 +150,18 @@ TEST(Transformational, Spread) { EXPECT_EQ(*result.ZeroBasedIndexedElement(j), 1 + j % 3); } result.Destroy(); + + auto scalar{MakeArray( + std::vector{}, std::vector{1})}; + RTNAME(Spread)(result, *scalar, 1, 2, __FILE__, __LINE__); + EXPECT_EQ(result.type(), array->type()); + EXPECT_EQ(result.rank(), 1); + EXPECT_EQ(result.GetDimension(0).LowerBound(), 1); + EXPECT_EQ(result.GetDimension(0).Extent(), 2); + for (int j{0}; j < 2; ++j) { + EXPECT_EQ(*result.ZeroBasedIndexedElement(j), 1); + } + result.Destroy(); } TEST(Transformational, Transpose) { diff --git a/libc/benchmarks/MemorySizeDistributions.cpp b/libc/benchmarks/MemorySizeDistributions.cpp index d8780c915a5b0..e46590dfe0143 100644 --- a/libc/benchmarks/MemorySizeDistributions.cpp +++ b/libc/benchmarks/MemorySizeDistributions.cpp @@ -3,65 +3,135 @@ namespace llvm { namespace libc_benchmarks { -// clang-format off -static constexpr double kMemcmpGoogleA[] = {0.311594, 0.0483092, 0.0229469, 0.0748792, 0.0422705, 0.00241546, 0.044686, 0.0326087, 0.0205314, 0.013285, 0.00362319, 0, 0.0108696, 0.00966184, 0.089372, 0.00845411, 0.00724638, 0, 0, 0.00362319, 0, 0.179952, 0.00120773, 0.00483092, 0.00483092, 0.00241546, 0.00120773, 0.0108696, 0.00120773, 0, 0.0144928, 0.00241546, 0.00120773, 0.00120773, 0, 0, 0, 0, 0, 0.00483092, 0, 0.00362319, 0.00241546, 0, 0.00603865, 0, 0, 0.00120773, 0, 0, 0, 0, 0, 0, 0, 0, 0.00120773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00120773, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00362319, 0.00362319}; -static constexpr double kMemcmpGoogleB[] = {0.0685155, 0.00489396, 0.119902, 0.00734095, 0.0252855, 0.0138662, 0.050571, 0.00326264, 0.00570962, 0.0130506, 0.0040783, 0.0212072, 0, 0, 0.000815661, 0.000815661, 0.467374, 0.0212072, 0.00244698, 0.00163132, 0.00734095, 0.00734095, 0.0040783, 0.00570962, 0.00244698, 0.000815661, 0.0195759, 0.00163132, 0, 0, 0.000815661, 0, 0.000815661, 0.0122349, 0.000815661, 0.0040783, 0.00163132, 0.000815661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0464927, 0.045677, 0, 0, 0, 0.000815661, 0, 0, 0, 0, 0.000815661, 0.000815661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000815661, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000815661, 0.00163132}; -static constexpr double kMemcmpGoogleD[] = {0, 0, 0, 0.0045045, 0.202703, 0.0518018, 0.0653153, 0.256757, 0.173423, 0, 0, 0, 0, 0.0698198, 0, 0, 0.00225225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.130631, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00225225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00675676, 0, 0, 0, 0, 0, 0, 0, 0.0337838}; -static constexpr double kMemcmpGoogleL[] = {0, 0.000720461, 0, 0.985591, 0.00129683, 0, 0.00244957, 0.000144092, 0, 0.000576369, 0, 0.00648415, 0.000720461, 0.000288184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00172911}; -static constexpr double kMemcmpGoogleM[] = {0.0275355, 0.0336493, 0.164834, 0.0696209, 0.0714692, 0.105877, 0.108057, 0.114976, 0.021564, 0.0109005, 0.120142, 0.0166351, 0.00398104, 0.00265403, 0.00118483, 0.0301422, 0.00843602, 0.00350711, 0.0036019, 0.00369668, 0.0108531, 0.00758294, 0.00881517, 0.00308057, 0.00232227, 0.00421801, 0.00279621, 0.000379147, 0.000473934, 9.47867e-05, 0.00421801, 0, 0.00028436, 0.0021327, 0.00279621, 0, 0.000473934, 0.000521327, 0.00763033, 0, 0, 0, 0, 4.73934e-05, 4.73934e-05, 0, 0.00919431, 0, 0, 0, 9.47867e-05, 0.00516588, 0.00127962, 4.73934e-05, 0, 0, 0, 9.47867e-05, 0, 0, 0, 0, 0.00028436, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000521327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.73934e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00014218, 0, 0, 0, 0, 0, 0, 0, 0.000853081, 0, 0, 0, 0, 0, 0, 0, 0.00104265}; -static constexpr double kMemcmpGoogleQ[] = {0.0985062, 0.051215, 0.00598885, 0.0212707, 0.034281, 0.0360019, 0.0353824, 0.0235424, 0.0256075, 0.0131479, 0.298823, 0.0168651, 0.00268466, 0.00392373, 0.0203759, 0.00653955, 0.00378605, 0.00172093, 0.0035107, 0.00929304, 0.00592001, 0.00275349, 0.00282233, 0.00839816, 0.00509396, 0.00757211, 0.0016521, 0.00206512, 0.0113582, 0.00178977, 0.00247814, 0.00240931, 0.00385489, 0.00357954, 0.00468094, 0.00158326, 0.00103256, 0.00137675, 0.00117023, 0.00103256, 0.00261582, 0.000550699, 0.00103256, 0.00123907, 0.000826048, 0.0051628, 0.000894885, 0.00275349, 0.000688373, 0.0040614, 0.00123907, 0.00117023, 0.00832932, 0.00151442, 0.00172093, 0.00137675, 0.000963723, 0.000894885, 0.00178977, 0.000550699, 0.000619536, 0.000963723, 0.00130791, 0.000826048, 0.000757211, 0.00123907, 0.00137675, 0.000688373, 0.000413024, 0.00151442, 0.00103256, 0.000688373, 0.000826048, 0.000688373, 0.000963723, 0.000757211, 0.000757211, 0.00103256, 0.000481861, 0.000550699, 0.0222345, 0.000757211, 0.0011014, 0.000619536, 0.000275349, 0.000413024, 0.000688373, 0.000137675, 0.0146624, 0.000688373, 0.000550699, 0.000413024, 0.000275349, 0.000757211, 0.000688373, 0.000550699, 0.00998141, 0.000619536, 0.000619536, 0.000275349, 0.000481861, 0.000619536, 0.000619536, 0.000275349, 0.00688373, 0.000826048, 0.000413024, 0.000206512, 0.000550699, 0.000550699, 0.000550699, 0.000206512, 0.00199628, 0.000137675, 0.000137675, 0.000757211, 0.000206512, 0.000344187, 0.000206512, 0.000344187, 0.00151442, 0.000550699, 0.000550699, 0.000275349, 0.000206512, 6.88373e-05, 0.000344187, 0.000206512, 0.000688373, 0.000688373, 0.000619536, 0.000137675, 0.000413024, 0.000344187, 0.000275349, 0.000550699, 0.000619536, 0.000137675, 0.000344187, 0.000344187, 0.000757211, 0.000137675, 0.000413024, 6.88373e-05, 0.000137675, 6.88373e-05, 0.000550699, 0.000275349, 0.000137675, 0.000413024, 0.000344187, 0.000206512, 0.000550699, 6.88373e-05, 0.000413024, 0.000275349, 0.000137675, 0.000481861, 0.000206512, 0.000206512, 0.000206512, 0.000481861, 0.000137675, 0.000206512, 0.000481861, 0.000344187, 0.000206512, 0.000275349, 0.000275349, 0.000206512, 0.000481861, 0.000413024, 0.000206512, 0.000413024, 0.000137675, 0.000137675, 0.000344187, 0.000137675, 0.000275349, 0.000206512, 0.000481861, 0.000550699, 0, 0.000344187, 0.000275349, 0.000275349, 0.000413024, 0, 0.000344187, 0.000206512, 0.000550699, 0.000206512, 0.000344187, 0.000413024, 0.000688373, 0.000275349, 0.000413024, 0.000275349, 0.000344187, 0.000481861, 0.000550699, 0.000206512, 0.000275349, 0.000137675, 0.000206512, 0.000481861, 0.000344187, 0.000275349, 0.000344187, 0.000413024, 0.000413024, 0.000344187, 0.000206512, 0.000275349, 0.000137675, 0.000481861, 0.000275349, 0.000206512, 0.000413024, 0.000481861, 0.000206512, 0.000137675, 0.000275349, 0.000137675, 0.000206512, 0.000344187, 0.000413024, 0.000413024, 0.000344187, 0.000344187, 0.000275349, 6.88373e-05, 0.000137675, 0.000275349, 6.88373e-05, 0.000344187, 0.000413024, 0.000344187, 0.000206512, 0.000344187, 0.000481861, 0.000481861, 0.000206512, 0.000344187, 0.000137675, 6.88373e-05, 0.000275349, 0.000413024, 0.000137675, 6.88373e-05, 0.000137675, 0.000137675, 0.000206512, 0.000413024, 6.88373e-05, 0.000206512, 0.000137675, 0.000206512, 0.000275349, 0.000344187, 0.000275349, 6.88373e-05, 0.000137675, 0.000344187, 0, 0.000206512, 0, 6.88373e-05, 0.000137675, 0.000550699, 0.000344187, 0.000137675, 0, 0.000344187, 0.000344187, 0.000550699, 0.000344187, 0.000206512, 0.000275349, 6.88373e-05, 0.000275349, 0.000275349, 0.000137675, 6.88373e-05, 6.88373e-05, 0.000206512, 0.000137675, 0.000137675, 0.000137675, 0.000137675, 0.000137675, 0, 0, 6.88373e-05, 0.000137675, 0, 0.000275349, 0.000137675, 6.88373e-05, 0.000206512, 0.000344187, 6.88373e-05, 0.000137675, 6.88373e-05, 0.000275349, 0.000206512, 0, 0.000206512, 0.000275349, 0.000206512, 0.000344187, 0.000137675, 0.000275349, 6.88373e-05, 6.88373e-05, 0.000137675, 6.88373e-05, 0.000206512, 0.000206512, 0.000275349, 0.000344187, 6.88373e-05, 0.000137675, 0.000137675, 0.000275349, 0.000344187, 0.000206512, 0.000344187, 0.000137675, 0.000275349, 0.000137675, 0.000137675, 0.000206512, 0.000137675, 0.000137675, 0.000137675, 6.88373e-05, 0.000206512, 6.88373e-05, 0, 6.88373e-05, 0.000344187, 6.88373e-05, 0.000137675, 0.000137675, 0.000481861, 0.000206512, 0, 0.000206512, 0, 0.000206512, 0, 6.88373e-05, 6.88373e-05, 6.88373e-05, 0.000206512, 0.000206512, 0, 6.88373e-05, 0, 0.000206512, 0.000206512, 0.000137675, 0.000275349, 0.000137675, 6.88373e-05, 0.000275349, 0.000137675, 0.000344187, 0, 0.000275349, 0, 0.000206512, 6.88373e-05, 0.000344187, 6.88373e-05, 0.000206512, 0.000137675, 0.000206512, 6.88373e-05, 0.000413024, 6.88373e-05, 0.000275349, 6.88373e-05, 0.000137675, 0, 0.000413024, 0, 0.000344187, 0, 0.000206512, 0, 0.000481861, 0, 0.000413024, 0, 0.000206512, 0, 0.000344187, 0, 0.000413024, 0, 0.000206512, 0, 0.000481861, 0, 0.000137675, 0, 0.000206512, 0, 0.000344187, 0, 6.88373e-05, 0, 0.000137675, 0, 0.000275349, 0, 0.000206512, 0, 0.000206512, 0, 0.000137675, 0, 0.000688373, 0, 0.000206512, 0, 0.000137675, 0, 0, 0, 0.000275349, 0, 0.000481861, 0, 0.000206512, 0, 0.000206512, 0, 0.000344187, 0, 0.000137675, 0, 0.000206512, 0, 0.000344187, 0, 0.000275349, 0, 6.88373e-05, 0, 0.000137675, 0, 6.88373e-05, 0, 0.000137675, 0, 0.000137675, 0, 0.000275349, 0, 0.000275349, 0, 6.88373e-05, 0, 6.88373e-05, 0, 6.88373e-05, 0, 0.000275349, 0, 0, 0, 0.000206512, 0, 0.000206512, 0, 0.000413024, 0, 6.88373e-05, 0, 0.000206512, 0, 0.000206512, 0, 0.000344187, 0, 0.000137675, 0, 0.000413024, 0, 0.000344187, 0, 0, 0, 0.000413024, 0, 6.88373e-05, 0, 0.000206512, 0, 0, 0, 0.000206512, 0, 0.000275349, 0, 0, 0, 0.000137675, 0, 0.000550699, 0, 6.88373e-05, 0, 0, 0, 0.000137675, 0, 0.000344187, 0, 0.000344187, 0, 0.000206512, 0, 6.88373e-05, 0, 0.000275349, 0, 0.000275349, 0, 0.000137675, 0, 6.88373e-05, 0, 0.000206512, 0, 0.000206512, 0, 0.000137675, 0, 0.000137675, 0, 0.000137675, 0, 6.88373e-05, 0, 0.000137675, 0, 6.88373e-05, 0, 0.000206512, 0, 6.88373e-05, 0, 6.88373e-05, 0, 6.88373e-05, 0, 0.000137675, 0, 0.000206512, 0, 0.000206512, 0, 0.000137675, 0, 6.88373e-05, 0, 0.000206512, 0, 0, 0, 6.88373e-05, 0, 6.88373e-05, 0, 0.000206512, 0, 0.000137675, 0, 0.000137675, 0, 0.000206512, 0, 6.88373e-05, 0, 6.88373e-05, 0, 0.000206512, 0, 6.88373e-05, 0, 0.000137675, 0, 6.88373e-05, 0, 0.000137675}; -static constexpr double kMemcmpGoogleS[] = {0, 0.0729167, 0.0208333, 0.0104167, 0.0416667, 0.0729167, 0.0416667, 0.0104167, 0, 0, 0, 0.28125, 0, 0, 0, 0, 0, 0, 0.125, 0.0833333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0416667, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0208333, 0, 0.0104167, 0.0208333, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0.0208333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0104167, 0.0104167}; -static constexpr double kMemcmpGoogleU[] = {0, 0.00524132, 0.0133826, 0.019914, 0.0121586, 0.00926881, 0.0164502, 0.0122805, 0.73091, 0.0108229, 0.00958877, 0.0123364, 0.0109753, 0.00854762, 0.0129509, 0.00817179, 0.0236215, 0.00756233, 0.0161049, 0.00399701, 0.00553081, 0.00266129, 0.00224483, 0.00223975, 0.0125446, 0.00158458, 0.00191979, 0.0011021, 0.000695795, 0.000827844, 0.00165569, 0.000726268, 0.00146777, 0.000543431, 0.00101068, 0.000467249, 0.000391067, 0.00127986, 0.000639928, 0.000233625, 0.000218388, 0.0105334, 0.000162522, 0.000909105, 0.000142206, 0.000157443, 0.00172171, 0.000289491, 0.000147285, 5.58668e-05, 4.57092e-05, 5.58668e-05, 3.55516e-05, 6.09456e-05, 1.52364e-05, 0.000909105, 1.01576e-05, 5.58668e-05, 4.06304e-05, 2.5394e-05, 1.52364e-05, 1.01576e-05, 1.01576e-05, 3.04728e-05, 2.03152e-05, 1.52364e-05, 1.52364e-05, 1.01576e-05, 2.5394e-05, 5.0788e-06, 1.01576e-05, 0, 5.0788e-06, 5.0788e-06, 1.01576e-05, 0, 1.01576e-05, 1.01576e-05, 0, 5.0788e-06, 1.01576e-05, 0, 1.01576e-05, 5.0788e-06, 0, 1.01576e-05, 0, 2.03152e-05, 0, 0, 5.0788e-06, 5.0788e-06, 5.0788e-06, 5.0788e-06, 0, 0, 0, 0, 5.0788e-06, 0, 0, 0, 0, 1.01576e-05, 0, 5.0788e-06, 5.0788e-06, 0, 0, 0, 0, 0, 5.0788e-06, 0, 5.0788e-06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.0788e-06, 5.0788e-06, 0, 0, 0, 0, 0, 5.0788e-06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.0788e-06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.0788e-06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.0788e-06}; -static constexpr double kMemcmpGoogleW[] = {0.0191339, 0.0151057, 0.0926485, 0.0281974, 0.0271903, 0.0483384, 0.0654582, 0.0261833, 0.0443102, 0.0553877, 0.0433031, 0.0120846, 0.0120846, 0.0422961, 0.0161128, 0.020141, 0.0261833, 0.020141, 0.0100705, 0.0332326, 0.0231621, 0.0292044, 0.0372608, 0.0161128, 0.0161128, 0.0100705, 0.0110775, 0.00704935, 0.0120846, 0.00704935, 0.00503525, 0.00906344, 0.0040282, 0.00805639, 0.00704935, 0.0060423, 0.0060423, 0.00503525, 0.0040282, 0.0191339, 0.0040282, 0.0140987, 0.0020141, 0.00100705, 0.0020141, 0, 0.0020141, 0.00100705, 0.0020141, 0, 0, 0, 0.0020141, 0, 0.0020141, 0, 0, 0, 0.00100705, 0, 0, 0, 0.00100705, 0.00100705, 0, 0, 0, 0, 0, 0.00100705, 0, 0.0020141, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0.00503525, 0.00100705, 0, 0, 0, 0, 0.0020141, 0.0020141, 0.00302115, 0.0020141, 0, 0.0020141, 0, 0, 0, 0.00100705, 0.0020141, 0, 0, 0.00100705, 0.00100705, 0, 0.00100705, 0, 0.00100705, 0, 0, 0, 0.00100705, 0, 0, 0, 0.00100705, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00302115, 0, 0, 0, 0.0020141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0040282, 0, 0, 0, 0, 0, 0, 0, 0.00302115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0.00302115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0020141, 0, 0, 0, 0, 0, 0, 0, 0.0020141, 0, 0, 0, 0, 0, 0, 0, 0.0020141, 0, 0, 0, 0, 0, 0, 0, 0.0020141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00100705}; -static constexpr double kMemcpyGoogleA[] = {0, 0, 0.020339, 0.0915254, 0.0644068, 0.0135593, 0.0271186, 0.00338983, 0.332203, 0, 0, 0.0271186, 0.00338983, 0, 0, 0, 0.166102, 0, 0.00338983, 0.00677966, 0.0135593, 0, 0, 0, 0, 0, 0, 0, 0.00338983, 0, 0, 0, 0.0610169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0271186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0440678, 0, 0, 0, 0, 0, 0, 0, 0.00677966, 0, 0, 0, 0, 0, 0, 0, 0.00338983, 0, 0, 0, 0.00677966, 0, 0, 0, 0.0169492, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0135593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00338983, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00677966, 0, 0, 0, 0.0101695, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0135593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00338983, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00338983, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00338983}; -static constexpr double kMemcpyGoogleB[] = {0.0755418, 0.0204334, 0.00464396, 0.0473684, 0.0260062, 0.00371517, 0.0145511, 0.00433437, 0.0377709, 0.113313, 0.0501548, 0.0108359, 0.00154799, 0.000619195, 0.000928793, 0.00154799, 0.237152, 0.00897833, 0.0733746, 0.00402477, 0.00216718, 0.00278638, 0.0216718, 0.00154799, 0.000619195, 0.000619195, 0.00309598, 0.00123839, 0.0198142, 0.00216718, 0.000928793, 0.00216718, 0.0291022, 0.00278638, 0.000619195, 0.00247678, 0.000619195, 0.00247678, 0.000928793, 0.0111455, 0.00588235, 0.000309598, 0.000619195, 0.000619195, 0, 0.0216718, 0.00123839, 0.00340557, 0.00123839, 0.000619195, 0.000928793, 0.0201238, 0.0260062, 0.000619195, 0, 0.00309598, 0.00897833, 0.00866873, 0.000928793, 0.000928793, 0, 0.00154799, 0, 0.000309598, 0.00247678, 0.0170279, 0.000309598, 0, 0.000309598, 0, 0.000309598, 0.000619195, 0.000309598, 0.000309598, 0.000309598, 0, 0.000309598, 0, 0.000309598, 0, 0.000309598, 0, 0, 0.000619195, 0, 0, 0.000619195, 0.000928793, 0.000309598, 0.000309598, 0, 0, 0, 0, 0.000309598, 0, 0.000928793, 0, 0.000309598, 0, 0.000309598, 0.000309598, 0.000309598, 0, 0, 0, 0.000309598, 0, 0, 0, 0.000928793, 0.000309598, 0, 0, 0.000309598, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0.000309598, 0, 0.000309598, 0, 0.000309598, 0, 0, 0.000309598, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0.000309598, 0, 0, 0.000309598, 0, 0, 0.000309598, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0.000619195, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0.000309598, 0, 0, 0.00216718, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000619195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000309598}; -static constexpr double kMemcpyGoogleD[] = {0.0234987, 0.0137076, 0.0104439, 0.0117493, 0.022846, 0.017624, 0.0672324, 0.0372063, 0.0391645, 0.0372063, 0.0248042, 0.0456919, 0.0267624, 0.0359008, 0.0156658, 0.00522193, 0.0306789, 0.0124021, 0.0104439, 0.0137076, 0.00261097, 0.0150131, 0.0365535, 0.00391645, 0.00652742, 0.0443864, 0.0163185, 0.0430809, 0.00587467, 0.0169713, 0.0110966, 0.00130548, 0.0293734, 0, 0.000652742, 0.00195822, 0.0248042, 0.00391645, 0.00979112, 0.000652742, 0.0365535, 0.000652742, 0.00130548, 0.000652742, 0.000652742, 0.000652742, 0.00913838, 0, 0.000652742, 0, 0, 0.000652742, 0, 0, 0.00130548, 0, 0.0163185, 0.000652742, 0.000652742, 0.000652742, 0, 0, 0.000652742, 0, 0.00913838, 0.000652742, 0, 0, 0.000652742, 0, 0, 0, 0.00130548, 0, 0.000652742, 0, 0, 0.00130548, 0, 0, 0, 0, 0, 0, 0, 0.00261097, 0, 0.00913838, 0.0300261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00195822, 0, 0, 0.00130548, 0.000652742, 0.00456919, 0, 0, 0, 0, 0, 0, 0.00130548, 0.0130548, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00261097, 0, 0, 0, 0, 0.000652742, 0, 0, 0.00326371, 0, 0.00130548, 0, 0, 0, 0.000652742, 0, 0.00130548, 0, 0, 0, 0, 0, 0, 0, 0.00130548, 0, 0, 0, 0, 0, 0.000652742, 0, 0.00195822, 0, 0.000652742, 0, 0, 0, 0, 0, 0.00130548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0.00195822, 0, 0, 0, 0.000652742, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00130548, 0, 0, 0, 0, 0, 0.000652742, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0.000652742, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0.00326371, 0, 0, 0.000652742, 0.000652742, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0.000652742, 0, 0.000652742, 0.00195822, 0.00195822, 0, 0, 0, 0, 0, 0, 0, 0.00130548, 0, 0, 0, 0, 0, 0.000652742, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0.00130548, 0, 0, 0, 0, 0, 0.000652742, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0.000652742, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0.000652742, 0.000652742, 0, 0.00326371, 0, 0, 0, 0, 0, 0.00261097, 0.000652742, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0.000652742, 0, 0.000652742, 0, 0.000652742, 0, 0.000652742, 0, 0.00130548, 0, 0.000652742, 0, 0.00130548, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0.00130548, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0.000652742, 0, 0.00130548, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000652742, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00130548}; -static constexpr double kMemcpyGoogleL[] = {0.140541, 0.0486486, 0, 0.0324324, 0.0216216, 0, 0.0378378, 0, 0.027027, 0.00540541, 0, 0.210811, 0.0162162, 0.0216216, 0.0918919, 0, 0.0432432, 0.0918919, 0, 0.0702703, 0, 0, 0, 0.0972973, 0, 0, 0, 0.00540541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00540541, 0, 0.0108108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00540541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00540541, 0, 0, 0, 0, 0, 0.00540541, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00540541}; -static constexpr double kMemcpyGoogleM[] = {0.0721535, 0.0325991, 0.068308, 0.0556539, 0.0563932, 0.0461322, 0.0532884, 0.0617689, 0.0828007, 0.0433771, 0.0594034, 0.0279377, 0.0207739, 0.0242924, 0.0185332, 0.0384378, 0.0360666, 0.0178533, 0.0215373, 0.0189424, 0.00918205, 0.00407135, 0.00558588, 0.0164542, 0.00517671, 0.00187243, 0.00539378, 0.00443405, 0.00281149, 0.0020793, 0.00188286, 0.00131771, 0.0237737, 0.00349755, 0.00316146, 0.000935628, 0.00276963, 0.0021735, 0.00301304, 0.000647972, 0.00162138, 0.000899166, 0.000446995, 0.000298311, 0.000419752, 0.000250476, 0.000173168, 0.000251647, 0.00166741, 0.000240198, 0.000212313, 0.000251685, 0.000494377, 0.000263776, 0.000282404, 0.000370745, 0.000823369, 0.000437322, 0.000194252, 0.00019667, 0.000828546, 0.000114224, 0.000515272, 0.000150837, 0.0101547, 8.00283e-05, 7.56452e-05, 8.59983e-05, 9.46888e-05, 6.64257e-05, 6.00779e-05, 0.000211406, 0.000262491, 5.85287e-05, 6.83905e-05, 6.7257e-05, 0.00014294, 6.28362e-05, 5.11607e-05, 4.88936e-05, 0.000250325, 5.18408e-05, 4.29614e-05, 9.52933e-05, 8.53937e-05, 4.32636e-05, 4.22434e-05, 3.61601e-05, 0.000140484, 3.7747e-05, 7.67788e-05, 3.37796e-05, 4.91959e-05, 5.22564e-05, 3.06813e-05, 4.11099e-05, 0.00285317, 2.89054e-05, 3.44598e-05, 2.82631e-05, 4.53418e-05, 2.21041e-05, 2.75451e-05, 2.1953e-05, 0.000106667, 2.45979e-05, 2.74318e-05, 2.05549e-05, 2.30487e-05, 2.49002e-05, 2.88298e-05, 2.31243e-05, 8.13507e-05, 3.09836e-05, 5.78108e-05, 5.58838e-05, 6.01912e-05, 4.32258e-05, 3.97119e-05, 3.91451e-05, 0.000372181, 1.63986e-05, 1.63608e-05, 1.20911e-05, 1.70787e-05, 1.63986e-05, 2.1953e-05, 1.25068e-05, 0.00486468, 9.78627e-06, 2.28976e-05, 1.33003e-05, 1.22045e-05, 1.71921e-05, 1.13354e-05, 0.000251571, 0.000526834, 9.78627e-06, 1.06175e-05, 1.36025e-05, 1.92703e-05, 1.36781e-05, 1.02775e-05, 1.00508e-05, 2.18774e-05, 1.76455e-05, 9.29507e-06, 1.55296e-05, 1.03908e-05, 9.74849e-06, 1.78722e-05, 8.76608e-06, 1.85901e-05, 1.03908e-05, 1.09954e-05, 1.47361e-05, 7.40583e-06, 7.85925e-06, 8.19931e-06, 1.34514e-05, 0.000588612, 9.67292e-06, 8.04817e-06, 9.03057e-06, 9.52178e-06, 1.60208e-05, 1.12599e-05, 9.33285e-06, 0.000758153, 1.00508e-05, 1.7381e-05, 1.4056e-05, 1.0542e-05, 7.4814e-06, 9.67292e-06, 1.50006e-05, 1.4925e-05, 1.20911e-05, 9.74849e-06, 8.99279e-06, 1.63608e-05, 1.10332e-05, 1.14866e-05, 1.49628e-05, 1.46605e-05, 1.39804e-05, 9.78627e-06, 1.01263e-05, 9.74849e-06, 9.29507e-06, 1.31869e-05, 7.55697e-06, 0.000428593, 7.36804e-06, 9.06836e-06, 1.99882e-05, 1.11087e-05, 5.32766e-06, 7.63254e-06, 5.28988e-06, 2.19152e-05, 5.44102e-06, 8.19931e-06, 4.9876e-06, 5.55437e-06, 1.21667e-05, 5.81886e-06, 5.81886e-06, 1.06931e-05, 2.9321e-05, 1.16755e-05, 5.74329e-06, 0.000636939, 5.4788e-06, 5.78108e-06, 0.000331675, 0.000737333, 5.17652e-06, 5.93222e-06, 6.49899e-06, 0.000642644, 6.12114e-06, 4.08076e-06, 7.17912e-06, 0.000196406, 1.28468e-05, 6.19671e-06, 5.21431e-06, 0.000352003, 6.00779e-06, 1.75322e-05, 7.10355e-06, 8.65273e-06, 7.85925e-06, 2.34266e-05, 1.53406e-05, 1.37159e-05, 1.26957e-05, 1.35648e-05, 1.26579e-05, 0.000177513, 5.81886e-06, 4.19412e-06, 5.40323e-06, 4.87424e-06, 1.03908e-05, 4.64753e-06, 7.17912e-06, 5.44102e-06, 3.28728e-06, 1.17133e-05, 3.28728e-06, 3.43842e-06, 5.21431e-06, 5.55437e-06, 1.27713e-05, 0.00346324}; -static constexpr double kMemcpyGoogleQ[] = {0.0178373, 0.114968, 0.0227802, 0.0150139, 0.188859, 0.00455751, 0.0233952, 0.0106787, 0.341347, 0.00630641, 0.050229, 0.00491322, 0.00606186, 0.00478724, 0.0110566, 0.00501697, 0.0128277, 0.00962636, 0.00522447, 0.0112196, 0.00589142, 0.00513554, 0.00491322, 0.00341628, 0.00472796, 0.00269004, 0.00394985, 0.00325325, 0.00183042, 0.00234916, 0.00129685, 0.00220095, 0.0034311, 0.0016822, 0.000837397, 0.00180818, 0.001119, 0.00357932, 0.0012598, 0.00108195, 0.00443894, 0.0013265, 0.00113382, 0.00103007, 0.000933734, 0.0016081, 0.00108195, 0.00116346, 0.000726238, 0.00250478, 0.00100043, 0.0010523, 0.00117087, 0.00113382, 0.000778112, 0.00108936, 0.001119, 0.00169703, 0.00145989, 0.000941145, 0.00181559, 0.000963377, 0.000637311, 0.000829986, 0.00169703, 0.00120793, 0.00138578, 0.00074847, 0.000792933, 0.000474278, 0.00075588, 0.000444635, 0.000704006, 0.000511331, 0.000437225, 0.000518741, 0.000333477, 0.000414993, 0.00037794, 0.00228246, 0.00904092, 0.000466867, 0.000259371, 0.000392761, 0.00025196, 0.000296424, 0.000289013, 0.000148212, 0.000852218, 0.000177854, 0.000103748, 0.000133391, 0.000192675, 0.000192675, 0.000185265, 0.000111159, 0.000407583, 0.000578026, 0.000111159, 0.00111159, 0.000118569, 0.000340887, 0.000177854, 0.000170444, 0.000133391, 0.000118569, 0.000155622, 8.89271e-05, 4.44635e-05, 7.41059e-05, 9.63377e-05, 5.92847e-05, 9.63377e-05, 0.000111159, 5.92847e-05, 0.00012598, 7.41059e-05, 5.18741e-05, 0.000155622, 3.7053e-05, 0.000177854, 0.00024455, 5.92847e-05, 5.92847e-05, 5.18741e-05, 0.000200086, 0.000103748, 2.22318e-05, 0.000555794, 2.96424e-05, 5.92847e-05, 5.18741e-05, 3.7053e-05, 3.7053e-05, 2.96424e-05, 2.22318e-05, 0.00012598, 2.96424e-05, 5.18741e-05, 2.22318e-05, 2.96424e-05, 5.18741e-05, 1.48212e-05, 2.96424e-05, 0.000140801, 2.96424e-05, 8.89271e-05, 7.41059e-05, 5.18741e-05, 7.41059e-05, 5.18741e-05, 7.41059e-06, 0.00037794, 4.44635e-05, 5.18741e-05, 5.18741e-05, 5.92847e-05, 4.44635e-05, 5.18741e-05, 2.22318e-05, 5.92847e-05, 2.96424e-05, 2.22318e-05, 4.44635e-05, 1.48212e-05, 3.7053e-05, 7.41059e-06, 5.18741e-05, 5.92847e-05, 3.7053e-05, 3.7053e-05, 2.96424e-05, 2.96424e-05, 5.18741e-05, 4.44635e-05, 2.96424e-05, 0.000274192, 7.41059e-05, 6.66953e-05, 6.66953e-05, 0.000140801, 5.18741e-05, 2.96424e-05, 7.41059e-05, 8.89271e-05, 5.18741e-05, 8.89271e-05, 6.66953e-05, 8.89271e-05, 0.000111159, 7.41059e-05, 3.7053e-05, 0.000185265, 8.89271e-05, 7.41059e-05, 5.92847e-05, 7.41059e-06, 5.92847e-05, 4.44635e-05, 4.44635e-05, 0.000155622, 6.66953e-05, 8.89271e-05, 3.7053e-05, 6.66953e-05, 4.44635e-05, 5.18741e-05, 2.22318e-05, 0.000155622, 5.18741e-05, 3.7053e-05, 7.41059e-05, 3.7053e-05, 8.15165e-05, 3.7053e-05, 1.48212e-05, 4.44635e-05, 3.7053e-05, 4.44635e-05, 4.44635e-05, 3.7053e-05, 6.66953e-05, 6.66953e-05, 2.22318e-05, 0.000155622, 5.92847e-05, 4.44635e-05, 6.66953e-05, 2.96424e-05, 2.96424e-05, 3.7053e-05, 2.96424e-05, 3.7053e-05, 5.18741e-05, 7.41059e-06, 2.22318e-05, 5.92847e-05, 2.96424e-05, 2.22318e-05, 2.22318e-05, 8.15165e-05, 1.48212e-05, 4.44635e-05, 2.22318e-05, 4.44635e-05, 2.22318e-05, 3.7053e-05, 2.22318e-05, 8.15165e-05, 3.7053e-05, 3.7053e-05, 5.92847e-05, 1.48212e-05, 1.48212e-05, 1.48212e-05, 1.48212e-05, 0.000207497, 3.7053e-05, 2.96424e-05, 3.7053e-05, 3.7053e-05, 1.48212e-05, 3.7053e-05, 1.48212e-05, 0.00012598, 2.96424e-05, 2.22318e-05, 2.96424e-05, 2.22318e-05, 2.96424e-05, 2.22318e-05, 2.96424e-05, 4.44635e-05, 2.22318e-05, 2.96424e-05, 3.7053e-05, 1.48212e-05, 2.22318e-05, 2.22318e-05, 2.96424e-05, 2.96424e-05, 2.96424e-05, 1.48212e-05, 2.22318e-05, 1.48212e-05, 1.48212e-05, 2.96424e-05, 1.48212e-05, 2.22318e-05, 1.48212e-05, 2.96424e-05, 1.48212e-05, 1.48212e-05, 1.48212e-05, 1.48212e-05, 7.41059e-06, 6.66953e-05, 1.48212e-05, 2.96424e-05, 2.96424e-05, 2.22318e-05, 1.48212e-05, 7.41059e-06, 7.41059e-06, 7.41059e-06, 0, 2.96424e-05, 0, 2.22318e-05, 2.22318e-05, 1.48212e-05, 2.22318e-05, 7.41059e-06, 1.48212e-05, 7.41059e-06, 2.22318e-05, 2.22318e-05, 2.22318e-05, 7.41059e-06, 2.96424e-05, 0.000207497, 7.41059e-06, 2.96424e-05, 7.41059e-06, 7.41059e-06, 7.41059e-06, 7.41059e-06, 1.48212e-05, 7.41059e-06, 1.48212e-05, 7.41059e-06, 5.18741e-05, 7.41059e-06, 1.48212e-05, 1.48212e-05, 1.48212e-05, 8.15165e-05, 0, 1.48212e-05, 7.41059e-06, 1.48212e-05, 0, 7.41059e-06, 1.48212e-05, 2.96424e-05, 7.41059e-06, 2.22318e-05, 2.22318e-05, 2.22318e-05, 7.41059e-06, 3.7053e-05, 2.22318e-05, 7.41059e-06, 7.41059e-06, 7.41059e-06, 1.48212e-05, 4.44635e-05, 2.22318e-05, 7.41059e-06, 1.48212e-05, 2.22318e-05, 2.22318e-05, 0, 1.48212e-05, 0, 2.96424e-05, 1.48212e-05, 7.41059e-06, 0.000118569, 2.96424e-05, 7.41059e-06, 1.48212e-05, 1.48212e-05, 2.22318e-05, 1.48212e-05, 7.41059e-06, 1.48212e-05, 1.48212e-05, 5.18741e-05, 7.41059e-06, 0, 0, 1.48212e-05, 2.22318e-05, 0.000185265, 0, 2.22318e-05, 0, 7.41059e-06, 0, 3.7053e-05, 0, 3.7053e-05, 0, 3.7053e-05, 0, 3.7053e-05, 0, 4.44635e-05, 0, 7.41059e-05, 0, 1.48212e-05, 0, 1.48212e-05, 0, 4.44635e-05, 0, 5.92847e-05, 0, 0, 0, 2.96424e-05, 0, 2.96424e-05, 0, 7.41059e-06, 0, 2.22318e-05, 0, 2.96424e-05, 0, 2.22318e-05, 0, 1.48212e-05, 0, 2.96424e-05, 0, 1.48212e-05, 0, 2.22318e-05, 0, 3.7053e-05, 0, 1.48212e-05, 0, 1.48212e-05, 0, 2.22318e-05, 0, 1.48212e-05, 0, 2.22318e-05, 0, 2.22318e-05, 0, 7.41059e-06, 0, 7.41059e-05, 0, 1.48212e-05, 0, 2.96424e-05, 0, 1.48212e-05, 0, 1.48212e-05, 0, 1.48212e-05, 0, 1.48212e-05, 0, 2.22318e-05, 0, 7.41059e-06, 0, 0, 0, 2.22318e-05, 0, 1.48212e-05, 0, 2.96424e-05, 0, 2.22318e-05, 0, 2.22318e-05, 0, 0, 0, 5.18741e-05, 0, 3.7053e-05, 0, 7.41059e-06, 0, 2.96424e-05, 0, 4.44635e-05, 0, 2.22318e-05, 0, 2.22318e-05, 0, 2.96424e-05, 0, 0.000207497, 0, 2.96424e-05, 0, 2.96424e-05, 0, 3.7053e-05, 0, 1.48212e-05, 0, 3.7053e-05, 0, 1.48212e-05, 0, 2.96424e-05, 0, 0.000155622, 0, 1.48212e-05, 0, 7.41059e-06, 0, 2.96424e-05, 0, 2.22318e-05, 0, 4.44635e-05, 0, 1.48212e-05, 0, 3.7053e-05, 0, 2.96424e-05, 0, 2.22318e-05, 0, 1.48212e-05, 0, 7.41059e-06, 0, 7.41059e-06, 0, 2.22318e-05, 0, 2.96424e-05, 0, 7.41059e-06, 0, 1.48212e-05, 0, 2.22318e-05, 0, 7.41059e-06, 0, 2.96424e-05, 0, 7.41059e-06, 0, 0, 0, 0, 0, 2.96424e-05, 0, 2.96424e-05, 0, 3.7053e-05, 0, 2.22318e-05, 0, 7.41059e-06, 0, 8.89271e-05, 0, 0, 0, 7.41059e-06, 0, 2.96424e-05, 0, 5.92847e-05, 0, 1.48212e-05, 0, 2.96424e-05, 0, 7.41059e-06, 0, 2.22318e-05, 0, 1.48212e-05, 0, 2.96424e-05, 0, 0, 0, 1.48212e-05, 0, 2.22318e-05, 0, 1.48212e-05, 0, 7.41059e-06}; -static constexpr double kMemcpyGoogleS[] = {0.0184049, 0.0306748, 0.00613497, 0.0122699, 0.0306748, 0.0122699, 0.0245399, 0.0245399, 0.00613497, 0.0122699, 0.00613497, 0.0122699, 0.0490798, 0.0920245, 0.0122699, 0, 0.0122699, 0.00613497, 0.147239, 0.239264, 0.00613497, 0.0184049, 0.0245399, 0, 0.0122699, 0.00613497, 0.00613497, 0.0122699, 0.00613497, 0, 0, 0.00613497, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0.0184049, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0122699, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0.00613497, 0.00613497, 0, 0.0122699, 0.0122699, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00613497}; -static constexpr double kMemcpyGoogleU[] = {0.02843, 0.025555, 0.00303466, 0.00239578, 0.0971091, 0.0247564, 0.00543044, 0.0367353, 0.00798594, 0.0033541, 0.01134, 0.0105414, 0.0635681, 0.00782623, 0.0116595, 0.0059096, 0.468296, 0.00127775, 0.00287494, 0.00383325, 0.00191663, 0.000638876, 0.00319438, 0.00159719, 0.00175691, 0.000638876, 0.000479157, 0.00127775, 0.00111803, 0.000638876, 0.00111803, 0.00127775, 0.00111803, 0.00111803, 0.00127775, 0.0220412, 0.00111803, 0.00111803, 0.00159719, 0.00111803, 0.00159719, 0.00191663, 0.000638876, 0.00111803, 0.000958313, 0.000638876, 0.00127775, 0.000958313, 0.000798594, 0.00127775, 0.00686791, 0.00670819, 0.000638876, 0.00159719, 0.00111803, 0.00127775, 0.00127775, 0.000319438, 0.000798594, 0.00143747, 0.000638876, 0.00127775, 0.000798594, 0.00143747, 0.000638876, 0.00159719, 0.000479157, 0.000798594, 0.000638876, 0.000638876, 0.000638876, 0.000798594, 0.00175691, 0.000958313, 0.00127775, 0.00207635, 0.000798594, 0.00143747, 0.000798594, 0.000798594, 0.00143747, 0.00143747, 0.000479157, 0.000638876, 0.00127775, 0.000159719, 0.00111803, 0.000798594, 0.00111803, 0.00111803, 0.00175691, 0.00127775, 0.00111803, 0.000958313, 0.000958313, 0.000319438, 0.00175691, 0.000958313, 0.00111803, 0.00111803, 0.00127775, 0.000958313, 0.00127775, 0.00127775, 0.00143747, 0.000958313, 0.00127775, 0.00127775, 0.00111803, 0.000798594, 0.000479157, 0.000798594, 0.00111803, 0.00127775, 0.000638876, 0.00127775, 0.000798594, 0.000958313, 0.000479157, 0.000638876, 0.00111803, 0.000958313, 0.000798594, 0.000798594, 0.000798594, 0.000479157, 0.000958313, 0.000638876, 0.00127775, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0.000319438, 0, 0, 0.000319438, 0, 0.000159719, 0, 0.000159719, 0, 0.000159719, 0.000319438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000319438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000319438, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0.000479157, 0.000159719, 0, 0.000159719, 0, 0, 0, 0, 0.000159719, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000479157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0.000319438, 0, 0, 0, 0.000479157, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0.000159719, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0.000319438, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0.000319438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0.000798594, 0, 0, 0, 0.0159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0.000159719, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000319438, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0.000159719, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0.00111803, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000159719}; -static constexpr double kMemcpyGoogleW[] = {0.0199353, 0.0245151, 0.102101, 0.0301724, 0.0347522, 0.0309806, 0.0242457, 0.0239763, 0.0360991, 0.0358297, 0.03125, 0.0188578, 0.0261315, 0.028556, 0.00942888, 0.0118534, 0.0282866, 0.0172414, 0.0180496, 0.0185884, 0.012931, 0.0145474, 0.00915948, 0.0107759, 0.0153556, 0.0115841, 0.00969828, 0.0123922, 0.0105065, 0.00996767, 0.0121228, 0.0107759, 0.0307112, 0.0102371, 0.00727371, 0.0113147, 0.00889009, 0.00915948, 0.00835129, 0.00915948, 0.0105065, 0.00484914, 0.00835129, 0.00538793, 0.00996767, 0.00538793, 0.00862069, 0.00511853, 0.00592672, 0.00565733, 0.00511853, 0.0080819, 0.00377155, 0.00404095, 0.00511853, 0.00457974, 0.00431034, 0.00296336, 0.00242457, 0.00404095, 0.00565733, 0.00188578, 0.00215517, 0.00242457, 0.0080819, 0.00080819, 0.00080819, 0.000269397, 0.00188578, 0.00161638, 0, 0.000269397, 0.00269397, 0.00107759, 0, 0.000269397, 0.000538793, 0, 0.000269397, 0.00134698, 0.00134698, 0.000538793, 0.000269397, 0.000269397, 0, 0, 0, 0.000538793, 0.00215517, 0.00080819, 0.000269397, 0.000269397, 0.000538793, 0.000538793, 0.00107759, 0.00161638, 0.00134698, 0.00296336, 0.000538793, 0.000269397, 0.000269397, 0.00134698, 0, 0.00107759, 0.00161638, 0, 0, 0, 0, 0, 0, 0.000269397, 0.00080819, 0.000269397, 0.00080819, 0, 0.000269397, 0.000269397, 0, 0, 0.00161638, 0.000269397, 0.000269397, 0, 0.000538793, 0, 0, 0, 0.00404095, 0, 0.000269397, 0.000269397, 0, 0.000269397, 0.000269397, 0.000269397, 0.000538793, 0.000269397, 0.000538793, 0.000269397, 0, 0.000538793, 0.000269397, 0, 0.000538793, 0.000269397, 0, 0, 0, 0.000269397, 0.000269397, 0.000269397, 0.00080819, 0.000269397, 0.000538793, 0, 0.000269397, 0.000269397, 0.000538793, 0.000269397, 0.000538793, 0, 0, 0.000269397, 0, 0.000269397, 0.000269397, 0, 0.000269397, 0.000269397, 0.000269397, 0, 0, 0, 0, 0, 0.000269397, 0, 0, 0, 0, 0.000269397, 0.000269397, 0, 0.000269397, 0, 0, 0, 0.000269397, 0, 0, 0.000269397, 0.000269397, 0.000269397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000269397, 0, 0, 0, 0, 0.000269397, 0, 0, 0, 0, 0, 0, 0.000538793, 0, 0.000269397, 0, 0, 0, 0, 0, 0.000269397, 0, 0.000269397, 0.000269397, 0, 0.000269397, 0.000269397, 0.000269397, 0, 0, 0, 0.000269397, 0, 0.000269397, 0, 0, 0, 0.000269397, 0, 0, 0.000269397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00215517}; -static constexpr double kMemcpyUniform384To4096[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -static constexpr double kMemsetGoogleB[] = {0, 0, 0, 0, 0, 0, 0, 0, 0.0681818, 0, 0, 0, 0, 0, 0.5, 0, 0.0227273, 0, 0, 0, 0, 0, 0.0227273, 0, 0.0454545, 0.0227273, 0, 0, 0, 0, 0, 0.0227273, 0.0227273, 0, 0, 0, 0, 0, 0, 0.0227273, 0.0227273, 0, 0, 0, 0, 0, 0, 0, 0.0454545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0227273, 0, 0, 0, 0, 0, 0, 0, 0.0227273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0681818, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0227273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0227273, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0227273}; -static constexpr double kMemsetGoogleD[] = {0.0243902, 0, 0, 0, 0, 0, 0, 0, 0.0487805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0243902, 0, 0, 0, 0, 0, 0, 0.0609756, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0.0121951, 0, 0, 0, 0.0365854, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0.0609756, 0, 0, 0, 0, 0, 0, 0, 0.0243902, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0.0609756, 0, 0, 0, 0, 0, 0, 0, 0.0487805, 0, 0, 0, 0, 0, 0, 0, 0.0243902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0853659, 0, 0, 0, 0, 0, 0, 0, 0.0487805, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0.0853659, 0, 0, 0, 0, 0, 0, 0, 0.0731707, 0, 0, 0, 0, 0, 0, 0, 0.0365854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0243902, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0365854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0121951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0365854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0365854}; -static constexpr double kMemsetGoogleQ[] = {0, 0, 0.00431894, 0.00548173, 0.00332226, 0.00249169, 0.00365449, 0.00265781, 0.0038206, 0.00232558, 0.00232558, 0.00299003, 0.00249169, 0.000830565, 0.000996678, 0.00116279, 0.00348837, 0.0013289, 0.000996678, 0.000166113, 0.000498339, 0.000830565, 0.00116279, 0.000664452, 0.000830565, 0.0013289, 0.000996678, 0.000498339, 0.000664452, 0, 0.000664452, 0.00215947, 0.20814, 0.0013289, 0.000332226, 0.000332226, 0.000498339, 0.000498339, 0.000830565, 0.000332226, 0.000498339, 0.000664452, 0.000166113, 0.000166113, 0.000664452, 0.000498339, 0.000498339, 0.000996678, 0.000664452, 0, 0.000498339, 0.000166113, 0.000166113, 0, 0.000332226, 0.000332226, 0.0543189, 0, 0.000498339, 0.000332226, 0.000332226, 0.000332226, 0.000166113, 0, 0.0601329, 0.000166113, 0.000166113, 0, 0, 0, 0.000332226, 0.000332226, 0.157807, 0, 0.000332226, 0.000166113, 0.000996678, 0, 0, 0.0013289, 0.123588, 0, 0.000166113, 0.000166113, 0.00282392, 0.000166113, 0, 0.000166113, 0.0330565, 0.000166113, 0, 0, 0.000166113, 0.000166113, 0.000166113, 0, 0.0129568, 0.000166113, 0.000166113, 0.000332226, 0.00182724, 0, 0, 0.000166113, 0.0126246, 0.000166113, 0.000166113, 0.000332226, 0.000664452, 0.000166113, 0, 0.000332226, 0.0166113, 0, 0.000166113, 0, 0.0013289, 0.000166113, 0, 0, 0.000166113, 0, 0, 0, 0.00199336, 0.00664452, 0, 0, 0, 0, 0, 0, 0.000498339, 0, 0, 0, 0.000166113, 0, 0, 0, 0.000498339, 0, 0, 0.000498339, 0.000166113, 0, 0, 0, 0, 0, 0, 0, 0.000332226, 0, 0, 0, 0.0013289, 0, 0, 0, 0.00232558, 0, 0, 0, 0.00166113, 0, 0, 0, 0, 0, 0, 0, 0.00166113, 0, 0, 0, 0.00647841, 0, 0, 0, 0, 0, 0, 0, 0.000830565, 0, 0, 0, 0.000498339, 0, 0, 0, 0.0702658, 0, 0, 0, 0.00149502, 0, 0, 0, 0.00166113, 0, 0, 0, 0.00182724, 0, 0, 0, 0.000166113, 0, 0, 0, 0.00282392, 0, 0, 0, 0.00299003, 0, 0, 0, 0, 0, 0, 0, 0.0121262, 0, 0, 0, 0, 0, 0, 0, 0.0038206, 0, 0, 0, 0.00215947, 0, 0, 0, 0.000498339, 0, 0, 0, 0.00365449, 0, 0, 0, 0.00448505, 0, 0, 0, 0.00199336, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0013289, 0, 0, 0, 0, 0, 0, 0.0162791, 0.00116279, 0, 0, 0, 0.00365449, 0, 0, 0, 0.000664452, 0, 0, 0, 0.000498339, 0, 0, 0, 0.00149502, 0, 0, 0, 0.0013289, 0, 0, 0, 0.00448505, 0, 0, 0, 0.00199336, 0, 0, 0, 0.00265781, 0, 0, 0, 0, 0, 0, 0, 0.000996678, 0, 0, 0, 0, 0, 0, 0, 0.00265781, 0, 0, 0, 0.000332226, 0, 0, 0, 0.00232558, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000332226, 0, 0, 0, 0.000166113, 0, 0, 0, 0.00282392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000830565, 0, 0, 0, 0.000664452, 0, 0, 0, 0, 0, 0, 0, 0.000166113, 0, 0, 0, 0, 0, 0, 0, 0.00116279, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000332226, 0, 0, 0, 0, 0, 0, 0, 0.000830565, 0, 0, 0, 0, 0, 0, 0, 0.00149502, 0, 0, 0, 0.00199336, 0, 0, 0, 0.000664452, 0, 0, 0, 0, 0, 0, 0, 0.00166113, 0, 0, 0, 0, 0, 0, 0, 0.000830565, 0, 0, 0, 0, 0, 0, 0, 0.000996678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.00199336, 0, 0, 0, 0, 0, 0, 0, 0.000664452, 0, 0, 0, 0, 0, 0, 0, 0.000166113, 0, 0, 0, 0.0285714, 0, 0, 0, 0.000664452, 0, 0, 0, 0, 0, 0, 0, 0.000664452, 0, 0, 0, 0, 0, 0, 0, 0.000166113, 0, 0, 0, 0.000166113, 0, 0, 0, 0, 0, 0, 0, 0.00215947, 0, 0, 0, 0, 0, 0, 0, 0.0038206, 0, 0, 0, 0.000332226, 0, 0, 0, 0.000332226, 0, 0, 0, 0, 0, 0, 0, 0.000664452, 0, 0, 0, 0, 0, 0, 0, 0.000830565, 0, 0, 0, 0, 0, 0, 0, 0.000166113, 0, 0, 0, 0, 0, 0, 0, 0.000996678, 0, 0, 0, 0, 0, 0, 0, 0.000166113, 0, 0, 0, 0.000498339, 0, 0, 0, 0.000996678, 0, 0, 0, 0.00182724, 0, 0, 0, 0, 0, 0, 0, 0.000498339, 0, 0, 0, 0, 0, 0, 0, 0.000166113, 0, 0, 0, 0, 0, 0, 0, 0.000332226}; -static constexpr double kMemsetGoogleU[] = {0.10641, 0.0986191, 0.0200672, 0.00420913, 0.150642, 0.0275624, 0.00276916, 0.00328607, 0.323364, 0.128138, 0.0109843, 0.00352607, 0.00149535, 0.00193841, 0.000443066, 0.000719982, 0.0143073, 0.0152119, 0.000479988, 0.0146396, 0.00123689, 0.000184611, 9.23054e-05, 0.00670137, 0.00535371, 0, 7.38443e-05, 7.38443e-05, 0.000553833, 5.53833e-05, 0.000147689, 0.00625831, 0.000406144, 5.53833e-05, 1.84611e-05, 1.84611e-05, 0.000350761, 0, 0, 9.23054e-05, 0.000276916, 0, 0.000110767, 0, 0.000129228, 0.000129228, 0, 0.00203072, 0.000239994, 1.84611e-05, 0, 3.69222e-05, 0.000184611, 3.69222e-05, 5.53833e-05, 0, 9.23054e-05, 0.000110767, 0, 3.69222e-05, 0.000129228, 3.69222e-05, 5.53833e-05, 3.69222e-05, 0.00917516, 1.84611e-05, 0, 0, 0.000184611, 0, 0, 0, 0.00695983, 0, 0, 0, 3.69222e-05, 0, 3.69222e-05, 0.00143996, 0.000129228, 7.38443e-05, 0, 1.84611e-05, 7.38443e-05, 0, 1.84611e-05, 1.84611e-05, 7.38443e-05, 1.84611e-05, 3.69222e-05, 3.69222e-05, 1.84611e-05, 3.69222e-05, 0, 3.69222e-05, 0.000147689, 0, 1.84611e-05, 1.84611e-05, 0, 1.84611e-05, 1.84611e-05, 1.84611e-05, 9.23054e-05, 5.53833e-05, 0.00529833, 3.69222e-05, 5.53833e-05, 0, 1.84611e-05, 1.84611e-05, 0.00016615, 0, 1.84611e-05, 3.69222e-05, 3.69222e-05, 9.23054e-05, 0, 1.84611e-05, 5.53833e-05, 0, 0, 3.69222e-05, 0, 0, 1.84611e-05, 0, 0.000110767, 0, 0, 0, 0.000110767, 0, 0, 3.69222e-05, 0.000110767, 0, 0, 0, 0, 3.69222e-05, 0, 0.00125535, 1.84611e-05, 0, 0, 3.69222e-05, 0, 0, 1.84611e-05, 0, 1.84611e-05, 1.84611e-05, 0, 0, 1.84611e-05, 0, 0, 5.53833e-05, 1.84611e-05, 0, 3.69222e-05, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 1.84611e-05, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 1.84611e-05, 0, 3.69222e-05, 1.84611e-05, 0, 0, 1.84611e-05, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 7.38443e-05, 0, 0, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0.000313838, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000203072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 1.84611e-05, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0.000590755, 0, 0, 0, 0, 0, 0, 0, 7.38443e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 1.84611e-05, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 5.53833e-05, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 1.84611e-05, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 0.0136058, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0.000203072, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0.000239994, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 0.000203072, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 0.000129228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 1.84611e-05, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 0.000110767, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 7.38443e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 5.53833e-05, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 7.38443e-05, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 1.84611e-05, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 9.23054e-05, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.000701521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7.38443e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.69222e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.84611e-05}; -// clang-format on +static constexpr double MemcmpGoogleA[] = { +#include "distributions/MemcmpGoogleA.csv" +}; +static constexpr double MemcmpGoogleB[] = { +#include "distributions/MemcmpGoogleB.csv" +}; +static constexpr double MemcmpGoogleD[] = { +#include "distributions/MemcmpGoogleD.csv" +}; +static constexpr double MemcmpGoogleQ[] = { +#include "distributions/MemcmpGoogleQ.csv" +}; +static constexpr double MemcmpGoogleL[] = { +#include "distributions/MemcmpGoogleL.csv" +}; +static constexpr double MemcmpGoogleM[] = { +#include "distributions/MemcmpGoogleM.csv" +}; +static constexpr double MemcmpGoogleS[] = { +#include "distributions/MemcmpGoogleS.csv" +}; +static constexpr double MemcmpGoogleW[] = { +#include "distributions/MemcmpGoogleW.csv" +}; +static constexpr double MemcmpGoogleU[] = { +#include "distributions/MemcmpGoogleU.csv" +}; +static constexpr double MemcpyGoogleA[] = { +#include "distributions/MemcpyGoogleA.csv" +}; +static constexpr double MemcpyGoogleD[] = { +#include "distributions/MemcpyGoogleD.csv" +}; +static constexpr double MemcpyGoogleB[] = { +#include "distributions/MemcpyGoogleB.csv" +}; +static constexpr double MemcpyGoogleQ[] = { +#include "distributions/MemcpyGoogleQ.csv" +}; +static constexpr double MemcpyGoogleL[] = { +#include "distributions/MemcpyGoogleL.csv" +}; +static constexpr double MemcpyGoogleM[] = { +#include "distributions/MemcpyGoogleM.csv" +}; +static constexpr double MemcpyGoogleS[] = { +#include "distributions/MemcpyGoogleS.csv" +}; +static constexpr double MemcpyGoogleW[] = { +#include "distributions/MemcpyGoogleW.csv" +}; +static constexpr double MemcpyGoogleU[] = { +#include "distributions/MemcpyGoogleU.csv" +}; +static constexpr double MemsetGoogleA[] = { +#include "distributions/MemsetGoogleA.csv" +}; +static constexpr double MemsetGoogleB[] = { +#include "distributions/MemsetGoogleB.csv" +}; +static constexpr double MemsetGoogleD[] = { +#include "distributions/MemsetGoogleD.csv" +}; +static constexpr double MemsetGoogleQ[] = { +#include "distributions/MemsetGoogleQ.csv" +}; +static constexpr double MemsetGoogleL[] = { +#include "distributions/MemsetGoogleL.csv" +}; +static constexpr double MemsetGoogleM[] = { +#include "distributions/MemsetGoogleM.csv" +}; +static constexpr double MemsetGoogleS[] = { +#include "distributions/MemsetGoogleS.csv" +}; +static constexpr double MemsetGoogleW[] = { +#include "distributions/MemsetGoogleW.csv" +}; +static constexpr double MemsetGoogleU[] = { +#include "distributions/MemsetGoogleU.csv" +}; +static constexpr double Uniform384To4096[] = { +#include "distributions/Uniform384To4096.csv" +}; ArrayRef getMemcpySizeDistributions() { static constexpr MemorySizeDistribution kDistributions[] = { - {"memcpy Google A", kMemcpyGoogleA}, - {"memcpy Google B", kMemcpyGoogleB}, - {"memcpy Google D", kMemcpyGoogleD}, - {"memcpy Google L", kMemcpyGoogleL}, - {"memcpy Google M", kMemcpyGoogleM}, - {"memcpy Google Q", kMemcpyGoogleQ}, - {"memcpy Google S", kMemcpyGoogleS}, - {"memcpy Google U", kMemcpyGoogleU}, - {"memcpy Google W", kMemcpyGoogleW}, - {"uniform 384 to 4096", kMemcpyUniform384To4096}, + {"memcpy Google A", MemcpyGoogleA}, + {"memcpy Google B", MemcpyGoogleB}, + {"memcpy Google D", MemcpyGoogleD}, + {"memcpy Google L", MemcpyGoogleL}, + {"memcpy Google M", MemcpyGoogleM}, + {"memcpy Google Q", MemcpyGoogleQ}, + {"memcpy Google S", MemcpyGoogleS}, + {"memcpy Google U", MemcpyGoogleU}, + {"memcpy Google W", MemcpyGoogleW}, + {"uniform 384 to 4096", Uniform384To4096}, }; return kDistributions; } ArrayRef getMemsetSizeDistributions() { static constexpr MemorySizeDistribution kDistributions[] = { - {"memset Google B", kMemsetGoogleB}, - {"memset Google D", kMemsetGoogleD}, - {"memset Google Q", kMemsetGoogleQ}, - {"memset Google U", kMemsetGoogleU}, + {"memset Google A", MemsetGoogleA}, + {"memset Google B", MemsetGoogleB}, + {"memset Google D", MemsetGoogleD}, + {"memset Google L", MemsetGoogleL}, + {"memset Google M", MemsetGoogleM}, + {"memset Google Q", MemsetGoogleQ}, + {"memset Google S", MemsetGoogleS}, + {"memset Google U", MemsetGoogleU}, + {"memset Google W", MemsetGoogleW}, + {"uniform 384 to 4096", Uniform384To4096}, }; return kDistributions; } ArrayRef getMemcmpSizeDistributions() { static constexpr MemorySizeDistribution kDistributions[] = { - {"memcmp Google A", kMemcmpGoogleA}, {"memcmp Google B", kMemcmpGoogleB}, - {"memcmp Google D", kMemcmpGoogleD}, {"memcmp Google L", kMemcmpGoogleL}, - {"memcmp Google M", kMemcmpGoogleM}, {"memcmp Google Q", kMemcmpGoogleQ}, - {"memcmp Google S", kMemcmpGoogleS}, {"memcmp Google U", kMemcmpGoogleU}, - {"memcmp Google W", kMemcmpGoogleW}, + {"memcmp Google A", MemcmpGoogleA}, + {"memcmp Google B", MemcmpGoogleB}, + {"memcmp Google D", MemcmpGoogleD}, + {"memcmp Google L", MemcmpGoogleL}, + {"memcmp Google M", MemcmpGoogleM}, + {"memcmp Google Q", MemcmpGoogleQ}, + {"memcmp Google S", MemcmpGoogleS}, + {"memcmp Google U", MemcmpGoogleU}, + {"memcmp Google W", MemcmpGoogleW}, + {"uniform 384 to 4096", Uniform384To4096}, }; return kDistributions; } diff --git a/libc/benchmarks/distributions/MemcmpGoogleA.csv b/libc/benchmarks/distributions/MemcmpGoogleA.csv new file mode 100644 index 0000000000000..31209d6d09c03 --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleA.csv @@ -0,0 +1 @@ +0,0,0.000230805,0.00869365,0.0258501,0.0519311,0.246115,0.00584705,0.0276966,0.00500077,0.00853978,0.0200031,0.1471,0.0370057,0.0113094,0.131097,0.0282351,0.0480843,0.0125404,0.00646253,0.00707801,0.00592399,0.00100015,0.00284659,0.0363133,0.00469303,0.0318511,0.00323127,0.00107709,0.00292353,0.00130789,0.0656255,0.00015387,0.00030774,0.000461609,0.00261579,0.00530851,0.000230805,0.00100015,0,0,7.69349e-05,0,0,0,0,0,0.00030774,0,0,0,0,0,0,0,0.000230805,0,0,7.69349e-05,0,0.000384675,0,0,0,0.00015387,0,0.00100015,0.000615479,0.000923219,7.69349e-05,0,0.00030774,0,0,0,0,7.69349e-05,0,0,0,7.69349e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleB.csv b/libc/benchmarks/distributions/MemcmpGoogleB.csv new file mode 100644 index 0000000000000..101f3db3ab382 --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleB.csv @@ -0,0 +1 @@ +0.00178971,0.00274345,0.00611042,0.00195598,0.00384961,0.00668543,0.0122786,0.00709187,0.00451931,0.0036741,0.00326305,0.00951202,0.0110223,0.0112371,0.00917717,0.00672469,0.0481005,0.025728,0.0181165,0.0124679,0.0246841,0.191783,0.0117059,0.0152506,0.0164538,0.00392582,0.00785856,0.0284252,0.00302057,0.00916101,0.0206036,0.00402281,0.00470405,0.0443802,0.0128744,0.00666696,0.0148142,0.00918641,0.0388402,0.0100686,0.00490034,0.00538761,0.00495115,0.0166016,0.00608501,0.00699719,0.002979,0.00481259,0.00629978,0.00557235,0.00391658,0.00750524,0.00320069,0.00436689,0.00364177,0.0063044,0.0107821,0.00264415,0.00331154,0.00513358,0.00296284,0.00490958,0.00526752,0.00408054,0.00303673,0.00302288,0.00236011,0.00256564,0.0100501,0.00258642,0.00297207,0.00482875,0.00167425,0.0019606,0.00434149,0.00726738,0.00517284,0.00215689,0.00204835,0.00195136,0.00145717,0.0092349,0.00571322,0.00130245,0.00250098,0.00143408,0.00168348,0.00264646,0.00121931,0.00100224,0.00108075,0.00135787,0.0015888,0.00108075,0.00063044,0.000720503,0.000780545,0.00117313,0.000683554,0.00069741,0.000789782,0.000699719,0.000436458,0.000635058,0.000417984,0.000484954,0.000512665,0.000526521,0.000445696,0.000639677,0.000434149,0.000792091,0.000521903,0.000417984,0.000417984,0.000334849,0.000454933,0.00151952,0.000341777,0.000281735,0.000715884,0.000738977,0.000722812,0.000690482,0.000609656,0.000725121,0.00082904,0.00042953,0.00110847,0.000383344,0.000473407,0.000508047,0.000480335,0.000311756,0.000309447,0.000708956,0.000625821,0.000348705,0.000461861,0.000588872,0.000628131,0.000309447,0.000320993,0.000501119,0.000466479,0.00621434,0.000344086,0.000466479,0.000293282,0.000570398,0.00150105,0.00182204,0.00115003,0.000355633,0.000355633,0.000692791,0.00169041,0.000549614,0.000494191,0.000348705,0.000394891,0.000554233,0.0012909,0.00104842,0.000339468,0.000443386,0.000411056,0.000508047,0.000355633,0.000351014,0.000408747,0.000258642,0.00042953,0.000519593,0.000930649,0.000448005,0.000607347,0.00043184,0.00046417,0.000484954,0.00063044,0.000348705,0.000445696,0.00056347,0.000378726,0.000942196,0.000381035,0.000323302,0.00036487,0.000367179,0.000533449,0.0002979,0.000247095,0.000320993,0.000459551,0.000371798,0.000586563,0.000424912,0.000323302,0.00708725,0.000272498,0.000448005,0.00046417,0.000286354,0.000256333,0.000173198,0.000256333,0.00033254,0.00121931,0.000217075,0.000325612,0.000161651,0.000235549,0.000277116,0.000251714,0.00016627,0.000235549,0.000535758,0.000591182,0.000221693,0.00023093,0.000224002,0.000159342,0.000254023,0.000293282,0.000300209,0.000226312,0.000177816,0.0001986,0.000314065,0.000152414,0.000235549,0.000143177,0.000127012,0.000136249,0.000136249,9.69907e-05,0.000154723,0.000103919,0.000106228,0.000177816,7.38977e-05,0.000129321,8.31349e-05,6.23512e-05,0.000205528,0.000182435,0.000159342,8.54442e-05,9.69907e-05,0.000150105,0.00016627,8.08256e-05,7.85163e-05,8.08256e-05,3.69489e-05,0.000103919,8.31349e-05,8.54442e-05,0.000221693,0.000154723,0.000138558,6.92791e-05,0.000163961,7.38977e-05,7.85163e-05,0.000101609,3.46396e-05,7.15884e-05,0.000240168,4.61861e-05,4.61861e-05,0.000138558,7.15884e-05,5.3114e-05,4.38768e-05,7.38977e-05,7.15884e-05,4.15675e-05,3.92582e-05,2.3093e-05,5.54233e-05,5.77326e-05,8.31349e-05,4.38768e-05,6.23512e-05,3.23302e-05,6.69698e-05,9.69907e-05,0.00013394,2.77116e-05,1.61651e-05,4.84954e-05,2.07837e-05,4.61861e-05,3.00209e-05,4.84954e-05,2.54023e-05,2.77116e-05,3.69489e-05,2.3093e-05,5.54233e-05,2.77116e-05,3.00209e-05,5.77326e-05,2.3093e-05,1.61651e-05,1.84744e-05,1.84744e-05,1.61651e-05,2.3093e-05,3.46396e-05,6.92791e-05,2.3093e-05,3.00209e-05,1.38558e-05,0.000170888,1.15465e-05,2.54023e-05,6.69698e-05,2.3093e-05,1.84744e-05,2.3093e-05,2.3093e-05,4.15675e-05,1.84744e-05,9.23721e-06,4.61861e-06,1.38558e-05,9.23721e-06,6.92791e-06,2.77116e-05,1.84744e-05,2.07837e-05,1.61651e-05,2.07837e-05,2.07837e-05,1.84744e-05,1.84744e-05,1.38558e-05,1.38558e-05,1.84744e-05,4.61861e-06,2.54023e-05,6.92791e-06,9.23721e-06,1.38558e-05,1.15465e-05,2.07837e-05,2.77116e-05,4.61861e-06,1.61651e-05,2.77116e-05,9.23721e-06,9.23721e-06,3.46396e-05,9.23721e-06,1.38558e-05,9.23721e-06,2.07837e-05,1.84744e-05,1.15465e-05,1.38558e-05,9.23721e-06,9.23721e-06,1.38558e-05,1.38558e-05,3.46396e-05,6.92791e-06,1.84744e-05,9.23721e-06,1.84744e-05,1.15465e-05,1.61651e-05,6.92791e-06,2.77116e-05,9.23721e-06,6.92791e-06,2.07837e-05,3.92582e-05,2.3093e-05,1.15465e-05,1.61651e-05,4.61861e-06,1.38558e-05,0,1.38558e-05,0,2.3093e-05,0,2.54023e-05,0,2.07837e-05,0,9.23721e-06,0,2.3093e-05,0,9.23721e-06,0,1.61651e-05,0,9.23721e-06,0,4.61861e-06,0,1.15465e-05,0,1.15465e-05,0,9.23721e-06,0,1.15465e-05,0,3.23302e-05,0,2.3093e-06,0,9.23721e-06,0,2.07837e-05,0,2.54023e-05,0,1.15465e-05,0,1.61651e-05,0,2.3093e-06,0,2.3093e-06,0,4.61861e-06,0,1.15465e-05,0,4.61861e-06,0,2.3093e-06,0,0,0,4.61861e-06,0,4.61861e-06,0,4.61861e-06,0,6.92791e-06,0,6.92791e-06,0,0,0,6.92791e-06,0,6.92791e-06,0,4.61861e-06,0,2.3093e-06,0,4.61861e-06,0,3.23302e-05,0,2.3093e-06,0,4.61861e-06,0,2.3093e-06,0,2.3093e-06,0,2.3093e-06,0,6.92791e-06,0,2.3093e-06,0,0,0,2.3093e-06,0,1.15465e-05,0,4.61861e-06,0,6.92791e-06,0,2.3093e-06,0,2.07837e-05,0,2.3093e-06,0,4.61861e-06,0,4.61861e-06,0,1.38558e-05,0,4.61861e-06,0,9.23721e-06,0,2.3093e-06,0,2.3093e-06,0,2.3093e-06,0,1.38558e-05,0,6.92791e-06,0,2.3093e-06,0,4.61861e-06,0,6.92791e-06,0,1.61651e-05,0,0,0,6.92791e-06,0,0,0,4.61861e-06,0,1.38558e-05,0,0,0,6.92791e-06,0,6.92791e-06,0,4.61861e-06,0,2.3093e-06,0,2.3093e-06,0,4.61861e-06,0,6.92791e-06,0,1.38558e-05,0,0,0,6.92791e-06,0,2.3093e-06,0,6.92791e-06,0,4.61861e-06,0,2.3093e-06,0,6.92791e-06,0,6.92791e-06,0,4.61861e-06,0,4.61861e-06,0,0,0,4.61861e-06,0,4.61861e-06,0,4.61861e-06,0,1.15465e-05,0,0,0,9.23721e-06,0,2.3093e-06,0,2.3093e-06,0,4.61861e-06,0,0,0,0,0,2.3093e-06,0,0,0,6.92791e-06,0,0,0,4.61861e-06,0,4.61861e-06,0,4.61861e-06,0,6.92791e-06,0,2.3093e-06,0,0,0,2.3093e-06,0,2.3093e-06,0,0,0,2.3093e-06,0,2.3093e-06,0,0,0,2.3093e-06,0,9.23721e-06,0,0,0,4.61861e-06,0,2.3093e-06,0,2.3093e-06,0,6.92791e-06,0,0,2.3093e-06,0,0,1.38558e-05,0,0,4.61861e-06,0,0,4.61861e-06,0,0,2.3093e-06,0,0,6.92791e-06,0,0,9.23721e-06,0,0,2.3093e-06,0,0,2.3093e-06,0,0,4.61861e-06,0,0,4.61861e-06,0,0,4.61861e-06,0,0,6.92791e-06,0,0,4.61861e-06,0,0,4.61861e-06,0,0,4.61861e-06,0,0,4.61861e-06,0,0,2.3093e-06,0,0,1.38558e-05,0,0,4.61861e-06,0,0,0,0,0,0,0,0,2.3093e-06,0,0,1.38558e-05,0,0,2.3093e-06,0,0,4.61861e-06,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,4.61861e-06,0,0,2.3093e-06,0,0,0,0,0,2.3093e-06,0,0,2.3093e-06,0,0,2.3093e-06,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,4.61861e-06,0,0,2.3093e-06,0,0,0,0,0,4.61861e-06,0,0,2.3093e-06,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.92791e-06,0,0,2.3093e-06,0,0,0,0,0,0,0,0,2.3093e-06,0,0,6.92791e-06,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,6.92791e-06,0,0,2.3093e-06,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,2.3093e-06,0,0,2.3093e-06,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,2.3093e-06,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,2.3093e-06,0,0,0,2.3093e-06,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,2.3093e-06,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.92791e-06,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.61861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.92791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.3093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.23512e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleD.csv b/libc/benchmarks/distributions/MemcmpGoogleD.csv new file mode 100644 index 0000000000000..79f0742c1370e --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleD.csv @@ -0,0 +1 @@ +0,0,0,0.0045045,0.202703,0.0518018,0.0653153,0.256757,0.173423,0,0,0,0,0.0698198,0,0,0.00225225,0,0,0,0,0,0,0,0,0,0,0,0,0,0.130631,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00225225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00675676,0,0,0,0,0,0,0,0.0337838 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleL.csv b/libc/benchmarks/distributions/MemcmpGoogleL.csv new file mode 100644 index 0000000000000..0e5e70ce96963 --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleL.csv @@ -0,0 +1 @@ +0.000251256,0.010804,0.0263819,0.00452261,0.0434673,0.00351759,0.00326633,0.00502513,0.00452261,0.00477387,0.00301508,0.0040201,0.0361809,0.00678392,0.0130653,0.0562814,0.0261307,0.412814,0.000753769,0.0150754,0.000753769,0,0.000753769,0.190955,0.00201005,0.106784,0.000502513,0.000251256,0,0,0.000251256,0,0.00502513,0,0.000251256,0,0,0,0.000502513,0,0.00552764,0,0.000251256,0.000251256,0,0,0.000251256,0,0,0,0.00276382,0,0,0,0,0,0,0,0.00226131 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleM.csv b/libc/benchmarks/distributions/MemcmpGoogleM.csv new file mode 100644 index 0000000000000..0c164de41494d --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleM.csv @@ -0,0 +1 @@ +0,0.00941525,0.0426712,0.0476815,0.0891422,0.0520192,0.0918659,0.0583073,0.0590134,0.0685632,0.195131,0.0744813,0.0350382,0.014829,0.0123071,0.0290528,0.0136521,0.00632167,0.0303978,0.00437136,0.00830559,0.00346347,0.00867548,0.0109284,0.00403511,0.00504388,0.00147954,0.00114328,0.00245469,0.000605266,0.00127778,0.0105585,0.000470762,0.00117691,0.000100878,0.000100878,6.72518e-05,0.000201755,0.000235381,3.36259e-05,3.36259e-05,0.000100878,0,0.000336259,0.00205118,0.00151316,0.000168129,0,0,0,6.72518e-05,6.72518e-05,0,3.36259e-05,0,0,6.72518e-05,0,0,3.36259e-05,0,0,3.36259e-05,0,0,0,0,3.36259e-05,0,0,0,0,0,3.36259e-05,0.000672518,0.000100878,0,0,0,0,0,0,0,0,0,0,0,0,0,3.36259e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleQ.csv b/libc/benchmarks/distributions/MemcmpGoogleQ.csv new file mode 100644 index 0000000000000..c86450f1994c2 --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleQ.csv @@ -0,0 +1 @@ +0,0.0314232,0.0311274,0.0290179,0.0364525,0.0275002,0.0414046,0.0469741,0.106515,0.058589,0.128188,0.0227539,0.0255193,0.055026,0.0292237,0.0466139,0.0165413,0.0093125,0.0232812,0.017596,0.0106502,0.00459194,0.00873368,0.00607113,0.0121037,0.00455335,0.00641842,0.0032285,0.00617403,0.00327995,0.00370442,0.0025082,0.0111904,0.00547945,0.00173645,0.00262396,0.0191524,0.00173645,0.0023024,0.00180076,0.00918387,0.00639269,0.00182648,0.00259824,0.00300984,0.00124767,0.000810342,0.000733166,0.00124767,0.000823204,0.000694578,0.000475915,0.00275259,0.000861792,0.000887517,0.000990417,0.00050164,0.00055309,0.000578815,0.000746029,0.000385877,0.000836067,0.000334427,0.000488777,0.0325937,0.000681716,0.000437327,0.000565953,0.00127339,0.000668853,0.000347289,0.000578815,0.000630266,0.000321564,0.000514503,0.000115763,0.000128626,0.000141488,0.000115763,0.000257251,0.000321564,0.000488777,0.000115763,0.000167213,0.000334427,0.000257251,0.000102901,0.000218664,0.000938967,9.00379e-05,0.000257251,0.000270114,0.000540228,0.000192938,0.000115763,0.000180076,0.000192938,0.000437327,0.000218664,0.000205801,0.000205801,0.00055309,0.000205801,0.000115763,0.000115763,0.000128626,0.000128626,0.000141488,0.000102901,7.71754e-05,0.000141488,9.00379e-05,7.71754e-05,0.000167213,9.00379e-05,0.000102901,6.43128e-05,0.000102901,9.00379e-05,7.71754e-05,5.14503e-05,0.000115763,5.14503e-05,0.000115763,0.000167213,0.000102901,7.71754e-05,5.14503e-05,7.71754e-05,6.43128e-05,0.000141488,1.28626e-05,0.000141488,7.71754e-05,0.000115763,2.57251e-05,0.000102901,5.14503e-05,3.85877e-05,7.71754e-05,0.000128626,7.71754e-05,0.000154351,9.00379e-05,6.43128e-05,5.14503e-05,2.57251e-05,7.71754e-05,3.85877e-05,5.14503e-05,6.43128e-05,9.00379e-05,0,9.00379e-05,6.43128e-05,3.85877e-05,3.85877e-05,3.85877e-05,3.85877e-05,9.00379e-05,1.28626e-05,0,5.14503e-05,0,5.14503e-05,0,0.00055309,7.71754e-05,3.85877e-05,1.28626e-05,3.85877e-05,2.57251e-05,1.28626e-05,0,2.57251e-05,1.28626e-05,2.57251e-05,7.71754e-05,1.28626e-05,1.28626e-05,2.57251e-05,2.57251e-05,2.57251e-05,1.28626e-05,2.57251e-05,6.43128e-05,1.28626e-05,2.57251e-05,0,3.85877e-05,2.57251e-05,3.85877e-05,3.85877e-05,1.28626e-05,3.85877e-05,2.57251e-05,2.57251e-05,1.28626e-05,5.14503e-05,5.14503e-05,1.28626e-05,2.57251e-05,5.14503e-05,0.000115763,2.57251e-05,5.14503e-05,1.28626e-05,2.57251e-05,3.85877e-05,2.57251e-05,3.85877e-05,3.85877e-05,2.57251e-05,6.43128e-05,6.43128e-05,3.85877e-05,0.000900379,3.85877e-05,5.14503e-05,1.28626e-05,0.000102901,3.85877e-05,2.57251e-05,0,5.14503e-05,9.00379e-05,0,1.28626e-05,5.14503e-05,1.28626e-05,1.28626e-05,0,1.28626e-05,1.28626e-05,3.85877e-05,7.71754e-05,5.14503e-05,7.71754e-05,2.57251e-05,0,1.28626e-05,0.000180076,0,0,3.85877e-05,2.57251e-05,3.85877e-05,1.28626e-05,2.57251e-05,2.57251e-05,0,0,2.57251e-05,0,1.28626e-05,2.57251e-05,0,0,1.28626e-05,2.57251e-05,0,0,3.85877e-05,2.57251e-05,1.28626e-05,1.28626e-05,3.85877e-05,2.57251e-05,0,1.28626e-05,1.28626e-05,1.28626e-05,0,2.57251e-05,0,0.000205801,6.43128e-05,2.57251e-05,0,2.57251e-05,0,1.28626e-05,1.28626e-05,1.28626e-05,1.28626e-05,5.14503e-05,0,0,3.85877e-05,1.28626e-05,3.85877e-05,1.28626e-05,0,3.85877e-05,2.57251e-05,0,3.85877e-05,0,1.28626e-05,1.28626e-05,1.28626e-05,0,2.57251e-05,0,2.57251e-05,1.28626e-05,2.57251e-05,0,1.28626e-05,0,2.57251e-05,1.28626e-05,0,0,2.57251e-05,5.14503e-05,1.28626e-05,1.28626e-05,2.57251e-05,6.43128e-05,1.28626e-05,0,1.28626e-05,3.85877e-05,2.57251e-05,1.28626e-05,1.28626e-05,2.57251e-05,1.28626e-05,2.57251e-05,0,1.28626e-05,2.57251e-05,2.57251e-05,0,1.28626e-05,2.57251e-05,2.57251e-05,0,1.28626e-05,2.57251e-05,0,0,1.28626e-05,1.28626e-05,0,0,1.28626e-05,0,0,1.28626e-05,1.28626e-05,1.28626e-05,0,1.28626e-05,0,1.28626e-05,0,0,2.57251e-05,2.57251e-05,3.85877e-05,0,2.57251e-05,0,1.28626e-05,0,0,0,2.57251e-05,0,0,0,1.28626e-05,2.57251e-05,1.28626e-05,0,1.28626e-05,1.28626e-05,2.57251e-05,1.28626e-05,3.85877e-05,5.14503e-05,2.57251e-05,1.28626e-05,0,0,0,2.57251e-05,0,0,0,0,0,1.28626e-05,0,3.85877e-05,0,1.28626e-05,0,1.28626e-05,0,1.28626e-05,0,0,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.85877e-05,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,1.28626e-05,0,0,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,1.28626e-05,0,0,0,2.57251e-05,0,0,0,3.85877e-05,0,2.57251e-05,0,3.85877e-05,0,1.28626e-05,0,6.43128e-05,0,0.000115763,0,0,0,1.28626e-05,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,2.57251e-05,0,0,0,1.28626e-05,0,0,0,1.28626e-05,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,2.57251e-05,0,0,2.57251e-05,0,0,1.28626e-05,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,3.85877e-05,0,0,2.57251e-05,0,0,1.28626e-05,0,0,2.57251e-05,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,1.28626e-05,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,1.28626e-05,0,0,3.85877e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,1.28626e-05,0,0,0,2.57251e-05,0,0,0,1.28626e-05,0,0,0,1.28626e-05,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,3.85877e-05,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,1.28626e-05,0,0,0,5.14503e-05,0,0,0,0.000141488,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000180076,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.85877e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.57251e-05,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.28626e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleS.csv b/libc/benchmarks/distributions/MemcmpGoogleS.csv new file mode 100644 index 0000000000000..76e15a42d3e31 --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleS.csv @@ -0,0 +1 @@ +0.00214928,0.0352523,0.0327515,0.0687671,0.0433774,0.0316668,0.015748,0.0437289,0.0312048,0.0209003,0.0255604,0.0647497,0.0876085,0.0208902,0.0140808,0.0109774,0.015045,0.0386068,0.0215029,0.0297284,0.0119115,0.00948096,0.0271774,0.0134883,0.0131267,0.0328821,0.00698015,0.00331432,0.00843645,0.0049313,0.00553391,0.00373614,0.00817532,0.00382653,0.00264141,0.00452957,0.00428853,0.00267154,0.00217942,0.00280211,0.00443918,0.00230998,0.00284228,0.00249076,0.00298289,0.00263137,0.00254098,0.00235015,0.00235015,0.0014362,0.00138599,0.00179777,0.00198859,0.0164109,0.0014362,0.00151655,0.00155673,0.00144625,0.00160694,0.0028925,0.00240037,0.00233007,0.00177768,0.00185803,0.00220955,0.00124538,0.0010646,0.00107464,0.000913948,0.00141612,0.0012956,0.00122529,0.00228989,0.00383657,0.000873775,0.00107464,0.000813514,0.00124538,0.00191829,0.000813514,0.000863731,0.00123534,0.00144625,0.000843645,0.000753254,0.000612647,0.00103447,0.000974209,0.0005323,0.000763297,0.00134581,0.00146633,0.00123534,0.000994295,0.0016672,0.00178772,0.000863731,0.000843645,0.00265145,0.000863731,0.000994295,0.00227985,0.00111482,0.000522256,0.0010646,0.000843645,0.0014362,0.000582516,0.000944078,0.000713081,0.00185803,0.0018982,0.000703037,0.000411779,0.000311345,0.00065282,0.000582516,0.000421822,0.000421822,0.00191829,0.000411779,0.000351519,0.000642777,0.000833601,0.00104451,0.000944078,0.000492126,0.00147638,0.000461996,0.00131568,0.00109473,0.000662864,0.000502169,0.000381649,0.000401735,0.000431866,0.000341475,0.000251085,0.000331432,0.000261128,0.000371605,0.000502169,0.000371605,0.000220955,0.00109473,0.000291258,0.000381649,0.000200868,0.000200868,0.000311345,0.000451952,0.000803471,0.000411779,0.000170738,0.000150651,0.000291258,0.000361562,0.000311345,0.000351519,0.000301302,0.000381649,0.000241041,0.000210911,0.000311345,0.000140607,0.000261128,0.000271171,0.000582516,0.000451952,0.000472039,0.000190824,0.000321388,0.000261128,0.000170738,0.000311345,0.000321388,0.000271171,0.000341475,0.000341475,0.000281215,0.000261128,0.000200868,0.000311345,0.000140607,0.000210911,0.000200868,0.000220955,0.000170738,0.000200868,0.000291258,0.000120521,0.000130564,0.000351519,0.000251085,0.000200868,0.000251085,0.000311345,0.000170738,0.000251085,0.000230998,0.000271171,0.000130564,0.000190824,0.000160694,0.000160694,0.000130564,0.000130564,0.000130564,0.000110477,9.03905e-05,0.000160694,0.000200868,0.000210911,0.000120521,0.000100434,0.000200868,0.000100434,0.000130564,8.03471e-05,0.000130564,8.03471e-05,0.000130564,0.000180781,9.03905e-05,0.000100434,0.000120521,0.000160694,9.03905e-05,0.000120521,6.02603e-05,0.000130564,0.000130564,8.03471e-05,0.000110477,0.000110477,5.02169e-05,8.03471e-05,8.03471e-05,7.03037e-05,0.000100434,0.000100434,7.03037e-05,8.03471e-05,8.03471e-05,4.01735e-05,6.02603e-05,4.01735e-05,4.01735e-05,7.03037e-05,0.000120521,0.000110477,6.02603e-05,5.02169e-05,3.01302e-05,3.01302e-05,4.01735e-05,4.01735e-05,3.01302e-05,8.03471e-05,4.01735e-05,9.03905e-05,4.01735e-05,4.01735e-05,3.01302e-05,5.02169e-05,1.00434e-05,8.03471e-05,4.01735e-05,2.00868e-05,3.01302e-05,6.02603e-05,3.01302e-05,5.02169e-05,3.01302e-05,4.01735e-05,4.01735e-05,3.01302e-05,0,5.02169e-05,2.00868e-05,1.00434e-05,1.00434e-05,2.00868e-05,2.00868e-05,5.02169e-05,4.01735e-05,5.02169e-05,3.01302e-05,3.01302e-05,4.01735e-05,3.01302e-05,4.01735e-05,2.00868e-05,5.02169e-05,3.01302e-05,5.02169e-05,1.00434e-05,2.00868e-05,5.02169e-05,3.01302e-05,2.00868e-05,2.00868e-05,2.00868e-05,1.00434e-05,4.01735e-05,1.00434e-05,1.00434e-05,1.00434e-05,2.00868e-05,3.01302e-05,3.01302e-05,5.02169e-05,3.01302e-05,3.01302e-05,6.02603e-05,3.01302e-05,5.02169e-05,4.01735e-05,4.01735e-05,6.02603e-05,5.02169e-05,2.00868e-05,4.01735e-05,7.03037e-05,4.01735e-05,4.01735e-05,3.01302e-05,3.01302e-05,2.00868e-05,4.01735e-05,8.03471e-05,0,2.00868e-05,1.00434e-05,1.00434e-05,5.02169e-05,1.00434e-05,0,0,3.01302e-05,2.00868e-05,0,2.00868e-05,0,2.00868e-05,1.00434e-05,0,0,2.00868e-05,2.00868e-05,1.00434e-05,3.01302e-05,2.00868e-05,1.00434e-05,1.00434e-05,2.00868e-05,0,2.00868e-05,3.01302e-05,2.00868e-05,0,0,0,1.00434e-05,1.00434e-05,2.00868e-05,1.00434e-05,2.00868e-05,0,0,0,0,1.00434e-05,0,0,2.00868e-05,1.00434e-05,0,2.00868e-05,0,0,1.00434e-05,1.00434e-05,2.00868e-05,2.00868e-05,0,1.00434e-05,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,1.00434e-05,0,1.00434e-05,0,3.01302e-05,0,2.00868e-05,0,2.00868e-05,0,1.00434e-05,0,2.00868e-05,0,0,0,1.00434e-05,0,4.01735e-05,0,0,0,1.00434e-05,0,4.01735e-05,0,0,0,2.00868e-05,0,3.01302e-05,0,1.00434e-05,0,1.00434e-05,0,1.00434e-05,0,0,0,2.00868e-05,0,2.00868e-05,0,0,0,1.00434e-05,0,1.00434e-05,0,0,0,1.00434e-05,0,0,0,2.00868e-05,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,3.01302e-05,0,0,0,1.00434e-05,0,2.00868e-05,0,0,0,0,0,2.00868e-05,0,0,0,0,0,0,0,1.00434e-05,0,1.00434e-05,0,0,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,1.00434e-05,0,0,0,2.00868e-05,0,0,0,0,0,0,0,0,0,1.00434e-05,0,1.00434e-05,0,1.00434e-05,0,1.00434e-05,0,0,0,1.00434e-05,0,0,0,2.00868e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.00434e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleU.csv b/libc/benchmarks/distributions/MemcmpGoogleU.csv new file mode 100644 index 0000000000000..0ad426d06217d --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleU.csv @@ -0,0 +1 @@ +4.16047e-05,0.00196299,0.00379738,0.00833986,0.00673618,0.00467108,0.00371417,0.00588896,0.050111,0.00615372,0.0267632,0.00641848,0.0281059,0.00639956,0.00497366,0.00667945,0.206968,0.00516655,0.00436093,0.00450088,0.0214189,0.0066265,0.0495096,0.00180035,0.0801232,0.00240551,0.0134156,0.002727,0.00136161,0.00292368,0.0151403,0.00225422,0.0478833,0.000718627,0.00900175,0.00518168,0.00131622,0.00611968,0.00177387,0.000979602,0.000695934,0.0241232,0.00112711,0.157028,0.000321491,0.0477395,0.00290477,0.00170201,0.00743968,0.000851006,0.00172471,0.00132,0.00186843,0.00287829,0.00202729,0.00301823,0.00138809,0.00100608,0.0150155,0.000582466,0.00622558,0.0257117,0.00275726,0.00715223,0.00163015,0.00133892,0.00145617,0.000196677,0.000359314,0.000544644,0.000347967,0.00105903,0.000669458,0.000332838,0.000404701,0.000885046,0.000934215,0.00057112,0.000279886,0.00126705,0.000136161,0.000677022,9.83385e-05,0.000400918,0.000661893,0.000242064,0.000162637,0.000102121,0.000189112,0.000147508,0.000279886,4.16047e-05,5.29515e-05,5.29515e-05,6.42982e-05,1.13467e-05,0.000272322,0.000162637,0.000147508,7.18627e-05,9.45562e-05,1.89112e-05,2.64757e-05,2.64757e-05,7.5645e-06,6.0516e-05,9.0774e-05,4.91692e-05,3.78225e-06,5.29515e-05,3.0258e-05,1.89112e-05,0,0.000332838,7.5645e-06,0.000136161,3.78225e-06,7.5645e-06,0.000359314,0,6.80805e-05,7.5645e-06,3.78225e-06,0,3.78225e-06,1.5129e-05,7.5645e-06,0,0,1.89112e-05,1.89112e-05,3.78225e-06,2.26935e-05,3.78225e-06,7.5645e-06,0,4.5387e-05,0.000242064,2.64757e-05,8.32095e-05,0,5.29515e-05,7.5645e-06,7.5645e-06,3.78225e-06,1.5129e-05,1.13467e-05,3.78225e-06,7.5645e-06,7.5645e-06,1.89112e-05,7.5645e-06,1.5129e-05,1.89112e-05,2.26935e-05,3.78225e-05,3.78225e-06,1.13467e-05,3.0258e-05,2.26935e-05,3.78225e-06,7.5645e-06,2.26935e-05,3.78225e-06,3.78225e-06,4.16047e-05,3.40402e-05,1.5129e-05,2.26935e-05,7.5645e-06,1.89112e-05,0,7.5645e-06,0,3.78225e-06,7.5645e-06,3.78225e-06,0,1.13467e-05,0,1.5129e-05,2.26935e-05,0,1.89112e-05,0,3.78225e-06,7.5645e-06,0,0,3.78225e-06,0,0,0,3.78225e-06,0,0,0,2.64757e-05,0,3.78225e-06,1.89112e-05,0,0,0,0,0,0,0,7.5645e-06,0,0,0,0,0,0,0,0,3.78225e-06,0,0,3.78225e-06,0,0,0,0,0,3.78225e-06,0,3.78225e-06,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,3.78225e-06,0,3.78225e-06,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,3.78225e-06,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.78225e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.0516e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcmpGoogleW.csv b/libc/benchmarks/distributions/MemcmpGoogleW.csv new file mode 100644 index 0000000000000..6fe7ef6f348cd --- /dev/null +++ b/libc/benchmarks/distributions/MemcmpGoogleW.csv @@ -0,0 +1 @@ +0,0.028169,0.112676,0.112676,0.169014,0.112676,0.084507,0.0352113,0.0774648,0.00704225,0.0211268,0.0140845,0.0352113,0.0140845,0.0140845,0,0.00704225,0.0140845,0.0211268,0.00704225,0,0.0140845,0.00704225,0.00704225,0.0140845,0.00704225,0.00704225,0,0,0,0.00704225,0.00704225,0,0,0,0,0,0,0,0,0.00704225,0,0.00704225,0,0,0.00704225,0,0,0,0,0.00704225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00704225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00704225 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleA.csv b/libc/benchmarks/distributions/MemcpyGoogleA.csv new file mode 100644 index 0000000000000..180df4065357a --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleA.csv @@ -0,0 +1 @@ +0.00655738,0.0571632,0.0228558,0.0106201,0.0187693,0.00639107,0.022737,0.0145165,0.0356617,0.00981231,0.00760276,0.0107151,0.0172012,0.00791162,0.032288,0.00508434,0.0879544,0.00955096,0.00862438,0.00601093,0.005512,0.0129247,0.005512,0.0231409,0.0390116,0.00392017,0.00563079,0.003445,0.00263721,0.00261345,0.00484676,0.00472796,0.0289142,0.00116417,0.000902827,0.00114041,0.00187693,0.000926586,0.00104538,0.000570207,0.00142552,0.00149679,0.000261345,0.000356379,0.000451414,0.000451414,0.000689,0.0167261,0.00154431,0.000593965,0.00216203,0.00819672,0.00596341,0.000546448,0.000665241,0.000879069,0.0023521,0.000451414,0.000285103,0.000593965,0.000760276,0.00168686,0.000213828,0.000356379,0.01713,0.000261345,0.000285103,9.50344e-05,0.000997862,0.0016631,0.000213828,0.000213828,0.000879069,0.00470421,0.000403896,0.000118793,0.000427655,0.000522689,0.000142552,0.000308862,0.000522689,0.000142552,0.00016631,0.000403896,0.000190069,0.000665241,0.000213828,2.37586e-05,0.00118793,0.000142552,2.37586e-05,0.000142552,0.000285103,0.000142552,0.000997862,0.000118793,0.000261345,0,0.000118793,2.37586e-05,0.000285103,0,4.75172e-05,4.75172e-05,0.000190069,0.000118793,0.000118793,2.37586e-05,7.12758e-05,2.37586e-05,9.50344e-05,2.37586e-05,0.000285103,4.75172e-05,0.00016631,0.000190069,0.000118793,0,0.00016631,4.75172e-05,0.000332621,4.75172e-05,9.50344e-05,0,2.37586e-05,2.37586e-05,9.50344e-05,0,0.00869565,0,4.75172e-05,2.37586e-05,2.37586e-05,2.37586e-05,0,2.37586e-05,0.000807793,2.37586e-05,4.75172e-05,0,0.000190069,2.37586e-05,0,0,0.000213828,2.37586e-05,0,0,7.12758e-05,4.75172e-05,9.50344e-05,0,0.000285103,0,0,0.000118793,0.000118793,0,0,0,0.000261345,0,0,0,0,0.000261345,0,0.000118793,0.000475172,0.000190069,2.37586e-05,0.000308862,0,0,9.50344e-05,0,9.50344e-05,7.12758e-05,0,0,0,0,0,4.75172e-05,0.00140176,4.75172e-05,0,2.37586e-05,0,4.75172e-05,0,0,0.000118793,0,0,4.75172e-05,0,0,0,2.37586e-05,0.00016631,0,0,0,2.37586e-05,0,0,2.37586e-05,9.50344e-05,4.75172e-05,2.37586e-05,0,2.37586e-05,0,2.37586e-05,2.37586e-05,4.75172e-05,2.37586e-05,2.37586e-05,2.37586e-05,0,2.37586e-05,0,0,7.12758e-05,0,0,0,0,2.37586e-05,2.37586e-05,0,4.75172e-05,0,0,0,2.37586e-05,2.37586e-05,2.37586e-05,0,0.000118793,0,0,0,0,0,2.37586e-05,0,0.000118793,0,0,2.37586e-05,0,0,7.12758e-05,4.75172e-05,0.0109527,0,2.37586e-05,4.75172e-05,0,0,2.37586e-05,0,2.37586e-05,0,2.37586e-05,0,0,0,0,4.75172e-05,0.000308862,2.37586e-05,2.37586e-05,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,4.75172e-05,2.37586e-05,0,0,0,0,2.37586e-05,2.37586e-05,2.37586e-05,0,0,4.75172e-05,4.75172e-05,0,0,0,0.31808,4.75172e-05,2.37586e-05,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,2.37586e-05,0,0,0,2.37586e-05,4.75172e-05,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,4.75172e-05,0,0.000213828,0,2.37586e-05,0,0,0,0,0,4.75172e-05,0,0,2.37586e-05,2.37586e-05,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,7.12758e-05,0,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,7.12758e-05,2.37586e-05,7.12758e-05,2.37586e-05,0,0,2.37586e-05,2.37586e-05,0,0,9.50344e-05,0,2.37586e-05,0,0,0,2.37586e-05,0,2.37586e-05,0,0,0,0,0,0,0,0.00130672,0,0,0,0,0,0,0,2.37586e-05,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0.000142552,0,0,0,0,0,0,0,2.37586e-05,0,7.12758e-05,0,2.37586e-05,0,0,0,4.75172e-05,0,2.37586e-05,0,4.75172e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,4.75172e-05,0,0,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0.000118793,0,2.37586e-05,0,2.37586e-05,0,2.37586e-05,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,7.12758e-05,0,0,0,4.75172e-05,0,7.12758e-05,0,2.37586e-05,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0.00342124,0,0,0,0,0,2.37586e-05,0,2.37586e-05,0,0,0,0,0,4.75172e-05,0,7.12758e-05,0,0,0,4.75172e-05,0,2.37586e-05,0,2.37586e-05,0,0,0,0,0,2.37586e-05,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0.000142552,0,0,0,2.37586e-05,0,0,0,0.000356379,0,0,0,0,0,0,0,2.37586e-05,0,2.37586e-05,0,0.000261345,0,0,0,2.37586e-05,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,2.37586e-05,0,2.37586e-05,0,2.37586e-05,0,0,0,7.12758e-05,0,2.37586e-05,0,0,0,0,0,0,0,4.75172e-05,0,4.75172e-05,0,0,0,2.37586e-05,0,7.12758e-05,0,0,0,0,0,0,0,0,9.50344e-05,0,0,0,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,0,0,4.75172e-05,0,0,0,0,0,0.000118793,0,0,2.37586e-05,0,0,2.37586e-05,0,0,0,0,0,0,0,0,7.12758e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,0,0,4.75172e-05,0,0,2.37586e-05,0,0,2.37586e-05,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.50344e-05,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,2.37586e-05,0,0,4.75172e-05,0,0,0,0,0,0,0,0,7.12758e-05,0,0,0,0,0,2.37586e-05,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,0,0,0,0,0,2.37586e-05,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,4.75172e-05,0,0,0,0,0,0,0,9.50344e-05,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,2.37586e-05,0,0,0,4.75172e-05,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,4.75172e-05,0,0,0,2.37586e-05,0,0,0,0.0016631,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,7.12758e-05,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,2.37586e-05,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.50344e-05,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.50344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0.000807793,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,7.12758e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.75172e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.37586e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.50344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00299359,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000641483 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleB.csv b/libc/benchmarks/distributions/MemcpyGoogleB.csv new file mode 100644 index 0000000000000..94c7821d7c6aa --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleB.csv @@ -0,0 +1 @@ +0.0141256,0.0301416,0.0298994,0.0485031,0.0294357,0.0142053,0.0218855,0.0112957,0.0156025,0.00679989,0.00921323,0.00771855,0.0116059,0.0192979,0.0104361,0.0088115,0.0175846,0.0149586,0.02307,0.0263075,0.0183556,0.0334589,0.0250402,0.0170293,0.00839795,0.0113696,0.00744679,0.00857223,0.0183644,0.0108379,0.0124507,0.0112042,0.0145391,0.0218766,0.00934615,0.0104598,0.00983946,0.00958247,0.0112987,0.00836546,0.00606437,0.00622978,0.00515161,0.00610867,0.00679398,0.00703325,0.00536134,0.00416501,0.00394642,0.0071514,0.00335564,0.00437178,0.00430975,0.00628,0.00344721,0.00485326,0.004614,0.00354764,0.00356536,0.0034797,0.00354764,0.00384598,0.00331133,0.00422704,0.00475579,0.00448993,0.00279735,0.00246356,0.00417091,0.00391097,0.00573057,0.00547063,0.00266147,0.00333791,0.00524613,0.00559174,0.00503641,0.00472034,0.00266147,0.00199979,0.0026467,0.00281802,0.00488871,0.00624455,0.00456674,0.00396709,0.00472625,0.00460218,0.00370715,0.00207955,0.00124359,0.00148581,0.00235722,0.00184619,0.00127904,0.00153308,0.00122882,0.00239562,0.00314591,0.00195844,0.00124655,0.00114907,0.00172508,0.0032168,0.00143855,0.00105159,0.0017812,0.001474,0.00148581,0.00201161,0.00182551,0.00159806,0.00108999,0.000759153,0.00103387,0.00142674,0.00080937,0.0013588,0.00107818,0.00141197,0.00125836,0.00118747,0.00133221,0.00115793,0.00237494,0.00139129,0.000874356,0.000738476,0.00294209,0.00185505,0.0011343,0.00147991,0.00207364,0.00252559,0.000437178,0.000995466,0.000995466,0.000513979,0.000472625,0.000460809,0.00103387,0.000700075,0.000348561,0.000472625,0.00131744,0.000968881,0.000534657,0.000691214,0.00049921,0.000537611,0.000744384,0.000472625,0.000522841,0.000304252,0.000333791,0.000460809,0.000351515,0.000345607,0.00036333,0.000351515,0.000508072,0.000339699,0.000381054,0.000493302,0.000339699,0.00055238,0.000280621,0.000321976,0.000330837,0.000262897,0.000262897,0.000410593,0.000511025,0.000236312,0.000324929,0.000351515,0.000319022,0.000425362,0.000224497,0.000316068,0.000259944,0.000239266,0.000292437,0.000389915,0.000212681,0.000227451,0.000218589,0.000200865,0.000271759,0.000298344,0.000180188,0.00018905,0.000194958,0.000162465,0.000150649,0.000531703,0.000221543,0.000159511,0.000206773,0.000319022,0.000259944,0.000192004,0.000333791,0.000153603,0.00018905,0.000215635,0.000162465,0.000578965,0.000209727,0.000209727,0.000180188,0.000206773,0.000186096,0.00017428,0.000153603,0.000147695,0.000268805,0.000543518,0.000147695,0.00017428,0.000168373,0.000129972,0.00017428,0.000192004,0.000144741,0.000209727,0.000138834,0.000227451,0.000124064,0.000141787,0.00013588,0.000100433,0.000289483,9.45249e-05,0.000132926,0.00013588,7.68015e-05,0.000109294,0.000180188,0.000206773,0.000218589,7.97554e-05,7.38476e-05,0.00013588,0.000192004,0.000103387,0.000171326,9.45249e-05,9.1571e-05,0.000109294,8.86171e-05,0.00013588,0.000106341,8.27093e-05,0.000162465,8.56632e-05,0.00106341,0.000109294,7.97554e-05,0.000127018,3.54469e-05,7.08937e-05,0.000124064,9.1571e-05,0.00013588,6.2032e-05,8.86171e-05,9.1571e-05,0.000141787,7.97554e-05,5.31703e-05,0.000183142,0.00012111,8.27093e-05,6.49859e-05,0.000103387,5.02164e-05,0.000106341,7.97554e-05,7.08937e-05,0.000132926,7.08937e-05,5.61242e-05,7.08937e-05,7.38476e-05,7.38476e-05,8.56632e-05,3.24929e-05,5.90781e-05,9.1571e-05,7.38476e-05,5.61242e-05,0.000768015,6.49859e-05,6.2032e-05,7.97554e-05,0.000543518,5.61242e-05,3.24929e-05,0.000150649,5.02164e-05,3.54469e-05,7.08937e-05,5.61242e-05,6.49859e-05,4.43086e-05,4.13547e-05,8.27093e-05,3.84008e-05,0.000103387,5.61242e-05,3.54469e-05,4.43086e-05,4.43086e-05,4.72625e-05,4.72625e-05,3.54469e-05,5.90781e-05,4.43086e-05,0.00012111,6.49859e-05,3.84008e-05,5.61242e-05,0.000118156,6.79398e-05,4.13547e-05,3.54469e-05,2.36312e-05,6.49859e-05,8.86171e-05,5.61242e-05,4.43086e-05,3.54469e-05,5.61242e-05,3.24929e-05,2.9539e-05,2.9539e-05,3.24929e-05,2.06773e-05,5.61242e-05,0.000144741,3.84008e-05,3.54469e-05,5.31703e-05,3.84008e-05,4.13547e-05,4.72625e-05,4.43086e-05,2.9539e-05,3.84008e-05,5.02164e-05,8.56632e-05,5.61242e-05,4.43086e-05,5.02164e-05,9.45249e-05,3.84008e-05,3.54469e-05,4.13547e-05,6.2032e-05,2.06773e-05,2.9539e-05,5.90781e-05,3.84008e-05,3.84008e-05,3.24929e-05,3.24929e-05,3.54469e-05,5.90781e-05,4.13547e-05,3.84008e-05,3.54469e-05,2.65851e-05,3.84008e-05,6.49859e-05,4.72625e-05,3.84008e-05,4.43086e-05,4.13547e-05,3.24929e-05,4.13547e-05,3.24929e-05,3.54469e-05,2.06773e-05,8.56632e-05,0,7.08937e-05,0,6.79398e-05,0,6.49859e-05,0,5.61242e-05,0,0.000100433,0,2.36312e-05,0,7.38476e-05,0,7.08937e-05,0,8.86171e-05,0,6.2032e-05,0,6.79398e-05,0,6.79398e-05,0,7.68015e-05,0,0.000100433,0,5.61242e-05,0,9.74788e-05,0,7.68015e-05,0,5.61242e-05,0,6.49859e-05,0,9.45249e-05,0,6.2032e-05,0,6.2032e-05,0,5.31703e-05,0,4.72625e-05,0,0.000141787,0,7.08937e-05,0,9.1571e-05,0,6.2032e-05,0,2.36312e-05,0,6.49859e-05,0,4.72625e-05,0,6.49859e-05,0,4.13547e-05,0,8.56632e-05,0,5.90781e-05,0,3.54469e-05,0,6.49859e-05,0,2.9539e-05,0,5.61242e-05,0,5.90781e-05,0,0.000118156,0,0.000100433,0,4.43086e-05,0,2.36312e-05,0,3.84008e-05,0,4.43086e-05,0,4.43086e-05,0,9.1571e-05,0,7.68015e-05,0,4.43086e-05,0,5.31703e-05,0,3.24929e-05,0,3.24929e-05,0,3.84008e-05,0,3.54469e-05,0,3.84008e-05,0,6.79398e-05,0,2.65851e-05,0,1.77234e-05,0,3.84008e-05,0,3.84008e-05,0,3.24929e-05,0,5.90781e-05,0,0.000159511,0,7.97554e-05,0,2.06773e-05,0,2.06773e-05,0,2.65851e-05,0,3.24929e-05,0,8.86171e-05,0,5.02164e-05,0,4.13547e-05,0,1.18156e-05,0,3.54469e-05,0,2.36312e-05,0,2.9539e-05,0,1.77234e-05,0,3.84008e-05,0,3.84008e-05,0,3.84008e-05,0,1.77234e-05,0,2.65851e-05,0,2.06773e-05,0,2.65851e-05,0,4.13547e-05,0,2.06773e-05,0,2.65851e-05,0,1.77234e-05,0,0.00012111,0,3.54469e-05,0,4.13547e-05,0,5.61242e-05,0,2.36312e-05,0,7.68015e-05,0,2.06773e-05,0,0.000345607,0,2.65851e-05,0,4.72625e-05,0,2.65851e-05,0,2.9539e-05,0,2.9539e-05,0,1.77234e-05,0,3.54469e-05,0,2.36312e-05,0,4.13547e-05,0,3.54469e-05,0,2.9539e-05,0,1.77234e-05,0,2.36312e-05,0,2.9539e-05,0,1.18156e-05,0,1.77234e-05,0,2.36312e-05,0,2.65851e-05,0,3.54469e-05,0,3.54469e-05,0,2.9539e-05,0,2.36312e-05,0,2.36312e-05,0,1.47695e-05,0,0.000112248,0,2.65851e-05,0,2.36312e-05,0,2.06773e-05,0,2.9539e-05,0,1.18156e-05,0,1.47695e-05,0,2.65851e-05,0,0,5.31703e-05,0,0,3.84008e-05,0,0,1.47695e-05,0,0,3.24929e-05,0,0,2.65851e-05,0,0,1.18156e-05,0,0,1.47695e-05,0,0,4.43086e-05,0,0,2.65851e-05,0,0,1.77234e-05,0,0,2.36312e-05,0,0,1.47695e-05,0,0,2.36312e-05,0,0,2.65851e-05,0,0,2.9539e-05,0,0,2.06773e-05,0,0,8.86171e-05,0,0,2.36312e-05,0,0,2.06773e-05,0,0,1.47695e-05,0,0,1.47695e-05,0,0,2.9539e-05,0,0,2.65851e-05,0,0,2.65851e-05,0,0,1.77234e-05,0,0,1.47695e-05,0,0,2.36312e-05,0,0,2.36312e-05,0,0,2.65851e-05,0,0,3.54469e-05,0,0,1.18156e-05,0,0,2.65851e-05,0,0,1.77234e-05,0,0,3.24929e-05,0,0,1.77234e-05,0,0,1.47695e-05,0,0,8.86171e-06,0,0,9.1571e-05,0,0,4.43086e-05,0,0,1.18156e-05,0,0,1.47695e-05,0,0,2.06773e-05,0,0,2.36312e-05,0,0,2.06773e-05,0,0,3.24929e-05,0,0,1.77234e-05,0,0,2.06773e-05,0,0,3.24929e-05,0,0,1.77234e-05,0,0,1.47695e-05,0,0,2.06773e-05,0,0,1.18156e-05,0,0,8.86171e-06,0,0,2.65851e-05,0,0,1.18156e-05,0,0,1.18156e-05,0,0,5.90781e-06,0,0,2.06773e-05,0,0,1.47695e-05,0,0,1.77234e-05,0,0,1.18156e-05,0,0,3.24929e-05,0,0,1.77234e-05,0,0,2.9539e-05,0,0,1.18156e-05,0,0,2.06773e-05,0,0,1.18156e-05,0,0,3.54469e-05,0,0,0,0,0,8.86171e-06,0,0,2.36312e-05,0,0,5.90781e-06,0,0,5.90781e-06,0,0,1.47695e-05,0,0,2.65851e-05,0,0,5.90781e-06,0,0,1.18156e-05,0,0,1.18156e-05,0,0,8.86171e-06,0,0,3.24929e-05,0,0,0.000106341,0,0,8.86171e-06,0,0,5.90781e-06,0,0,1.47695e-05,0,0,2.9539e-06,0,0,1.18156e-05,0,0,0,2.06773e-05,0,0,0,4.43086e-05,0,0,0,2.65851e-05,0,0,0,1.47695e-05,0,0,0,3.54469e-05,0,0,0,2.36312e-05,0,0,0,2.06773e-05,0,0,0,2.06773e-05,0,0,0,2.36312e-05,0,0,0,2.06773e-05,0,0,0,1.47695e-05,0,0,0,2.65851e-05,0,0,0,3.24929e-05,0,0,0,1.47695e-05,0,0,0,2.36312e-05,0,0,0,8.86171e-06,0,0,0,4.13547e-05,0,0,0,5.90781e-06,0,0,0,8.86171e-06,0,0,0,1.18156e-05,0,0,0,2.06773e-05,0,0,0,3.24929e-05,0,0,0,2.65851e-05,0,0,0,8.86171e-06,0,0,0,3.24929e-05,0,0,0,2.06773e-05,0,0,0,1.77234e-05,0,0,0,5.31703e-05,0,0,0,1.47695e-05,0,0,0,1.18156e-05,0,0,0,0.000640997,0,0,0,3.84008e-05,0,0,0,2.06773e-05,0,0,0,1.18156e-05,0,0,0,0.00012111,0,0,0,5.90781e-06,0,0,0,8.86171e-06,0,0,0,0,0,0,0,2.9539e-06,0,0,0,5.90781e-06,0,0,0,1.47695e-05,0,0,0,5.90781e-06,0,0,0,2.9539e-06,0,0,0,5.90781e-06,0,0,0,1.47695e-05,0,0,0,5.90781e-06,0,0,0,2.9539e-06,0,0,0,5.90781e-06,0,0,0,0,0,0,0,8.86171e-06,0,0,0,5.90781e-06,0,0,0,8.86171e-06,0,0,0,5.90781e-06,0,0,0,8.86171e-06,0,0,0,5.90781e-06,0,0,0,5.90781e-06,0,0,0,8.86171e-06,0,0,0,1.47695e-05,0,0,0,8.86171e-06,0,0,0,5.02164e-05,0,0,0,2.36312e-05,0,0,0,2.06773e-05,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,2.9539e-06,0,0,0,0,5.90781e-06,0,0,0,0,3.54469e-05,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,5.90781e-06,0,0,0,0,5.90781e-06,0,0,0,0,2.36312e-05,0,0,0,0,1.47695e-05,0,0,0,0,8.86171e-06,0,0,0,0,5.90781e-06,0,0,0,0,8.86171e-06,0,0,0,0,5.90781e-06,0,0,0,0,1.18156e-05,0,0,0,0,2.9539e-06,0,0,0,0,5.90781e-06,0,0,0,0,1.18156e-05,0,0,0,0,2.9539e-06,0,0,0,0,2.9539e-06,0,0,0,0,8.86171e-06,0,0,0,0,6.49859e-05,0,0,0,0,5.90781e-06,0,0,0,0,1.77234e-05,0,0,0,0,8.86171e-06,0,0,0,0,2.9539e-06,0,0,0,0,2.9539e-06,0,0,0,0,1.18156e-05,0,0,0,0,2.9539e-06,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,1.77234e-05,0,0,0,0,5.90781e-06,0,0,0,0,5.90781e-06,0,0,0,0,2.9539e-06,0,0,0,0,5.90781e-06,0,0,0,0,8.86171e-06,0,0,0,0,1.47695e-05,0,0,0,0,2.9539e-06,0,0,0,0,8.86171e-06,0,0,0,0,1.18156e-05,0,0,0,0,2.9539e-06,0,0,0,0,5.90781e-06,0,0,0,0,8.86171e-06,0,0,0,0,5.90781e-06,0,0,0,0,4.13547e-05,0,0,0,0,2.9539e-06,0,0,0,0,2.06773e-05,0,0,0,0,1.47695e-05,0,0,0,0,0,2.9539e-06,0,0,0,0,0,1.18156e-05,0,0,0,0,0,2.9539e-06,0,0,0,0,0,1.18156e-05,0,0,0,0,0,5.90781e-06,0,0,0,0,0,5.90781e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,5.90781e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,5.90781e-06,0,0,0,0,0,1.47695e-05,0,0,0,0,0,1.18156e-05,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.77234e-05,0,0,0,0,0,2.9539e-06,0,0,0,0,0,1.77234e-05,0,0,0,0,0,8.86171e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,5.90781e-06,0,0,0,0,0,2.9539e-06,0,0,0,0,0,5.90781e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,1.47695e-05,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,5.90781e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,8.86171e-06,0,0,0,0,0,2.9539e-06,0,0,0,0,0,1.47695e-05,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,1.77234e-05,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,2.9539e-05,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000307206,0,0,0,0,0,0,0,6.49859e-05,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,1.77234e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,7.08937e-05,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,4.43086e-05,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,2.06773e-05,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.77234e-05,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.06773e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.77234e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.86171e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.90781e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.9539e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.18156e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00153898,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.47695e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleD.csv b/libc/benchmarks/distributions/MemcpyGoogleD.csv new file mode 100644 index 0000000000000..8424242f61f8c --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleD.csv @@ -0,0 +1 @@ +0.0234987,0.0137076,0.0104439,0.0117493,0.022846,0.017624,0.0672324,0.0372063,0.0391645,0.0372063,0.0248042,0.0456919,0.0267624,0.0359008,0.0156658,0.00522193,0.0306789,0.0124021,0.0104439,0.0137076,0.00261097,0.0150131,0.0365535,0.00391645,0.00652742,0.0443864,0.0163185,0.0430809,0.00587467,0.0169713,0.0110966,0.00130548,0.0293734,0,0.000652742,0.00195822,0.0248042,0.00391645,0.00979112,0.000652742,0.0365535,0.000652742,0.00130548,0.000652742,0.000652742,0.000652742,0.00913838,0,0.000652742,0,0,0.000652742,0,0,0.00130548,0,0.0163185,0.000652742,0.000652742,0.000652742,0,0,0.000652742,0,0.00913838,0.000652742,0,0,0.000652742,0,0,0,0.00130548,0,0.000652742,0,0,0.00130548,0,0,0,0,0,0,0,0.00261097,0,0.00913838,0.0300261,0,0,0,0,0,0,0,0,0,0,0,0,0.00195822,0,0,0.00130548,0.000652742,0.00456919,0,0,0,0,0,0,0.00130548,0.0130548,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00261097,0,0,0,0,0.000652742,0,0,0.00326371,0,0.00130548,0,0,0,0.000652742,0,0.00130548,0,0,0,0,0,0,0,0.00130548,0,0,0,0,0,0.000652742,0,0.00195822,0,0.000652742,0,0,0,0,0,0.00130548,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0.000652742,0,0,0,0,0,0,0,0.00195822,0,0,0,0.000652742,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0.00130548,0,0,0,0,0,0.000652742,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0.000652742,0,0.000652742,0,0,0,0,0,0,0.00326371,0,0,0.000652742,0.000652742,0,0,0,0,0.000652742,0,0,0,0.000652742,0,0.000652742,0.00195822,0.00195822,0,0,0,0,0,0,0,0.00130548,0,0,0,0,0,0.000652742,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0.00130548,0,0,0,0,0,0.000652742,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0.000652742,0,0,0,0,0,0,0.000652742,0.000652742,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0.000652742,0.000652742,0,0.00326371,0,0,0,0,0,0.00261097,0.000652742,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0.000652742,0,0,0,0,0,0,0,0.000652742,0,0.000652742,0,0.000652742,0,0.000652742,0,0.000652742,0,0.00130548,0,0.000652742,0,0.00130548,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0.00130548,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0.000652742,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0.000652742,0,0.00130548,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0.000652742,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00130548 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleL.csv b/libc/benchmarks/distributions/MemcpyGoogleL.csv new file mode 100644 index 0000000000000..398d0c2deb92a --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleL.csv @@ -0,0 +1 @@ +0.0410454,0.377231,0.201702,0.0243191,0.0111213,0.0109773,0.00850557,0.0113448,0.0235075,0.0234799,0.011645,0.0144445,0.00936011,0.0106159,0.0104137,0.00545496,0.0102637,0.0152316,0.00527425,0.0118686,0.0105944,0.00799407,0.00506904,0.00563873,0.00789912,0.00645958,0.00419306,0.00293116,0.00327726,0.00272288,0.00275351,0.00313637,0.0022849,0.00236759,0.00214707,0.00221445,0.001559,0.00267694,0.00148243,0.00140892,0.00145792,0.00205212,0.0014518,0.0010965,0.0011547,0.00117614,0.000732024,0.00113938,0.000912733,0.00107506,0.00102912,0.00101074,0.000698333,0.00110263,0.000624824,0.000924984,0.00084535,0.000765716,0.000998493,0.000777967,0.000486995,0.000860664,0.000741213,0.00075959,0.000437989,0.000787156,0.000578881,0.00067383,0.000514561,0.000382858,0.000376732,0.000465555,0.000312412,0.00025728,0.000385921,0.000324663,0.000367543,0.000358355,0.000349166,0.000284846,0.000486995,0.000499247,0.000401235,0.00027872,0.00030016,0.000315475,0.000260343,0.000315475,0.000324663,0.000287909,0.000186835,0.000251155,0.000269532,0.000238903,0.000539064,0.000327726,0.000238903,0.000183772,0.000312412,0.000263406,0.00019296,0.000514561,0.000266469,0.000174583,0.00015008,0.000248092,0.00030016,0.000137829,0.000238903,0.000137829,0.000407361,0.000223589,0.000251155,0.000183772,0.000392046,0.00017152,0.000226652,0.000220526,0.000174583,0.0001072,0.000241966,0.000180709,0.000275658,0.000168457,0.000208275,0.000186835,0.000217463,0.000165395,0.000220526,7.35087e-05,0.00017152,0.000168457,0.000186835,0.000147017,0.00015008,0.000165395,0.0001072,0.000147017,0.000189897,0.000165395,0.000122514,0.00017152,0.000147017,0.000153143,0.00017152,0.000174583,0.000159269,0.0001072,8.57601e-05,0.0001072,0.000147017,0.000140892,0.000116389,8.57601e-05,9.49487e-05,0.000104137,7.35087e-05,6.7383e-05,6.43201e-05,6.7383e-05,8.26973e-05,0.000113326,0.000125577,9.49487e-05,4.28801e-05,0.000125577,5.81944e-05,7.96344e-05,0.000104137,8.8823e-05,0.000116389,0.0001072,0.000113326,7.96344e-05,0.000113326,0.0001072,6.12572e-05,9.80116e-05,6.7383e-05,8.57601e-05,6.7383e-05,7.35087e-05,0.000104137,7.35087e-05,7.65716e-05,8.57601e-05,0.000131703,8.8823e-05,7.65716e-05,0.00012864,6.7383e-05,8.8823e-05,7.35087e-05,7.96344e-05,6.12572e-05,7.04458e-05,9.80116e-05,8.8823e-05,4.59429e-05,4.90058e-05,6.7383e-05,0.0001072,0.000116389,3.67543e-05,7.35087e-05,5.20687e-05,0.000101074,8.57601e-05,7.35087e-05,9.49487e-05,8.8823e-05,6.12572e-05,7.96344e-05,7.96344e-05,8.8823e-05,4.90058e-05,0.000122514,7.96344e-05,4.90058e-05,5.51315e-05,6.12572e-05,5.20687e-05,5.51315e-05,7.65716e-05,6.7383e-05,4.28801e-05,3.98172e-05,5.51315e-05,7.96344e-05,7.35087e-05,9.18859e-05,3.98172e-05,5.81944e-05,7.04458e-05,7.65716e-05,5.20687e-05,6.43201e-05,3.98172e-05,6.43201e-05,4.90058e-05,4.90058e-05,5.81944e-05,4.28801e-05,5.51315e-05,2.75658e-05,3.06286e-05,6.7383e-05,3.67543e-05,6.43201e-05,6.43201e-05,4.28801e-05,5.81944e-05,5.20687e-05,3.67543e-05,5.51315e-05,7.04458e-05,0.00143342,5.51315e-05,7.04458e-05,7.04458e-05,0.000232778,6.7383e-05,8.26973e-05,3.36915e-05,3.67543e-05,3.36915e-05,3.06286e-05,4.90058e-05,4.59429e-05,3.36915e-05,4.90058e-05,7.65716e-05,6.43201e-05,2.75658e-05,3.67543e-05,2.75658e-05,4.28801e-05,2.45029e-05,4.90058e-05,3.98172e-05,4.59429e-05,6.7383e-05,5.81944e-05,4.59429e-05,3.67543e-05,4.28801e-05,2.75658e-05,5.81944e-05,3.36915e-05,4.90058e-05,3.98172e-05,3.06286e-05,4.90058e-05,3.98172e-05,5.51315e-05,4.59429e-05,3.67543e-05,3.98172e-05,6.7383e-05,5.20687e-05,3.36915e-05,4.28801e-05,3.67543e-05,2.75658e-05,3.36915e-05,2.75658e-05,4.90058e-05,3.06286e-05,3.06286e-05,3.67543e-05,3.06286e-05,2.144e-05,3.36915e-05,5.81944e-05,5.20687e-05,3.06286e-05,2.45029e-05,4.28801e-05,2.144e-05,4.59429e-05,3.36915e-05,3.36915e-05,3.06286e-05,2.75658e-05,4.59429e-05,2.144e-05,3.36915e-05,3.98172e-05,4.59429e-05,2.75658e-05,3.36915e-05,2.144e-05,2.75658e-05,4.59429e-05,3.36915e-05,2.45029e-05,2.75658e-05,3.36915e-05,3.98172e-05,3.06286e-05,3.06286e-05,2.144e-05,2.45029e-05,2.75658e-05,2.75658e-05,2.75658e-05,2.144e-05,2.144e-05,3.98172e-05,3.36915e-05,2.75658e-05,3.36915e-05,2.45029e-05,2.45029e-05,5.51315e-05,2.75658e-05,2.75658e-05,2.144e-05,4.59429e-05,3.36915e-05,3.06286e-05,2.144e-05,3.06286e-05,3.98172e-05,3.36915e-05,3.06286e-05,1.83772e-05,2.144e-05,1.53143e-05,3.36915e-05,4.28801e-05,4.59429e-05,5.51315e-05,3.98172e-05,4.59429e-05,6.43201e-05,3.98172e-05,4.28801e-05,4.28801e-05,3.36915e-05,4.90058e-05,4.28801e-05,3.06286e-05,2.45029e-05,6.12572e-05,0,6.12572e-05,0,5.81944e-05,0,6.43201e-05,0,7.35087e-05,0,6.43201e-05,0,7.96344e-05,0,9.18859e-05,0,6.12572e-05,0,8.57601e-05,0,9.80116e-05,0,6.7383e-05,0,6.43201e-05,0,4.59429e-05,0,6.7383e-05,0,5.20687e-05,0,6.12572e-05,0,3.67543e-05,0,5.20687e-05,0,5.51315e-05,0,8.57601e-05,0,6.7383e-05,0,2.75658e-05,0,4.59429e-05,0,4.28801e-05,0,5.51315e-05,0,3.06286e-05,0,5.51315e-05,0,4.59429e-05,0,3.67543e-05,0,3.98172e-05,0,4.28801e-05,0,3.36915e-05,0,5.51315e-05,0,4.90058e-05,0,3.98172e-05,0,6.12572e-05,0,6.12572e-05,0,4.28801e-05,0,4.59429e-05,0,6.7383e-05,0,2.45029e-05,0,5.51315e-05,0,3.06286e-05,0,2.45029e-05,0,3.36915e-05,0,3.67543e-05,0,3.67543e-05,0,2.75658e-05,0,5.51315e-05,0,3.67543e-05,0,3.36915e-05,0,4.28801e-05,0,3.98172e-05,0,3.36915e-05,0,2.45029e-05,0,3.36915e-05,0,3.67543e-05,0,2.75658e-05,0,3.36915e-05,0,1.53143e-05,0,3.67543e-05,0,2.45029e-05,0,3.36915e-05,0,3.67543e-05,0,3.67543e-05,0,3.06286e-05,0,1.22514e-05,0,3.36915e-05,0,2.144e-05,0,3.67543e-05,0,3.36915e-05,0,3.06286e-05,0,1.83772e-05,0,2.75658e-05,0,2.75658e-05,0,3.06286e-05,0,4.28801e-05,0,3.36915e-05,0,4.59429e-05,0,2.45029e-05,0,4.59429e-05,0,4.28801e-05,0,4.28801e-05,0,5.20687e-05,0,2.45029e-05,0,2.45029e-05,0,2.45029e-05,0,4.90058e-05,0,1.53143e-05,0,4.28801e-05,0,4.28801e-05,0,1.53143e-05,0,4.28801e-05,0,3.36915e-05,0,4.59429e-05,0,0.000131703,0,3.67543e-05,0,3.06286e-05,0,5.20687e-05,0,4.90058e-05,0,3.06286e-05,0,5.51315e-05,0,5.20687e-05,0,1.53143e-05,0,1.83772e-05,0,2.75658e-05,0,2.144e-05,0,2.75658e-05,0,5.51315e-05,0,3.98172e-05,0,3.67543e-05,0,3.98172e-05,0,4.90058e-05,0,4.59429e-05,0,4.28801e-05,0,2.75658e-05,0,4.90058e-05,0,3.06286e-05,0,6.12572e-05,0,2.75658e-05,0,4.90058e-05,0,3.98172e-05,0,3.67543e-05,0,4.59429e-05,0,3.98172e-05,0,3.98172e-05,0,4.90058e-05,0,5.81944e-05,0,0,3.67543e-05,0,0,7.96344e-05,0,0,4.59429e-05,0,0,4.59429e-05,0,0,6.7383e-05,0,0,7.04458e-05,0,0,8.8823e-05,0,0,7.35087e-05,0,0,6.7383e-05,0,0,4.90058e-05,0,0,7.35087e-05,0,0,6.12572e-05,0,0,5.51315e-05,0,0,4.59429e-05,0,0,8.8823e-05,0,0,6.43201e-05,0,0,8.26973e-05,0,0,6.12572e-05,0,0,5.51315e-05,0,0,7.65716e-05,0,0,0.000104137,0,0,7.04458e-05,0,0,4.28801e-05,0,0,6.7383e-05,0,0,7.65716e-05,0,0,9.18859e-05,0,0,8.8823e-05,0,0,7.04458e-05,0,0,9.18859e-05,0,0,7.65716e-05,0,0,7.96344e-05,0,0,7.04458e-05,0,0,5.20687e-05,0,0,9.80116e-05,0,0,0.000113326,0,0,9.49487e-05,0,0,8.8823e-05,0,0,0.000101074,0,0,9.18859e-05,0,0,7.04458e-05,0,0,7.96344e-05,0,0,8.8823e-05,0,0,7.04458e-05,0,0,9.49487e-05,0,0,6.43201e-05,0,0,0.000104137,0,0,7.96344e-05,0,0,0.000101074,0,0,0.000101074,0,0,7.96344e-05,0,0,9.18859e-05,0,0,7.04458e-05,0,0,8.8823e-05,0,0,7.35087e-05,0,0,7.04458e-05,0,0,7.35087e-05,0,0,9.49487e-05,0,0,8.8823e-05,0,0,4.90058e-05,0,0,7.96344e-05,0,0,6.12572e-05,0,0,3.67543e-05,0,0,5.81944e-05,0,0,5.51315e-05,0,0,2.144e-05,0,0,5.51315e-05,0,0,5.51315e-05,0,0,5.20687e-05,0,0,5.81944e-05,0,0,6.12572e-05,0,0,7.35087e-05,0,0,3.36915e-05,0,0,4.59429e-05,0,0,5.51315e-05,0,0,4.59429e-05,0,0,3.36915e-05,0,0,3.98172e-05,0,0,4.90058e-05,0,0,5.81944e-05,0,0,4.59429e-05,0,0,3.67543e-05,0,0,3.36915e-05,0,0,2.75658e-05,0,0,4.59429e-05,0,0,3.36915e-05,0,0,3.67543e-05,0,0,0,4.90058e-05,0,0,0,5.20687e-05,0,0,0,3.67543e-05,0,0,0,3.98172e-05,0,0,0,3.36915e-05,0,0,0,4.28801e-05,0,0,0,4.28801e-05,0,0,0,3.36915e-05,0,0,0,3.36915e-05,0,0,0,2.75658e-05,0,0,0,3.98172e-05,0,0,0,4.90058e-05,0,0,0,3.67543e-05,0,0,0,3.67543e-05,0,0,0,4.28801e-05,0,0,0,1.83772e-05,0,0,0,4.90058e-05,0,0,0,1.53143e-05,0,0,0,3.36915e-05,0,0,0,1.53143e-05,0,0,0,2.144e-05,0,0,0,3.36915e-05,0,0,0,3.06286e-05,0,0,0,1.53143e-05,0,0,0,1.83772e-05,0,0,0,3.36915e-05,0,0,0,3.67543e-05,0,0,0,2.75658e-05,0,0,0,2.75658e-05,0,0,0,3.36915e-05,0,0,0,0.00301386,0,0,0,3.06286e-05,0,0,0,2.45029e-05,0,0,0,1.53143e-05,0,0,0,6.12572e-06,0,0,0,1.83772e-05,0,0,0,1.22514e-05,0,0,0,1.83772e-05,0,0,0,3.67543e-05,0,0,0,1.53143e-05,0,0,0,3.06286e-05,0,0,0,3.98172e-05,0,0,0,3.67543e-05,0,0,0,6.12572e-06,0,0,0,2.45029e-05,0,0,0,9.18859e-06,0,0,0,1.83772e-05,0,0,0,2.144e-05,0,0,0,1.22514e-05,0,0,0,2.75658e-05,0,0,0,3.36915e-05,0,0,0,2.144e-05,0,0,0,2.144e-05,0,0,0,2.45029e-05,0,0,0,2.144e-05,0,0,0,2.45029e-05,0,0,0,3.67543e-05,0,0,0,1.83772e-05,0,0,0,2.144e-05,0,0,0,9.18859e-06,0,0,0,1.83772e-05,0,0,0,9.18859e-06,0,0,0,2.144e-05,0,0,0,2.144e-05,0,0,0,0,1.22514e-05,0,0,0,0,1.53143e-05,0,0,0,0,6.12572e-06,0,0,0,0,1.83772e-05,0,0,0,0,2.144e-05,0,0,0,0,2.144e-05,0,0,0,0,2.144e-05,0,0,0,0,1.83772e-05,0,0,0,0,1.53143e-05,0,0,0,0,1.53143e-05,0,0,0,0,2.144e-05,0,0,0,0,1.22514e-05,0,0,0,0,1.53143e-05,0,0,0,0,2.144e-05,0,0,0,0,2.144e-05,0,0,0,0,1.22514e-05,0,0,0,0,1.22514e-05,0,0,0,0,2.75658e-05,0,0,0,0,1.83772e-05,0,0,0,0,1.83772e-05,0,0,0,0,2.75658e-05,0,0,0,0,9.18859e-06,0,0,0,0,2.75658e-05,0,0,0,0,3.06286e-05,0,0,0,0,1.83772e-05,0,0,0,0,6.12572e-06,0,0,0,0,1.83772e-05,0,0,0,0,9.18859e-06,0,0,0,0,1.83772e-05,0,0,0,0,1.53143e-05,0,0,0,0,1.53143e-05,0,0,0,0,2.144e-05,0,0,0,0,1.83772e-05,0,0,0,0,1.83772e-05,0,0,0,0,2.45029e-05,0,0,0,0,2.144e-05,0,0,0,0,9.18859e-06,0,0,0,0,1.83772e-05,0,0,0,0,2.144e-05,0,0,0,0,1.83772e-05,0,0,0,0,2.144e-05,0,0,0,0,9.18859e-06,0,0,0,0,2.144e-05,0,0,0,0,1.22514e-05,0,0,0,0,1.22514e-05,0,0,0,0,1.83772e-05,0,0,0,0,2.144e-05,0,0,0,0,1.83772e-05,0,0,0,0,2.45029e-05,0,0,0,0,1.22514e-05,0,0,0,0,3.06286e-05,0,0,0,0,0,9.18859e-06,0,0,0,0,0,1.83772e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,1.22514e-05,0,0,0,0,0,3.06286e-05,0,0,0,0,0,1.53143e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,2.75658e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,6.12572e-06,0,0,0,0,0,1.83772e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,9.18859e-06,0,0,0,0,0,3.06286e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,1.22514e-05,0,0,0,0,0,1.53143e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,2.45029e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,2.45029e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,3.06286e-05,0,0,0,0,0,1.53143e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,6.12572e-06,0,0,0,0,0,1.83772e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,9.18859e-06,0,0,0,0,0,1.22514e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,1.22514e-05,0,0,0,0,0,1.83772e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,2.45029e-05,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,2.45029e-05,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,3.36915e-05,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,2.75658e-05,0,0,0,0,0,0,0,3.06286e-05,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.45029e-05,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,2.75658e-05,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,2.45029e-05,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.36915e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,3.67543e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.75658e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.83772e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.45029e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.144e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.06286e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.12572e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.18859e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.22514e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00152837,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.53143e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleM.csv b/libc/benchmarks/distributions/MemcpyGoogleM.csv new file mode 100644 index 0000000000000..1cdeff756977d --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleM.csv @@ -0,0 +1 @@ +0.0170536,0.0858551,0.0695917,0.0466788,0.0644246,0.0507621,0.0467837,0.0339883,0.0582017,0.040358,0.0365194,0.0232765,0.0238079,0.0213117,0.0270661,0.0259055,0.0241924,0.0100266,0.0207034,0.0120123,0.0123479,0.0076353,0.0178227,0.00801986,0.0136554,0.0067543,0.0065795,0.00685219,0.00468466,0.00445392,0.00299259,0.00860719,0.00981681,0.00446791,0.00355195,0.00225143,0.00241225,0.00555167,0.00218851,0.00100685,0.00664942,0.00284576,0.00462173,0.00149629,0.00144735,0.00192281,0.000671235,0.00145434,0.00415327,0.000664243,0.000650259,0.00086002,0.00153125,0.00183191,0.000985876,0.000538386,0.00150329,0.00051741,0.000300657,0.000433506,0.00145434,0.000321633,0.000328625,0.00044749,0.00476856,0.000300657,0.000321633,0.000265697,0.0028947,0.000272689,0.000321633,0.000160817,0.000594322,0.000251713,0.000244721,0.000279681,0.000209761,0.000237729,0.00041253,0.000251713,0.0010558,0.000237729,0.000328625,0.000286673,0.000335617,0.000160817,0.000230737,0.000167809,0.00041253,0.000209761,0.000230737,0.000174801,0.000167809,0.000209761,0.00051741,0.000643267,0.00102783,0.00010488,0.000125857,0.00037757,0.000146833,9.08964e-05,0.000111872,6.99203e-05,0.000384562,0.000230737,0.000118864,0.000202769,0.000202769,0.000279681,0.000286673,0.000174801,0.000363586,0.000181793,6.29283e-05,0.000139841,0.000153825,8.39043e-05,5.59362e-05,6.29283e-05,0.00058733,7.69123e-05,9.78884e-05,4.19522e-05,6.99203e-05,9.08964e-05,2.79681e-05,5.59362e-05,0.00207663,4.19522e-05,4.89442e-05,6.29283e-05,0.000839043,0.000230737,4.19522e-05,2.79681e-05,0.000776115,5.59362e-05,6.29283e-05,0.00010488,5.59362e-05,3.49601e-05,5.59362e-05,6.99203e-05,0.000223745,6.99203e-05,4.19522e-05,2.79681e-05,3.49601e-05,0.000615299,6.29283e-05,3.49601e-05,0.000629283,6.99203e-05,3.49601e-05,3.49601e-05,3.49601e-05,2.09761e-05,5.59362e-05,6.99203e-05,0.000643267,3.49601e-05,9.78884e-05,4.19522e-05,9.08964e-05,6.99203e-05,0.000153825,5.59362e-05,0.000510418,4.19522e-05,0.000132849,3.49601e-05,0.000181793,0.000202769,1.39841e-05,8.39043e-05,3.49601e-05,1.39841e-05,6.99203e-05,1.39841e-05,1.39841e-05,0.000349601,6.29283e-05,2.09761e-05,3.49601e-05,5.59362e-05,4.19522e-05,2.79681e-05,0.000125857,4.89442e-05,4.19522e-05,0.000118864,0.000454482,2.09761e-05,7.69123e-05,2.79681e-05,4.89442e-05,0,2.09761e-05,3.49601e-05,4.19522e-05,6.99203e-06,6.99203e-06,6.99203e-06,0.00037757,4.19522e-05,0,6.29283e-05,5.59362e-05,6.99203e-06,4.19522e-05,6.99203e-06,6.99203e-06,3.49601e-05,4.19522e-05,2.09761e-05,6.99203e-06,2.09761e-05,0,3.49601e-05,2.79681e-05,6.99203e-06,0,2.09761e-05,0.000188785,1.39841e-05,0,1.39841e-05,6.99203e-06,1.39841e-05,2.09761e-05,1.39841e-05,4.19522e-05,1.39841e-05,3.49601e-05,9.78884e-05,2.09761e-05,3.49601e-05,3.49601e-05,1.39841e-05,6.99203e-05,1.39841e-05,6.99203e-06,1.39841e-05,1.39841e-05,2.09761e-05,1.39841e-05,2.09761e-05,8.39043e-05,2.09761e-05,0.000601315,5.59362e-05,0.021081,9.78884e-05,0.000125857,0.000237729,0.00413229,9.78884e-05,4.89442e-05,6.29283e-05,6.29283e-05,6.99203e-06,1.39841e-05,1.39841e-05,8.39043e-05,1.39841e-05,0,6.99203e-06,0,6.99203e-06,6.99203e-06,0,2.79681e-05,6.99203e-06,6.99203e-06,1.39841e-05,2.79681e-05,6.99203e-06,1.39841e-05,6.99203e-06,3.49601e-05,6.99203e-06,6.29283e-05,4.89442e-05,1.39841e-05,6.99203e-06,6.99203e-06,6.99203e-06,1.39841e-05,0.000160817,0.000671235,2.09761e-05,2.79681e-05,6.99203e-06,3.49601e-05,4.89442e-05,0.000181793,2.09761e-05,2.09761e-05,6.99203e-06,0.00232835,5.59362e-05,1.39841e-05,1.39841e-05,0.000188785,1.39841e-05,6.99203e-06,6.99203e-06,2.09761e-05,2.79681e-05,0,0,4.89442e-05,6.99203e-06,6.99203e-06,2.79681e-05,0,0,6.99203e-06,0,3.49601e-05,6.99203e-06,1.39841e-05,6.99203e-06,1.39841e-05,6.99203e-06,6.99203e-06,1.39841e-05,1.39841e-05,2.09761e-05,1.39841e-05,6.99203e-06,0,1.39841e-05,1.39841e-05,6.99203e-06,1.39841e-05,6.99203e-06,0,6.99203e-06,1.39841e-05,2.09761e-05,6.99203e-06,6.99203e-06,1.39841e-05,6.99203e-06,0,1.39841e-05,0,2.09761e-05,2.09761e-05,0,0.000265697,2.09761e-05,2.79681e-05,6.99203e-06,3.49601e-05,1.39841e-05,0,0,1.39841e-05,0,6.99203e-06,2.09761e-05,0,1.39841e-05,2.79681e-05,0,6.99203e-06,0,0,6.99203e-06,6.99203e-06,0,2.79681e-05,9.08964e-05,0,1.39841e-05,2.09761e-05,2.79681e-05,2.79681e-05,0.000244721,0,4.89442e-05,0.000139841,0,1.39841e-05,0,1.39841e-05,0,0,0,1.39841e-05,0,1.39841e-05,0,6.99203e-06,0,2.79681e-05,0,0.000643267,0,2.79681e-05,0,3.49601e-05,0,6.99203e-06,0,0.000545378,0,1.39841e-05,0,0,0,6.99203e-06,0,2.79681e-05,0,6.99203e-06,0,3.49601e-05,0,2.79681e-05,0,3.49601e-05,0,2.09761e-05,0,5.59362e-05,0,1.39841e-05,0,0.000426514,0,4.19522e-05,0,2.79681e-05,0,2.79681e-05,0,1.39841e-05,0,6.99203e-06,0,2.09761e-05,0,2.79681e-05,0,0.000132849,0,2.09761e-05,0,0.000601315,0,6.99203e-06,0,6.99203e-06,0,2.09761e-05,0,6.99203e-06,0,1.39841e-05,0,3.49601e-05,0,6.99203e-06,0,2.79681e-05,0,4.19522e-05,0,2.09761e-05,0,6.99203e-06,0,1.39841e-05,0,6.99203e-06,0,2.09761e-05,0,2.09761e-05,0,1.39841e-05,0,6.99203e-06,0,6.99203e-06,0,2.79681e-05,0,6.99203e-06,0,6.99203e-06,0,1.39841e-05,0,1.39841e-05,0,1.39841e-05,0,2.09761e-05,0,4.19522e-05,0,2.09761e-05,0,1.39841e-05,0,2.09761e-05,0,0.00267795,0,6.99203e-06,0,2.09761e-05,0,0,0,6.99203e-05,0,0,0,2.79681e-05,0,6.99203e-06,0,1.39841e-05,0,1.39841e-05,0,2.09761e-05,0,2.79681e-05,0,2.79681e-05,0,0,0,2.09761e-05,0,6.99203e-06,0,6.99203e-06,0,2.09761e-05,0,1.39841e-05,0,2.09761e-05,0,6.99203e-06,0,6.99203e-06,0,1.39841e-05,0,6.99203e-06,0,2.79681e-05,0,6.99203e-06,0,1.39841e-05,0,1.39841e-05,0,1.39841e-05,0,1.39841e-05,0,1.39841e-05,0,2.09761e-05,0,2.79681e-05,0,3.49601e-05,0,1.39841e-05,0,1.39841e-05,0,1.39841e-05,0,6.99203e-06,0,1.39841e-05,0,1.39841e-05,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,6.99203e-06,0,0,0,1.39841e-05,0,1.39841e-05,0,6.99203e-06,0,0,0,1.39841e-05,0,6.99203e-06,0,0,0,2.09761e-05,0,0,0,5.59362e-05,0,1.39841e-05,0,5.59362e-05,0,0,0,1.39841e-05,0,6.99203e-06,0,0.000433506,0,0,6.99203e-06,0,0,2.09761e-05,0,0,6.29283e-05,0,0,6.99203e-06,0,0,6.99203e-06,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,2.79681e-05,0,0,2.09761e-05,0,0,2.09761e-05,0,0,1.39841e-05,0,0,1.39841e-05,0,0,0,0,0,1.39841e-05,0,0,2.09761e-05,0,0,0.000468466,0,0,0.000594322,0,0,2.09761e-05,0,0,6.99203e-06,0,0,6.99203e-06,0,0,0.000419522,0,0,0.000272689,0,0,1.39841e-05,0,0,6.99203e-06,0,0,3.49601e-05,0,0,6.99203e-06,0,0,2.09761e-05,0,0,2.79681e-05,0,0,2.79681e-05,0,0,2.09761e-05,0,0,6.29283e-05,0,0,2.09761e-05,0,0,6.99203e-06,0,0,7.69123e-05,0,0,0.000265697,0,0,1.39841e-05,0,0,0.000181793,0,0,1.39841e-05,0,0,1.39841e-05,0,0,0,0,0,6.99203e-06,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0.00109775,0,0,3.49601e-05,0,0,2.09761e-05,0,0,1.39841e-05,0,0,1.39841e-05,0,0,6.99203e-06,0,0,0,0,0,6.99203e-06,0,0,6.99203e-06,0,0,2.09761e-05,0,0,6.99203e-06,0,0,6.99203e-06,0,0,2.09761e-05,0,0,0,0,0,2.09761e-05,0,0,6.99203e-06,0,0,1.39841e-05,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,6.99203e-06,0,0,1.39841e-05,0,0,0,0,0,6.99203e-06,0,0,1.39841e-05,0,0,2.09761e-05,0,0,6.99203e-06,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0.000146833,0,0,0,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,2.79681e-05,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,6.99203e-06,0,0,0,2.79681e-05,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,2.79681e-05,0,0,0,2.79681e-05,0,0,0,6.99203e-06,0,0,0,0,0,0,0,1.39841e-05,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,3.49601e-05,0,0,0,0,0,0,0,7.69123e-05,0,0,0,6.99203e-06,0,0,0,5.59362e-05,0,0,0,0,0,0,0,0.000797091,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0.00248916,0,0,0,6.99203e-06,0,0,0,0.000356593,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,0.00266396,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,1.39841e-05,0,0,0,6.99203e-06,0,0,0,6.99203e-06,0,0,0,0,0,0,0,6.99203e-06,0,0,0,1.39841e-05,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,1.39841e-05,0,0,0,0,6.99203e-06,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,6.99203e-06,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,6.99203e-06,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,1.39841e-05,0,0,0,0,2.09761e-05,0,0,0,0,5.59362e-05,0,0,0,0,1.39841e-05,0,0,0,0,6.99203e-06,0,0,0,0,1.39841e-05,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,6.99203e-06,0,0,0,0,6.99203e-06,0,0,0,0,1.39841e-05,0,0,0,0,2.79681e-05,0,0,0,0,6.99203e-06,0,0,0,0,2.09761e-05,0,0,0,0,2.09761e-05,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,3.49601e-05,0,0,0,0,6.99203e-06,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,1.39841e-05,0,0,0,0,1.39841e-05,0,0,0,0,0,1.39841e-05,0,0,0,0,0,6.99203e-06,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,1.39841e-05,0,0,0,0,0,2.09761e-05,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,6.99203e-06,0,0,0,0,0,9.78884e-05,0,0,0,0,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,6.99203e-05,0,0,0,0,0,8.39043e-05,0,0,0,0,0,0.000167809,0,0,0,0,0,9.78884e-05,0,0,0,0,0,6.99203e-06,0,0,0,0,0,6.99203e-06,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000132849,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,3.49601e-05,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,9.08964e-05,0,0,0,0,0,0,4.19522e-05,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,6.29283e-05,0,0,0,0,0,0,3.49601e-05,0,0,0,0,0,0,4.19522e-05,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,3.49601e-05,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,7.69123e-05,0,0,0,0,0,0,0,0.000188785,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.59362e-05,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.08964e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0.000230737,0,0,0,0,0,0,0,0,0,0,0,6.29283e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.79681e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78884e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.39841e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.49601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.09761e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.99203e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000223745,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000867012 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleQ.csv b/libc/benchmarks/distributions/MemcpyGoogleQ.csv new file mode 100644 index 0000000000000..fce895a6e8f94 --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleQ.csv @@ -0,0 +1 @@ +0.0248684,0.0819381,0.0490306,0.0267845,0.0835775,0.0252078,0.0276942,0.0278702,0.243005,0.0193998,0.0257556,0.0183669,0.0182271,0.0281343,0.023144,0.025604,0.0210469,0.0113197,0.0121687,0.01233,0.00815449,0.00808896,0.0094945,0.00929497,0.00886069,0.00504802,0.0050353,0.00604863,0.00560359,0.00469394,0.0051116,0.00420196,0.00813689,0.00344783,0.00370997,0.00448952,0.0130998,0.00370605,0.00247951,0.00255384,0.00423521,0.00268197,0.00258514,0.00225161,0.00204816,0.0018721,0.00155911,0.00160508,0.0018721,0.0012598,0.00127937,0.00122068,0.000974197,0.00103875,0.00278957,0.000805962,0.000913554,0.00082259,0.000700326,0.0007864,0.000673917,0.000800093,0.000609362,0.000707173,0.00314266,0.000621099,0.000461667,0.000451886,0.000759991,0.000490033,0.000458733,0.000493945,0.000498836,0.0003932,0.000344294,0.000288542,0.000329623,0.000375594,0.000619143,0.00032571,0.000566325,0.000423521,0.000283652,0.000331579,0.000368747,0.000309082,0.000431346,0.000260177,0.000459711,0.000311039,0.000214206,0.000235724,0.000319842,0.000243549,0.000195622,0.000286586,0.000368747,0.000178016,0.000220075,0.000242571,0.000184863,0.000231812,0.000207359,0.000148673,0.000279739,0.000239637,0.00018095,0.000175082,0.000149651,0.000134979,0.000132045,0.000161388,0.000310061,0.000192687,0.000153563,0.000145738,0.000159432,0.000104658,0.000134001,0.000116395,0.000203447,0.000155519,0.000138891,9.78109e-05,0.00013987,0.000137913,0.000125198,0.000120307,0.000472427,0.00013987,0.000121286,0.000105636,9.58547e-05,7.92268e-05,8.31393e-05,0.000110526,0.000189753,9.97671e-05,8.60736e-05,8.50955e-05,0.000101723,9.68328e-05,9.78109e-05,7.1402e-05,0.000172147,8.1183e-05,0.000115417,9.68328e-05,5.86865e-05,6.35771e-05,7.62925e-05,4.59711e-05,8.9986e-05,4.69492e-05,7.82487e-05,9.38985e-05,6.06428e-05,5.3796e-05,6.45552e-05,7.23801e-05,0.000133023,5.96646e-05,7.1402e-05,5.28179e-05,5.96646e-05,5.18398e-05,4.89054e-05,5.47741e-05,0.000421565,5.47741e-05,6.55333e-05,4.4993e-05,6.06428e-05,5.08617e-05,3.12995e-05,4.01025e-05,0.000130088,4.69492e-05,4.69492e-05,2.15184e-05,7.1402e-05,4.59711e-05,4.98836e-05,7.04238e-05,7.53144e-05,4.4993e-05,3.71681e-05,4.40149e-05,5.77084e-05,4.69492e-05,4.69492e-05,6.94457e-05,0.000170191,4.98836e-05,4.10806e-05,3.42338e-05,4.69492e-05,0.000387331,3.81462e-05,4.30368e-05,6.06428e-05,3.32557e-05,5.57522e-05,4.89054e-05,3.42338e-05,3.619e-05,3.22776e-05,6.65114e-05,7.72706e-05,4.20587e-05,3.52119e-05,2.34746e-05,0.000132045,3.42338e-05,4.4993e-05,3.32557e-05,3.91244e-05,3.22776e-05,3.03214e-05,2.64089e-05,4.01025e-05,3.619e-05,4.4993e-05,2.93433e-05,7.43363e-05,3.619e-05,2.83652e-05,2.64089e-05,2.64089e-05,2.54308e-05,2.54308e-05,2.64089e-05,5.67303e-05,2.64089e-05,2.83652e-05,2.44527e-05,2.15184e-05,1.36935e-05,2.44527e-05,2.44527e-05,5.77084e-05,4.79273e-05,2.54308e-05,1.46716e-05,2.44527e-05,1.46716e-05,2.05403e-05,2.54308e-05,2.54308e-05,2.24965e-05,2.93433e-05,1.66279e-05,2.83652e-05,1.46716e-05,2.34746e-05,2.34746e-05,0.000528179,2.73871e-05,2.44527e-05,1.27154e-05,2.15184e-05,2.05403e-05,1.56497e-05,1.7606e-05,4.30368e-05,1.36935e-05,1.95622e-05,1.17373e-05,1.56497e-05,1.95622e-05,1.36935e-05,2.34746e-05,5.47741e-05,1.66279e-05,1.66279e-05,2.44527e-05,1.66279e-05,2.73871e-05,1.7606e-05,1.36935e-05,2.73871e-05,1.66279e-05,2.64089e-05,1.66279e-05,1.17373e-05,2.15184e-05,2.44527e-05,3.32557e-05,3.91244e-05,2.24965e-05,9.78109e-06,1.46716e-05,1.95622e-05,2.05403e-05,1.7606e-05,2.34746e-05,4.20587e-05,1.27154e-05,1.27154e-05,1.66279e-05,1.36935e-05,1.36935e-05,1.07592e-05,2.24965e-05,2.15184e-05,1.17373e-05,9.78109e-06,1.17373e-05,1.27154e-05,1.7606e-05,9.78109e-06,1.07592e-05,2.15184e-05,1.36935e-05,7.82487e-06,1.27154e-05,1.85841e-05,1.17373e-05,1.07592e-05,1.56497e-05,0.000135957,1.17373e-05,1.85841e-05,1.07592e-05,1.46716e-05,1.17373e-05,1.27154e-05,2.05403e-05,1.85841e-05,2.24965e-05,1.07592e-05,1.56497e-05,1.36935e-05,1.85841e-05,1.17373e-05,1.17373e-05,3.91244e-05,2.05403e-05,6.84676e-06,1.27154e-05,1.27154e-05,1.36935e-05,1.36935e-05,8.80298e-06,1.07592e-05,1.07592e-05,2.64089e-05,6.84676e-06,1.07592e-05,1.07592e-05,1.66279e-05,6.84676e-06,1.95622e-05,1.27154e-05,8.80298e-06,1.07592e-05,2.54308e-05,1.27154e-05,8.80298e-06,3.91244e-06,2.15184e-05,1.36935e-05,1.7606e-05,7.82487e-06,1.85841e-05,8.80298e-06,1.07592e-05,1.17373e-05,4.98836e-05,1.56497e-05,8.80298e-06,6.84676e-06,8.80298e-06,6.84676e-06,1.46716e-05,9.78109e-06,8.80298e-06,6.84676e-06,5.86865e-06,9.78109e-06,9.78109e-06,5.86865e-06,1.46716e-05,2.44527e-05,0.000220075,0,2.64089e-05,0,1.7606e-05,0,1.95622e-05,0,2.73871e-05,0,2.24965e-05,0,9.78109e-06,0,1.56497e-05,0,2.83652e-05,0,1.46716e-05,0,2.15184e-05,0,1.27154e-05,0,3.12995e-05,0,1.46716e-05,0,1.46716e-05,0,1.56497e-05,0,1.36935e-05,0,1.85841e-05,0,1.07592e-05,0,9.78109e-06,0,1.27154e-05,0,9.78109e-06,0,1.56497e-05,0,1.27154e-05,0,2.64089e-05,0,8.80298e-06,0,1.27154e-05,0,1.46716e-05,0,1.56497e-05,0,1.17373e-05,0,1.36935e-05,0,1.17373e-05,0,8.1183e-05,0,1.07592e-05,0,1.95622e-05,0,1.56497e-05,0,1.66279e-05,0,1.36935e-05,0,7.82487e-06,0,1.36935e-05,0,1.85841e-05,0,3.91244e-06,0,1.27154e-05,0,7.82487e-06,0,1.46716e-05,0,1.17373e-05,0,5.86865e-06,0,8.80298e-06,0,1.85841e-05,0,1.07592e-05,0,1.17373e-05,0,1.17373e-05,0,1.46716e-05,0,1.07592e-05,0,1.56497e-05,0,1.46716e-05,0,4.79273e-05,0,1.7606e-05,0,1.36935e-05,0,1.17373e-05,0,1.17373e-05,0,6.84676e-06,0,1.56497e-05,0,1.46716e-05,0,0.000267024,0,1.36935e-05,0,6.84676e-06,0,1.17373e-05,0,1.07592e-05,0,1.46716e-05,0,1.17373e-05,0,4.89054e-06,0,2.73871e-05,0,6.84676e-06,0,1.27154e-05,0,7.82487e-06,0,8.80298e-06,0,1.07592e-05,0,1.66279e-05,0,9.78109e-06,0,1.27154e-05,0,1.07592e-05,0,3.91244e-06,0,1.07592e-05,0,1.07592e-05,0,1.07592e-05,0,6.84676e-06,0,1.17373e-05,0,1.66279e-05,0,1.95622e-05,0,9.78109e-06,0,6.84676e-06,0,1.36935e-05,0,1.36935e-05,0,1.27154e-05,0,1.27154e-05,0,7.23801e-05,0,8.80298e-06,0,3.91244e-06,0,1.95622e-06,0,1.07592e-05,0,8.80298e-06,0,1.07592e-05,0,1.46716e-05,0,8.80298e-06,0,9.78109e-06,0,1.07592e-05,0,5.86865e-06,0,1.27154e-05,0,4.89054e-06,0,5.86865e-06,0,7.82487e-06,0,4.89054e-06,0,8.80298e-06,0,8.80298e-06,0,1.7606e-05,0,9.78109e-06,0,7.82487e-06,0,1.07592e-05,0,8.80298e-06,0,8.80298e-06,0,6.84676e-06,0,7.82487e-06,0,4.89054e-06,0,7.82487e-06,0,9.78109e-06,0,1.07592e-05,0,9.78109e-06,0,0.000164322,0,0,1.56497e-05,0,0,5.86865e-06,0,0,5.86865e-06,0,0,9.78109e-06,0,0,7.82487e-06,0,0,9.78109e-06,0,0,7.82487e-06,0,0,7.82487e-06,0,0,8.80298e-06,0,0,1.46716e-05,0,0,5.86865e-06,0,0,7.82487e-06,0,0,8.80298e-06,0,0,3.91244e-06,0,0,1.07592e-05,0,0,2.93433e-06,0,0,1.17373e-05,0,0,1.46716e-05,0,0,5.86865e-06,0,0,1.95622e-05,0,0,2.24965e-05,0,0,8.80298e-06,0,0,5.86865e-06,0,0,1.07592e-05,0,0,8.80298e-06,0,0,1.46716e-05,0,0,9.78109e-06,0,0,1.27154e-05,0,0,1.27154e-05,0,0,1.46716e-05,0,0,8.80298e-06,0,0,1.36935e-05,0,0,8.80298e-06,0,0,1.17373e-05,0,0,1.17373e-05,0,0,5.86865e-06,0,0,1.07592e-05,0,0,1.07592e-05,0,0,4.89054e-06,0,0,9.78109e-06,0,0,4.89054e-06,0,0,9.8789e-05,0,0,1.17373e-05,0,0,1.27154e-05,0,0,3.91244e-06,0,0,2.93433e-06,0,0,2.93433e-06,0,0,8.80298e-06,0,0,9.78109e-06,0,0,9.78109e-06,0,0,1.07592e-05,0,0,1.95622e-06,0,0,9.78109e-06,0,0,7.82487e-06,0,0,5.86865e-06,0,0,1.17373e-05,0,0,3.91244e-06,0,0,4.89054e-06,0,0,3.91244e-06,0,0,6.84676e-06,0,0,3.91244e-06,0,0,4.89054e-06,0,0,6.84676e-06,0,0,1.56497e-05,0,0,5.86865e-06,0,0,6.84676e-06,0,0,6.84676e-06,0,0,5.86865e-06,0,0,3.91244e-06,0,0,2.93433e-06,0,0,7.82487e-06,0,0,6.84676e-06,0,0,2.93433e-06,0,0,7.82487e-06,0,0,8.80298e-06,0,0,5.86865e-06,0,0,7.82487e-06,0,0,1.95622e-06,0,0,3.91244e-06,0,0,4.89054e-06,0,0,3.91244e-06,0,0,5.86865e-06,0,0,3.91244e-06,0,0,2.93433e-06,0,0,0.000126176,0,0,9.78109e-06,0,0,0,7.82487e-06,0,0,0,7.82487e-06,0,0,0,7.82487e-06,0,0,0,8.80298e-06,0,0,0,5.86865e-06,0,0,0,5.86865e-06,0,0,0,2.93433e-06,0,0,0,1.07592e-05,0,0,0,1.07592e-05,0,0,0,2.93433e-06,0,0,0,4.89054e-06,0,0,0,4.89054e-06,0,0,0,5.86865e-06,0,0,0,4.89054e-06,0,0,0,8.80298e-06,0,0,0,7.82487e-06,0,0,0,2.93433e-06,0,0,0,5.86865e-06,0,0,0,4.89054e-06,0,0,0,5.86865e-06,0,0,0,4.89054e-06,0,0,0,2.93433e-06,0,0,0,2.93433e-06,0,0,0,3.91244e-06,0,0,0,5.86865e-06,0,0,0,1.07592e-05,0,0,0,8.80298e-06,0,0,0,3.91244e-06,0,0,0,4.89054e-06,0,0,0,7.82487e-06,0,0,0,9.38985e-05,0,0,0,1.95622e-05,0,0,0,4.89054e-06,0,0,0,4.89054e-06,0,0,0,9.78109e-06,0,0,0,5.86865e-06,0,0,0,7.82487e-06,0,0,0,4.89054e-06,0,0,0,2.93433e-06,0,0,0,4.89054e-06,0,0,0,3.91244e-06,0,0,0,1.95622e-06,0,0,0,4.89054e-06,0,0,0,3.91244e-06,0,0,0,5.86865e-06,0,0,0,8.80298e-06,0,0,0,1.36935e-05,0,0,0,3.91244e-06,0,0,0,2.93433e-06,0,0,0,7.82487e-06,0,0,0,4.89054e-06,0,0,0,2.93433e-06,0,0,0,5.86865e-06,0,0,0,1.95622e-06,0,0,0,7.82487e-06,0,0,0,3.91244e-06,0,0,0,2.93433e-06,0,0,0,4.89054e-06,0,0,0,3.91244e-06,0,0,0,6.84676e-06,0,0,0,8.80298e-06,0,0,0,7.82487e-06,0,0,0,4.01025e-05,0,0,0,5.86865e-06,0,0,0,0,5.86865e-06,0,0,0,0,6.84676e-06,0,0,0,0,7.82487e-06,0,0,0,0,8.80298e-06,0,0,0,0,6.84676e-06,0,0,0,0,1.27154e-05,0,0,0,0,7.82487e-06,0,0,0,0,6.84676e-06,0,0,0,0,1.17373e-05,0,0,0,0,6.84676e-06,0,0,0,0,8.80298e-06,0,0,0,0,8.80298e-06,0,0,0,0,8.80298e-06,0,0,0,0,1.27154e-05,0,0,0,0,1.07592e-05,0,0,0,0,1.17373e-05,0,0,0,0,4.89054e-06,0,0,0,0,6.84676e-06,0,0,0,0,6.84676e-06,0,0,0,0,6.84676e-06,0,0,0,0,5.86865e-06,0,0,0,0,2.15184e-05,0,0,0,0,8.80298e-06,0,0,0,0,4.89054e-06,0,0,0,0,5.86865e-05,0,0,0,0,3.91244e-06,0,0,0,0,1.95622e-06,0,0,0,0,2.93433e-06,0,0,0,0,9.78109e-06,0,0,0,0,3.91244e-06,0,0,0,0,3.91244e-06,0,0,0,0,4.89054e-06,0,0,0,0,3.91244e-06,0,0,0,0,3.91244e-06,0,0,0,0,3.91244e-06,0,0,0,0,4.89054e-06,0,0,0,0,1.95622e-06,0,0,0,0,5.86865e-06,0,0,0,0,3.91244e-06,0,0,0,0,7.82487e-06,0,0,0,0,9.78109e-06,0,0,0,0,4.89054e-06,0,0,0,0,9.78109e-07,0,0,0,0,3.91244e-06,0,0,0,0,1.95622e-06,0,0,0,0,3.91244e-06,0,0,0,0,1.95622e-06,0,0,0,0,4.89054e-06,0,0,0,0,1.95622e-06,0,0,0,0,3.22776e-05,0,0,0,0,2.93433e-06,0,0,0,0,0,7.82487e-06,0,0,0,0,0,2.93433e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,9.78109e-07,0,0,0,0,0,3.91244e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,6.84676e-06,0,0,0,0,0,5.86865e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,2.93433e-06,0,0,0,0,0,2.93433e-06,0,0,0,0,0,6.84676e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,7.82487e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,7.82487e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,1.56497e-05,0,0,0,0,0,3.91244e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,9.78109e-07,0,0,0,0,0,9.78109e-07,0,0,0,0,0,3.91244e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,2.93433e-06,0,0,0,0,0,6.84676e-06,0,0,0,0,0,8.80298e-06,0,0,0,0,0,1.07592e-05,0,0,0,0,0,2.93433e-06,0,0,0,0,0,4.89054e-06,0,0,0,0,0,7.82487e-06,0,0,0,0,0,2.93433e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,6.84676e-06,0,0,0,0,0,2.93433e-06,0,0,0,0,0,3.91244e-06,0,0,0,0,0,6.84676e-06,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,5.86865e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,9.78109e-06,0,0,0,0,0,0,2.05403e-05,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,6.84676e-06,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,5.86865e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,3.81462e-05,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,5.86865e-06,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,1.46716e-05,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,7.82487e-06,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,7.82487e-06,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,6.84676e-06,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,6.84676e-06,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,0,7.82487e-06,0,0,0,0,0,0,0,0,0,0,1.27154e-05,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,0,6.84676e-06,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.82487e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.84676e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,5.86865e-06,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,0,5.86865e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,7.82487e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,4.89054e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.93433e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.91244e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.95622e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.78109e-07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.96646e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12995e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleS.csv b/libc/benchmarks/distributions/MemcpyGoogleS.csv new file mode 100644 index 0000000000000..5b1ef6f360ca1 --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleS.csv @@ -0,0 +1 @@ +0.023769,0.0371105,0.0542431,0.0270962,0.0187841,0.0156894,0.0169422,0.0245966,0.0279865,0.0190733,0.0192371,0.0184577,0.0286442,0.0190191,0.0120188,0.0136114,0.0228438,0.0120706,0.00904453,0.0135307,0.0141763,0.0103793,0.0129609,0.00973721,0.0168712,0.0189913,0.0168507,0.0141559,0.0154954,0.00661354,0.01202,0.00727128,0.0140667,0.00728092,0.00551731,0.00660993,0.00604013,0.00493185,0.0042994,0.00566066,0.0146534,0.00394644,0.00388741,0.00485234,0.00462827,0.00469935,0.00557754,0.00430422,0.00661716,0.0044283,0.00525349,0.00463068,0.00473067,0.00471501,0.00326099,0.00392355,0.00514146,0.00360673,0.00308391,0.00373804,0.00409702,0.00262614,0.00323931,0.00263217,0.00532697,0.00374647,0.0034694,0.00436084,0.00318149,0.00337785,0.00233221,0.00249604,0.00326822,0.00329593,0.0028996,0.0030297,0.00245749,0.00244906,0.00208766,0.00219247,0.00395246,0.00286466,0.0035465,0.00249965,0.003055,0.00152991,0.00227197,0.00202502,0.00230691,0.00283937,0.00163712,0.0190877,0.00243581,0.00330195,0.00192865,0.00278877,0.00247315,0.00127573,0.00126248,0.00203707,0.00162628,0.00151063,0.00148654,0.00138535,0.00236112,0.00143233,0.00141908,0.00150702,0.00242978,0.00158291,0.00137089,0.00150943,0.00205273,0.000846871,0.000895057,0.00112635,0.00104925,0.000830005,0.00185155,0.00102636,0.00109142,0.000993838,0.000778205,0.000961313,0.000827596,0.000848075,0.00128657,0.000881806,0.00114201,0.000643284,0.00106732,0.000905899,0.000540889,0.000662559,0.00059028,0.000678219,0.000681833,0.000902285,0.000755317,0.000695084,0.000527638,0.000409582,0.000430061,0.000442107,0.000527638,0.000544503,0.000532456,0.00072761,0.000424038,0.000467405,0.00045054,0.000372238,0.000399945,0.000630033,0.000332484,0.000409582,0.000342121,0.000349349,0.000738452,0.000298754,0.000319233,0.000315619,0.000357782,0.000430061,0.00032887,0.000257796,0.000404763,0.000558959,0.000408377,0.0013733,0.000430061,0.00048427,0.000474633,0.000285503,0.000410786,0.000355372,0.000609554,0.000393921,0.000350554,0.000345735,0.00031321,0.000278275,0.000333689,0.000319233,0.00043247,0.000304777,0.000298754,0.000336098,0.000378261,0.000361396,0.000351758,0.000345735,0.0147401,0.000610759,0.00045054,0.000505954,0.00045054,0.000286707,0.000387898,0.000483066,0.000507159,0.000489089,0.000372238,0.000345735,0.000451745,0.000297549,0.000355372,0.0003108,0.000309596,0.000273456,0.000254182,0.000534866,0.000355372,0.000269842,0.000528842,0.000366214,0.000324051,0.000286707,0.000239726,0.000230089,0.000263819,0.000333689,0.000269842,0.000236112,0.000218042,0.0002072,0.000212019,0.000315619,0.000238521,0.0002072,0.000216837,0.000216837,0.000216837,0.000184312,0.000172265,0.000202382,0.000246954,0.000178289,0.000221656,0.000259,0.00649669,0.000212019,0.000222861,0.000271047,0.000171061,0.00013733,0.000119261,0.000177084,0.000145763,0.000172265,0.00013974,0.00019154,0.000138535,0.000166242,0.000160219,0.000201177,0.000664968,9.99861e-05,0.000102395,0.000386693,0.000124079,0.000125284,0.000201177,0.000113237,0.000132512,8.79396e-05,0.000112033,9.39629e-05,0.000104805,7.58931e-05,0.000112033,0.00012167,0.000110828,0.00012167,8.91443e-05,0.000196358,8.07117e-05,8.79396e-05,0.000113237,0.000140944,0.000130102,0.000107214,9.75768e-05,8.07117e-05,9.87815e-05,6.50512e-05,9.63722e-05,7.10745e-05,8.3121e-05,0.00013974,7.34838e-05,0.000119261,6.38466e-05,9.87815e-05,7.83024e-05,0.000110828,9.27582e-05,9.03489e-05,6.74605e-05,0.000257796,7.95071e-05,0.000102395,7.70978e-05,9.51675e-05,6.98698e-05,8.79396e-05,7.34838e-05,8.91443e-05,6.14373e-05,6.14373e-05,8.19164e-05,8.91443e-05,0.000109623,8.6735e-05,7.34838e-05,7.95071e-05,4.33675e-05,5.42094e-05,6.02326e-05,7.70978e-05,5.18001e-05,6.02326e-05,7.34838e-05,0.000203586,4.21628e-05,5.30047e-05,5.42094e-05,5.42094e-05,9.27582e-05,5.5414e-05,6.98698e-05,3.97535e-05,5.9028e-05,3.85489e-05,5.30047e-05,5.66187e-05,5.9028e-05,4.09582e-05,4.33675e-05,3.37303e-05,6.62559e-05,4.33675e-05,5.18001e-05,4.33675e-05,3.49349e-05,6.26419e-05,4.57768e-05,9.99861e-05,4.81861e-05,4.93907e-05,4.09582e-05,7.83024e-05,3.73442e-05,5.42094e-05,4.33675e-05,0.000244544,4.57768e-05,5.30047e-05,5.9028e-05,4.09582e-05,0.000109623,6.14373e-05,4.93907e-05,4.33675e-05,4.69814e-05,4.57768e-05,4.69814e-05,3.61396e-05,5.05954e-05,3.73442e-05,3.01163e-05,3.01163e-05,3.97535e-05,2.04791e-05,3.61396e-05,3.97535e-05,0.000104805,3.61396e-05,4.21628e-05,3.25256e-05,3.49349e-05,1.92744e-05,3.49349e-05,8.43257e-05,0.000138535,0,7.58931e-05,0,6.62559e-05,0,5.05954e-05,0,5.05954e-05,0,0.000175879,0,5.42094e-05,0,6.14373e-05,0,6.38466e-05,0,7.22791e-05,0,7.83024e-05,0,0.000104805,0,4.09582e-05,0,4.21628e-05,0,3.73442e-05,0,5.5414e-05,0,5.78233e-05,0,4.33675e-05,0,4.33675e-05,0,4.93907e-05,0,5.18001e-05,0,5.5414e-05,0,3.49349e-05,0,5.5414e-05,0,3.01163e-05,0,0.000179493,0,3.37303e-05,0,3.61396e-05,0,3.73442e-05,0,4.69814e-05,0,3.85489e-05,0,4.45721e-05,0,3.49349e-05,0,3.25256e-05,0,3.49349e-05,0,3.61396e-05,0,2.89117e-05,0,3.73442e-05,0,2.65024e-05,0,3.01163e-05,0,4.57768e-05,0,0.000168651,0,4.09582e-05,0,3.85489e-05,0,4.45721e-05,0,2.89117e-05,0,3.1321e-05,0,2.89117e-05,0,9.63722e-05,0,4.21628e-05,0,3.61396e-05,0,4.57768e-05,0,3.97535e-05,0,4.33675e-05,0,3.61396e-05,0,3.61396e-05,0,3.1321e-05,0,9.51675e-05,0,3.1321e-05,0,4.57768e-05,0,4.21628e-05,0,3.61396e-05,0,3.49349e-05,0,4.93907e-05,0,0.000101191,0,3.25256e-05,0,1.92744e-05,0,3.97535e-05,0,4.45721e-05,0,6.14373e-05,0,3.1321e-05,0,3.1321e-05,0,5.9028e-05,0,4.09582e-05,0,3.73442e-05,0,2.89117e-05,0,3.37303e-05,0,3.85489e-05,0,3.1321e-05,0,6.26419e-05,0,5.05954e-05,0,3.97535e-05,0,3.01163e-05,0,2.16837e-05,0,2.89117e-05,0,4.33675e-05,0,3.37303e-05,0,2.4093e-05,0,2.16837e-05,0,8.43257e-05,0,2.4093e-05,0,2.4093e-05,0,3.85489e-05,0,2.4093e-05,0,2.89117e-05,0,2.89117e-05,0,7.10745e-05,0,1.44558e-05,0,3.25256e-05,0,1.44558e-05,0,2.28884e-05,0,2.16837e-05,0,1.80698e-05,0,1.56605e-05,0,1.92744e-05,0,1.68651e-05,0,1.08419e-05,0,8.43257e-06,0,1.80698e-05,0,2.52977e-05,0,3.25256e-05,0,2.28884e-05,0,1.32512e-05,0,2.16837e-05,0,1.32512e-05,0,1.32512e-05,0,2.28884e-05,0,3.73442e-05,0,2.52977e-05,0,2.28884e-05,0,3.1321e-05,0,8.19164e-05,0,2.04791e-05,0,1.68651e-05,0,2.16837e-05,0,2.4093e-05,0,1.68651e-05,0,1.92744e-05,0,0.000175879,0,0,3.01163e-05,0,0,2.65024e-05,0,0,3.97535e-05,0,0,3.25256e-05,0,0,3.1321e-05,0,0,3.1321e-05,0,0,2.52977e-05,0,0,2.4093e-05,0,0,2.28884e-05,0,0,3.1321e-05,0,0,2.16837e-05,0,0,2.16837e-05,0,0,3.85489e-05,0,0,9.63722e-06,0,0,2.89117e-05,0,0,2.4093e-05,0,0,9.51675e-05,0,0,3.01163e-05,0,0,1.68651e-05,0,0,2.28884e-05,0,0,1.80698e-05,0,0,2.28884e-05,0,0,1.56605e-05,0,0,1.80698e-05,0,0,1.68651e-05,0,0,8.43257e-06,0,0,1.32512e-05,0,0,1.08419e-05,0,0,1.68651e-05,0,0,1.68651e-05,0,0,1.08419e-05,0,0,2.7707e-05,0,0,2.04791e-05,0,0,1.56605e-05,0,0,1.20465e-05,0,0,1.92744e-05,0,0,2.28884e-05,0,0,7.22791e-05,0,0,1.32512e-05,0,0,3.85489e-05,0,0,1.20465e-05,0,0,5.30047e-05,0,0,6.02326e-06,0,0,1.56605e-05,0,0,6.02326e-06,0,0,1.08419e-05,0,0,1.20465e-05,0,0,9.63722e-06,0,0,4.81861e-06,0,0,1.08419e-05,0,0,1.08419e-05,0,0,7.22791e-06,0,0,1.56605e-05,0,0,1.32512e-05,0,0,1.92744e-05,0,0,1.20465e-05,0,0,7.22791e-06,0,0,6.02326e-06,0,0,2.65024e-05,0,0,6.02326e-06,0,0,4.81861e-06,0,0,7.22791e-06,0,0,8.43257e-06,0,0,8.43257e-06,0,0,8.43257e-06,0,0,1.20465e-05,0,0,1.32512e-05,0,0,4.81861e-06,0,0,7.22791e-06,0,0,1.32512e-05,0,0,1.68651e-05,0,0,1.44558e-05,0,0,9.63722e-06,0,0,1.32512e-05,0,0,2.16837e-05,0,0,9.63722e-06,0,0,1.32512e-05,0,0,4.81861e-06,0,0,1.20465e-05,0,0,1.68651e-05,0,0,6.98698e-05,0,0,1.32512e-05,0,0,1.08419e-05,0,0,9.63722e-06,0,0,8.43257e-06,0,0,1.32512e-05,0,0,0,4.81861e-06,0,0,0,2.16837e-05,0,0,0,3.61396e-06,0,0,0,1.32512e-05,0,0,0,1.32512e-05,0,0,0,1.08419e-05,0,0,0,1.08419e-05,0,0,0,7.22791e-06,0,0,0,3.61396e-06,0,0,0,1.08419e-05,0,0,0,1.80698e-05,0,0,0,1.32512e-05,0,0,0,1.20465e-05,0,0,0,9.63722e-06,0,0,0,9.63722e-06,0,0,0,1.32512e-05,0,0,0,1.32512e-05,0,0,0,7.22791e-06,0,0,0,6.02326e-06,0,0,0,1.20465e-05,0,0,0,1.32512e-05,0,0,0,7.22791e-06,0,0,0,4.81861e-06,0,0,0,8.43257e-06,0,0,0,9.63722e-06,0,0,0,1.20465e-05,0,0,0,7.22791e-06,0,0,0,4.69814e-05,0,0,0,1.08419e-05,0,0,0,9.63722e-06,0,0,0,0.000110828,0,0,0,9.99861e-05,0,0,0,9.63722e-06,0,0,0,8.43257e-06,0,0,0,4.81861e-06,0,0,0,2.4093e-06,0,0,0,6.02326e-06,0,0,0,8.43257e-06,0,0,0,7.22791e-06,0,0,0,7.22791e-06,0,0,0,1.08419e-05,0,0,0,2.4093e-06,0,0,0,7.22791e-06,0,0,0,6.02326e-06,0,0,0,8.43257e-06,0,0,0,7.22791e-06,0,0,0,3.61396e-06,0,0,0,6.02326e-06,0,0,0,7.22791e-06,0,0,0,9.63722e-06,0,0,0,6.02326e-06,0,0,0,6.02326e-06,0,0,0,1.20465e-05,0,0,0,3.61396e-06,0,0,0,3.61396e-06,0,0,0,3.61396e-06,0,0,0,3.61396e-06,0,0,0,1.44558e-05,0,0,0,7.22791e-06,0,0,0,3.61396e-05,0,0,0,1.08419e-05,0,0,0,2.4093e-06,0,0,0,9.63722e-06,0,0,0,6.02326e-06,0,0,0,0,1.08419e-05,0,0,0,0,1.08419e-05,0,0,0,0,1.08419e-05,0,0,0,0,7.22791e-06,0,0,0,0,7.22791e-06,0,0,0,0,3.61396e-06,0,0,0,0,8.43257e-06,0,0,0,0,4.81861e-06,0,0,0,0,6.02326e-06,0,0,0,0,9.63722e-06,0,0,0,0,2.4093e-06,0,0,0,0,1.20465e-06,0,0,0,0,3.61396e-06,0,0,0,0,3.61396e-06,0,0,0,0,9.63722e-06,0,0,0,0,3.61396e-06,0,0,0,0,6.02326e-06,0,0,0,0,9.63722e-06,0,0,0,0,6.02326e-06,0,0,0,0,6.02326e-06,0,0,0,0,8.43257e-06,0,0,0,0,2.52977e-05,0,0,0,0,4.81861e-06,0,0,0,0,6.02326e-06,0,0,0,0,7.22791e-06,0,0,0,0,2.4093e-06,0,0,0,0,2.4093e-06,0,0,0,0,8.43257e-06,0,0,0,0,3.61396e-06,0,0,0,0,1.92744e-05,0,0,0,0,3.61396e-06,0,0,0,0,4.81861e-06,0,0,0,0,7.22791e-06,0,0,0,0,6.02326e-06,0,0,0,0,3.61396e-06,0,0,0,0,8.43257e-06,0,0,0,0,3.61396e-06,0,0,0,0,7.22791e-06,0,0,0,0,9.63722e-06,0,0,0,0,6.02326e-06,0,0,0,0,6.02326e-06,0,0,0,0,7.22791e-06,0,0,0,0,6.02326e-06,0,0,0,0,4.81861e-06,0,0,0,0,6.02326e-06,0,0,0,0,4.81861e-06,0,0,0,0,7.22791e-06,0,0,0,0,2.52977e-05,0,0,0,0,0,0,0,0,0,7.70978e-05,0,0,0,0,1.20465e-06,0,0,0,0,0,4.81861e-06,0,0,0,0,0,7.22791e-06,0,0,0,0,0,2.4093e-06,0,0,0,0,0,4.81861e-06,0,0,0,0,0,7.22791e-06,0,0,0,0,0,8.43257e-06,0,0,0,0,0,6.02326e-06,0,0,0,0,0,6.02326e-06,0,0,0,0,0,8.43257e-06,0,0,0,0,0,1.20465e-06,0,0,0,0,0,1.32512e-05,0,0,0,0,0,2.4093e-06,0,0,0,0,0,4.81861e-06,0,0,0,0,0,8.43257e-06,0,0,0,0,0,1.08419e-05,0,0,0,0,0,7.22791e-06,0,0,0,0,0,9.63722e-06,0,0,0,0,0,8.43257e-06,0,0,0,0,0,1.80698e-05,0,0,0,0,0,8.43257e-06,0,0,0,0,0,3.61396e-05,0,0,0,0,0,4.81861e-06,0,0,0,0,0,8.43257e-06,0,0,0,0,0,7.22791e-06,0,0,0,0,0,6.02326e-06,0,0,0,0,0,7.22791e-06,0,0,0,0,0,6.02326e-06,0,0,0,0,0,1.20465e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,2.4093e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,1.92744e-05,0,0,0,0,0,1.20465e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,2.4093e-06,0,0,0,0,0,4.81861e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,3.61396e-06,0,0,0,0,0,6.02326e-06,0,0,0,0,0,6.02326e-06,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,1.32512e-05,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,1.68651e-05,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,8.55303e-05,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,1.08419e-05,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,1.44558e-05,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,2.7707e-05,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,9.63722e-06,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,0,9.63722e-06,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,3.1321e-05,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,9.63722e-06,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.20465e-05,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.20465e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.08419e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.22791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.61396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.43257e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.32512e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.32512e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.32512e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.08419e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.20465e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.81861e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.56605e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.02326e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.4093e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.52977e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.04791e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000660149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.10745e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleU.csv b/libc/benchmarks/distributions/MemcpyGoogleU.csv new file mode 100644 index 0000000000000..8dd97091b0f5f --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleU.csv @@ -0,0 +1 @@ +0.0758381,0.0162854,0.0250612,0.0231911,0.0221483,0.0309823,0.0373132,0.0141104,0.086218,0.06165,0.0162194,0.0131355,0.0289102,0.00801648,0.0072863,0.0106129,0.0245,0.0122655,0.0101022,0.00881658,0.00677556,0.00743777,0.0105061,0.00609975,0.0150581,0.00500059,0.00532296,0.0115936,0.0041403,0.00556571,0.00528218,0.00701831,0.0238533,0.00378686,0.00416554,0.0050705,0.00479668,0.00595022,0.00464521,0.00447043,0.00261196,0.00575991,0.00322951,0.0244553,0.00224298,0.00161184,0.00230901,0.0027712,0.00301783,0.00201383,0.0026741,0.00410534,0.00214589,0.00226629,0.00138463,0.00176526,0.00197888,0.00129336,0.00321591,0.00229736,0.00117684,0.00556377,0.00160796,0.00140599,0.00435974,0.00125258,0.00162155,0.00048161,0.00127976,0.00312076,0.000840876,0.000836992,0.00114577,0.00105838,0.000774849,0.000842818,0.00109139,0.000778733,0.000572883,0.000821457,0.00172253,0.000543754,0.000772907,0.000493262,0.00105644,0.000302949,0.000468017,0.00073601,0.000749603,0.000400047,0.000433061,0.000471901,0.000349556,0.000238863,0.000234979,0.000302949,0.000776791,0.000240805,0.000514624,0.000240805,0.000234979,0.000170894,0.000244689,0.000493262,0.00304114,0.000231095,0.000283529,0.00035344,0.000108751,0.000161184,0.000250515,0.000190314,0.0238164,0.000223327,0.000464133,0.000200024,0.000238863,0.000130112,0.000211676,0.00034373,0.00386648,0.000133996,0.000219443,0.000135938,9.32149e-05,0.000128171,0.000172836,0.000153416,0.00508992,8.7389e-05,0.00014759,0.000269935,7.18532e-05,6.40853e-05,4.27235e-05,0.000211676,0.123927,0.000110693,6.21433e-05,0.00013788,0.000124287,5.63174e-05,5.82593e-05,5.04914e-05,7.37951e-05,0.000108751,5.04914e-05,7.37951e-05,9.12729e-05,6.60272e-05,0.000112635,5.24334e-05,8.15631e-05,6.79692e-05,5.82593e-05,0.000124287,7.96211e-05,4.27235e-05,6.21433e-05,5.04914e-05,0.000168952,4.46655e-05,4.85494e-05,5.24334e-05,5.04914e-05,0.000116519,4.07815e-05,7.57371e-05,5.82593e-05,5.63174e-05,4.27235e-05,8.5447e-05,5.43754e-05,5.24334e-05,4.07815e-05,4.66075e-05,0.000165068,0.000102925,3.68976e-05,7.96211e-05,3.88396e-05,3.68976e-05,3.68976e-05,7.96211e-05,6.99112e-05,4.27235e-05,3.68976e-05,3.88396e-05,9.32149e-05,9.12729e-05,2.13618e-05,3.68976e-05,0.000149532,3.30136e-05,4.27235e-05,6.79692e-05,3.68976e-05,4.85494e-05,4.27235e-05,1.94198e-05,6.79692e-05,3.68976e-05,7.18532e-05,2.91297e-05,2.13618e-05,4.07815e-05,0.000178662,4.46655e-05,3.30136e-05,7.18532e-05,0.000161184,3.68976e-05,3.10716e-05,3.68976e-05,1.35938e-05,2.13618e-05,6.02013e-05,4.46655e-05,7.18532e-05,2.13618e-05,4.66075e-05,3.10716e-05,3.30136e-05,8.5447e-05,3.30136e-05,2.91297e-05,3.49556e-05,2.71877e-05,3.10716e-05,2.91297e-05,6.99112e-05,1.74778e-05,0.000425293,3.49556e-05,4.07815e-05,3.49556e-05,2.71877e-05,2.52457e-05,3.49556e-05,2.91297e-05,3.88396e-05,2.13618e-05,3.10716e-05,2.52457e-05,1.55358e-05,2.91297e-05,9.12729e-05,3.88396e-05,2.52457e-05,2.71877e-05,3.68976e-05,2.33037e-05,0.00336351,3.30136e-05,8.5447e-05,4.46655e-05,0.00328971,2.71877e-05,1.94198e-05,7.37951e-05,2.13618e-05,2.33037e-05,0.000132054,1.94198e-05,0.000198082,2.33037e-05,2.71877e-05,3.49556e-05,2.13618e-05,1.55358e-05,2.52457e-05,0.000277703,0.000209734,4.07815e-05,2.52457e-05,1.16519e-05,1.74778e-05,1.55358e-05,2.91297e-05,2.71877e-05,6.60272e-05,7.76791e-06,9.70989e-06,1.16519e-05,3.68976e-05,3.10716e-05,3.10716e-05,8.15631e-05,2.13618e-05,7.18532e-05,3.10716e-05,2.71877e-05,2.13618e-05,2.52457e-05,3.30136e-05,1.35938e-05,2.13618e-05,1.16519e-05,1.94198e-05,4.46655e-05,4.07815e-05,2.52457e-05,1.74778e-05,2.33037e-05,1.16519e-05,4.46655e-05,2.13618e-05,1.74778e-05,1.94198e-05,4.27235e-05,3.88396e-05,2.13618e-05,3.49556e-05,2.91297e-05,3.30136e-05,1.74778e-05,9.70989e-06,5.82593e-06,2.13618e-05,3.49556e-05,1.55358e-05,2.13618e-05,3.30136e-05,1.74778e-05,1.35938e-05,1.74778e-05,1.74778e-05,1.94198e-05,2.52457e-05,4.66075e-05,1.94198e-05,5.82593e-06,1.55358e-05,1.94198e-05,9.70989e-06,3.88396e-06,1.55358e-05,1.16519e-05,1.55358e-05,2.91297e-05,2.33037e-05,1.16519e-05,7.76791e-06,2.13618e-05,1.55358e-05,1.55358e-05,1.74778e-05,1.16519e-05,1.35938e-05,1.35938e-05,2.33037e-05,4.46655e-05,4.46655e-05,1.16519e-05,1.16519e-05,3.68976e-05,1.94198e-05,1.74778e-05,2.71877e-05,1.94198e-05,1.74778e-05,1.74778e-05,4.66075e-05,2.71877e-05,1.55358e-05,1.94198e-05,1.94198e-05,2.52457e-05,3.30136e-05,1.74778e-05,2.71877e-05,1.55358e-05,1.94198e-05,1.16519e-05,3.49556e-05,1.74778e-05,3.10716e-05,7.76791e-06,1.55358e-05,9.70989e-06,1.55358e-05,9.70989e-06,9.70989e-06,1.55358e-05,8.3505e-05,0,5.82593e-05,0,3.30136e-05,0,3.68976e-05,0,1.94198e-05,0,1.35938e-05,0,5.43754e-05,0,3.88396e-05,0,3.49556e-05,0,1.74778e-05,0,3.68976e-05,0,4.85494e-05,0,5.24334e-05,0,3.30136e-05,0,7.57371e-05,0,1.94198e-05,0,3.10716e-05,0,3.68976e-05,0,0.000108751,0,1.35938e-05,0,4.46655e-05,0,3.49556e-05,0,2.33037e-05,0,1.55358e-05,0,1.35938e-05,0,2.33037e-05,0,1.55358e-05,0,3.68976e-05,0,1.16519e-05,0,2.91297e-05,0,9.32149e-05,0,2.52457e-05,0,0.000104867,0,0.000180604,0,5.63174e-05,0,4.07815e-05,0,7.18532e-05,0,2.13618e-05,0,2.71877e-05,0,4.07815e-05,0,0.000114577,0,6.60272e-05,0,0.000118461,0,6.02013e-05,0,4.66075e-05,0,5.24334e-05,0,5.43754e-05,0,1.74778e-05,0,6.40853e-05,0,4.66075e-05,0,2.91297e-05,0,0.000108751,0,3.49556e-05,0,4.85494e-05,0,3.88396e-05,0,1.74778e-05,0,7.76791e-05,0,5.82593e-05,0,7.37951e-05,0,5.43754e-05,0,3.88396e-05,0,5.24334e-05,0,3.30136e-05,0,1.94198e-05,0,0.000722416,0,6.79692e-05,0,4.66075e-05,0,2.33037e-05,0,5.24334e-05,0,8.7389e-05,0,2.33037e-05,0,3.49556e-05,0,2.33037e-05,0,1.16519e-05,0,0.000116519,0,2.13618e-05,0,1.74778e-05,0,7.76791e-06,0,1.94198e-05,0,1.16519e-05,0,2.52457e-05,0,0.000297123,0,4.27235e-05,0,1.94198e-05,0,1.55358e-05,0,1.35938e-05,0,1.55358e-05,0,1.74778e-05,0,3.49556e-05,0,3.88396e-05,0,2.52457e-05,0,4.27235e-05,0,0.000155358,0,2.13618e-05,0,0.000116519,0,4.46655e-05,0,0.000345672,0,0.000188372,0,6.60272e-05,0,0.000246631,0,0.000114577,0,0.000118461,0,0.000277703,0,1.94198e-05,0,0.000236921,0,8.15631e-05,0,6.02013e-05,0,0.00016701,0,0.000299065,0,3.68976e-05,0,0.00020585,0,0.00038257,0,0.000293239,0,4.46655e-05,0,0.000104867,0,1.55358e-05,0,0.000518508,0,1.35938e-05,0,6.02013e-05,0,3.68976e-05,0,1.16519e-05,0,3.88396e-05,0,1.74778e-05,0,7.57371e-05,0,2.13618e-05,0,1.55358e-05,0,1.55358e-05,0,1.74778e-05,0,1.55358e-05,0,0,2.13618e-05,0,0,2.13618e-05,0,0,6.21433e-05,0,0,2.91297e-05,0,0,3.49556e-05,0,0,6.40853e-05,0,0,3.68976e-05,0,0,1.94198e-05,0,0,1.16519e-05,0,0,1.94198e-05,0,0,3.68976e-05,0,0,7.76791e-06,0,0,1.16519e-05,0,0,2.13618e-05,0,0,1.55358e-05,0,0,9.70989e-06,0,0,8.5447e-05,0,0,1.55358e-05,0,0,1.74778e-05,0,0,6.02013e-05,0,0,2.13618e-05,0,0,2.52457e-05,0,0,4.27235e-05,0,0,0.00018643,0,0,1.35938e-05,0,0,1.74778e-05,0,0,1.35938e-05,0,0,2.33037e-05,0,0,1.35938e-05,0,0,1.74778e-05,0,0,1.94198e-05,0,0,1.94198e-05,0,0,2.52457e-05,0,0,1.94198e-06,0,0,1.35938e-05,0,0,1.55358e-05,0,0,1.35938e-05,0,0,2.33037e-05,0,0,1.35938e-05,0,0,1.74778e-05,0,0,3.88396e-06,0,0,6.40853e-05,0,0,1.74778e-05,0,0,1.55358e-05,0,0,3.88396e-05,0,0,1.16519e-05,0,0,1.55358e-05,0,0,1.16519e-05,0,0,1.74778e-05,0,0,5.82593e-06,0,0,1.16519e-05,0,0,2.71877e-05,0,0,1.74778e-05,0,0,2.91297e-05,0,0,7.76791e-06,0,0,1.74778e-05,0,0,9.70989e-06,0,0,7.76791e-06,0,0,2.52457e-05,0,0,1.94198e-05,0,0,1.16519e-05,0,0,3.10716e-05,0,0,5.82593e-06,0,0,1.35938e-05,0,0,1.94198e-05,0,0,2.13618e-05,0,0,1.16519e-05,0,0,3.88396e-06,0,0,1.16519e-05,0,0,1.55358e-05,0,0,2.71877e-05,0,0,9.70989e-06,0,0,5.82593e-06,0,0,1.16519e-05,0,0,1.94198e-05,0,0,1.35938e-05,0,0,1.55358e-05,0,0,1.16519e-05,0,0,9.70989e-06,0,0,2.71877e-05,0,0,2.71877e-05,0,0,7.76791e-06,0,0,1.74778e-05,0,0,1.16519e-05,0,0,1.16519e-05,0,0,1.74778e-05,0,0,0,1.35938e-05,0,0,0,2.13618e-05,0,0,0,1.16519e-05,0,0,0,1.55358e-05,0,0,0,1.35938e-05,0,0,0,2.52457e-05,0,0,0,1.74778e-05,0,0,0,1.35938e-05,0,0,0,9.70989e-06,0,0,0,3.30136e-05,0,0,0,1.35938e-05,0,0,0,1.55358e-05,0,0,0,5.82593e-06,0,0,0,3.88396e-06,0,0,0,1.55358e-05,0,0,0,2.52457e-05,0,0,0,2.13618e-05,0,0,0,2.13618e-05,0,0,0,1.94198e-05,0,0,0,9.70989e-06,0,0,0,1.74778e-05,0,0,0,2.13618e-05,0,0,0,2.91297e-05,0,0,0,7.76791e-06,0,0,0,3.68976e-05,0,0,0,2.13618e-05,0,0,0,2.33037e-05,0,0,0,2.33037e-05,0,0,0,1.74778e-05,0,0,0,1.55358e-05,0,0,0,0.000267993,0,0,0,0.000211676,0,0,0,6.40853e-05,0,0,0,1.94198e-05,0,0,0,4.85494e-05,0,0,0,0.000423351,0,0,0,7.76791e-06,0,0,0,1.74778e-05,0,0,0,1.16519e-05,0,0,0,1.55358e-05,0,0,0,1.74778e-05,0,0,0,9.70989e-06,0,0,0,9.70989e-06,0,0,0,1.16519e-05,0,0,0,9.70989e-06,0,0,0,5.82593e-06,0,0,0,4.85494e-05,0,0,0,7.76791e-06,0,0,0,9.70989e-06,0,0,0,1.74778e-05,0,0,0,5.82593e-06,0,0,0,5.82593e-06,0,0,0,9.70989e-06,0,0,0,5.82593e-06,0,0,0,1.74778e-05,0,0,0,3.88396e-06,0,0,0,5.82593e-06,0,0,0,1.35938e-05,0,0,0,9.70989e-06,0,0,0,1.74778e-05,0,0,0,7.37951e-05,0,0,0,7.76791e-06,0,0,0,9.70989e-06,0,0,0,2.13618e-05,0,0,0,0,3.88396e-06,0,0,0,0,7.76791e-06,0,0,0,0,1.55358e-05,0,0,0,0,1.55358e-05,0,0,0,0,1.94198e-05,0,0,0,0,9.70989e-06,0,0,0,0,9.70989e-06,0,0,0,0,5.82593e-06,0,0,0,0,3.88396e-06,0,0,0,0,1.94198e-05,0,0,0,0,1.94198e-06,0,0,0,0,4.46655e-05,0,0,0,0,1.74778e-05,0,0,0,0,1.74778e-05,0,0,0,0,5.82593e-06,0,0,0,0,7.76791e-06,0,0,0,0,1.94198e-05,0,0,0,0,1.94198e-05,0,0,0,0,3.49556e-05,0,0,0,0,3.10716e-05,0,0,0,0,1.55358e-05,0,0,0,0,1.16519e-05,0,0,0,0,5.82593e-06,0,0,0,0,1.94198e-06,0,0,0,0,1.94198e-05,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,7.76791e-06,0,0,0,0,9.70989e-06,0,0,0,0,2.13618e-05,0,0,0,0,7.76791e-06,0,0,0,0,7.76791e-06,0,0,0,0,1.16519e-05,0,0,0,0,9.70989e-06,0,0,0,0,9.70989e-06,0,0,0,0,1.94198e-06,0,0,0,0,7.76791e-06,0,0,0,0,3.88396e-06,0,0,0,0,7.76791e-06,0,0,0,0,1.16519e-05,0,0,0,0,9.70989e-06,0,0,0,0,1.16519e-05,0,0,0,0,7.76791e-06,0,0,0,0,9.70989e-06,0,0,0,0,3.88396e-06,0,0,0,0,5.82593e-06,0,0,0,0,3.88396e-06,0,0,0,0,3.88396e-06,0,0,0,0,1.16519e-05,0,0,0,0,1.16519e-05,0,0,0,0,7.76791e-06,0,0,0,0,0,7.76791e-06,0,0,0,0,0,1.35938e-05,0,0,0,0,0,9.70989e-06,0,0,0,0,0,3.88396e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,1.55358e-05,0,0,0,0,0,2.13618e-05,0,0,0,0,0,5.82593e-06,0,0,0,0,0,5.82593e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,1.16519e-05,0,0,0,0,0,1.55358e-05,0,0,0,0,0,5.82593e-06,0,0,0,0,0,1.94198e-06,0,0,0,0,0,1.16519e-05,0,0,0,0,0,9.70989e-06,0,0,0,0,0,1.16519e-05,0,0,0,0,0,2.71877e-05,0,0,0,0,0,1.16519e-05,0,0,0,0,0,3.49556e-05,0,0,0,0,0,7.76791e-06,0,0,0,0,0,7.76791e-06,0,0,0,0,0,5.82593e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,1.16519e-05,0,0,0,0,0,1.94198e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,3.88396e-06,0,0,0,0,0,7.76791e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,5.82593e-06,0,0,0,0,0,1.74778e-05,0,0,0,0,0,9.70989e-06,0,0,0,0,0,7.76791e-06,0,0,0,0,0,1.35938e-05,0,0,0,0,0,1.16519e-05,0,0,0,0,0,1.74778e-05,0,0,0,0,0,3.88396e-06,0,0,0,0,0,5.82593e-06,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,3.10716e-05,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,4.85494e-05,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,2.33037e-05,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.33037e-05,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,2.71877e-05,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,2.33037e-05,0,0,0,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,1.94198e-05,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,2.13618e-05,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.94198e-05,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,2.13618e-05,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.55358e-05,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.94198e-05,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.94198e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,2.33037e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,2.91297e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.94198e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.70989e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.35938e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.82593e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.74778e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.76791e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.88396e-06,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.16519e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.63174e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0056395,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000130112 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemcpyGoogleW.csv b/libc/benchmarks/distributions/MemcpyGoogleW.csv new file mode 100644 index 0000000000000..8d334ff311eba --- /dev/null +++ b/libc/benchmarks/distributions/MemcpyGoogleW.csv @@ -0,0 +1 @@ +0.0152838,0.0414847,0.084425,0.0487627,0.0924309,0.0167394,0.0138282,0.0167394,0.0218341,0.0167394,0.0720524,0.0269287,0.0320233,0.0618632,0.0167394,0.00582242,0.0152838,0.00946143,0.00436681,0.00218341,0.00291121,0.00655022,0.00291121,0.00436681,0.00727802,0.00727802,0.014556,0.00582242,0.00800582,0.00800582,0.00509461,0.00218341,0.00800582,0.00436681,0.00509461,0.0014556,0.0014556,0.0218341,0.00363901,0.00873362,0.00509461,0.00436681,0.0101892,0.0298399,0.00363901,0.00509461,0.00436681,0.00291121,0.00873362,0.00582242,0.00582242,0.0218341,0.000727802,0.0014556,0.00291121,0.00291121,0.00655022,0.000727802,0.0014556,0.00436681,0.00218341,0.00509461,0.0014556,0.000727802,0.00436681,0.00873362,0.000727802,0.0014556,0.00291121,0.0014556,0.000727802,0.0014556,0.000727802,0,0.00436681,0.00291121,0.00291121,0.00582242,0.000727802,0.000727802,0.0014556,0.000727802,0.000727802,0.000727802,0.00218341,0.00218341,0.000727802,0.0014556,0.00582242,0.0014556,0.00291121,0,0.000727802,0.000727802,0,0.000727802,0.000727802,0.000727802,0.000727802,0.0014556,0,0,0.000727802,0,0.0014556,0.000727802,0,0,0,0.000727802,0.000727802,0.000727802,0.000727802,0.000727802,0.000727802,0.000727802,0,0,0,0,0.000727802,0,0,0,0.000727802,0,0.000727802,0,0.00436681,0.000727802,0,0.000727802,0,0.000727802,0,0,0,0,0,0.00218341,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0.000727802,0,0,0,0,0.000727802,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0014556,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0.000727802,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0.0014556,0,0.000727802,0,0.00363901,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000727802 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleA.csv b/libc/benchmarks/distributions/MemsetGoogleA.csv new file mode 100644 index 0000000000000..9a0f7a8161a20 --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleA.csv @@ -0,0 +1 @@ +6.62734e-05,6.62734e-05,0.000463914,6.62734e-05,0.0209424,0.000265094,0.00019882,0,0.067135,0,6.62734e-05,0,0.000861555,0,0.000132547,0,0.157466,0.100007,0,0.0719067,0.00019882,0,0,0.0297568,0.201935,0,6.62734e-05,0,0.000132547,0,6.62734e-05,0.0248525,0.0454636,0,0,0,0.000331367,6.62734e-05,0,0,0.00861555,0,0,0,0,0,0,0.0109351,0.0243886,0,0.000132547,0,6.62734e-05,0,0,0,0.00331367,0,0,0,0,0,0,0,0.00821791,0,0,0,0,0,0,0,0.0042415,0,0,0,0,0,0,0.0131221,0.00311485,0,0,0,0.000132547,0,6.62734e-05,0,0.0019882,0,0,0,6.62734e-05,0,0,0,0.00384386,0,0,0,6.62734e-05,0,0,0,0.00112665,0,0.000132547,0,0,0,6.62734e-05,0,0.00318113,0,0,0,0.000132547,0,6.62734e-05,0,0.000596461,0,0,0,0,0,0,0,0.00457287,0.000331367,0,0.000463914,0.000795281,0,0,0,0.00139174,0.000662734,0,0,0,0,0.0052356,0.0112002,0.00583206,0,0,0,6.62734e-05,0.0055007,0,0,0.0117967,0,0,0.000265094,6.62734e-05,0,0,0,0.0125257,0,0,0,0,0,6.62734e-05,0,0.00152429,0,0,0,0.00019882,0,0,0,0.00278348,0,0,0,0.00019882,0,6.62734e-05,0,0.00192193,0,0,0,0.000795281,0,0,0,0.0032474,0,0,0,0,0,0,0,0.00119292,0,0,0,0,0,0,0,0.00351249,0,0,0,0.00019882,0,0,0,0.00483796,0,0,0,0,0,0,0,0.00172311,0,0,0,0,0,0,0,0.0032474,0,0,0,0,0,0,0,0.0123931,0,0,0,0,0,0,0,0.00311485,0,0,0,0,0,0,0,0.0062297,6.62734e-05,0,0,0,0,0,0,0.000662734,0,0,0,0,0,0,0.00477169,0.00112665,0,0,0,0,0,0,0,0.00218702,0,0,0,0,0,0,0,0.00112665,0,0,0,0,0,0,0,0.000397641,0,0,0,0,0,0,0,0.00159056,0,6.62734e-05,0,0,0,0,0,0.00603088,0,0,0,0,0,0,0,0.0032474,0,0,0,0,0,0,0,0.00112665,0,0,0,0,0,0,0,0.000861555,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0.00178938,0,0,0,0,0,0,0,0.000265094,0,6.62734e-05,0,0,0,0,0,0.000861555,0,0,0,0,0,0,0,0.000331367,0,0,0,0,0,0,0,0.0019882,0,0,0,0.000861555,0,0.000132547,0,6.62734e-05,0,0,0,0,0,0,0,0.000861555,0,0,0,6.62734e-05,0,0,0,0.000331367,0,0,0,0,0,0,0,0.00377759,0,0,0,0,0,0,0,0.000861555,0,0,0,0,0,0,0,0.00106038,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,6.62734e-05,0,0.00159056,0,0,0,0,0,0,0,0.000331367,0,0,0,0,0,0,0,0.000795281,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0.00106038,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0.000927828,0,0,0,0,0,0,0,0.00178938,0,0,0,0,0,0,0,0.00258466,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0.000729008,0,0.000463914,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0.000397641,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0.000795281,0,0,0,0,0,0,0,0.000530188,0,0,0,0,0,0,0,0.000861555,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0.000397641,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0.00106038,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000596461,0,0,0,0,0,0,0,0,0.0138511,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000331367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000331367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0.000331367,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000662734,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000397641,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0.000530188,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0019882,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0.00019882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000132547,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000265094,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00344622,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.62734e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleB.csv b/libc/benchmarks/distributions/MemsetGoogleB.csv new file mode 100644 index 0000000000000..c5e9e96eca13d --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleB.csv @@ -0,0 +1 @@ +6.03355e-05,0.0185833,0.00120671,0.00123688,0.247979,0.00138772,0.00111621,0.000724026,0.206528,0.000422348,0.000512851,0.000331845,0.00446482,0.000392181,0.00150839,0.000241342,0.0446181,0.0412695,9.05032e-05,0.0211174,0.000422348,0.000814529,9.05032e-05,0.00576204,0.0195789,0.000120671,0.000150839,0.000150839,0.00108604,0.000181006,9.05032e-05,0.00238325,0.0175878,3.01677e-05,9.05032e-05,9.05032e-05,9.05032e-05,3.01677e-05,3.01677e-05,3.01677e-05,0.0747556,3.01677e-05,3.01677e-05,6.03355e-05,9.05032e-05,0,3.01677e-05,0.00129721,0.00564137,3.01677e-05,0,0,0.165199,3.01677e-05,0,6.03355e-05,0.00184023,3.01677e-05,3.01677e-05,0.000241342,3.01677e-05,3.01677e-05,3.01677e-05,3.01677e-05,0.0107699,3.01677e-05,6.03355e-05,3.01677e-05,3.01677e-05,0,0,3.01677e-05,0.00244359,0,3.01677e-05,3.01677e-05,0,0,6.03355e-05,0.000754193,0.00268493,0,0,0,6.03355e-05,3.01677e-05,0.000422348,3.01677e-05,0.0009352,6.03355e-05,3.01677e-05,0,0,6.03355e-05,0,6.03355e-05,0.00410281,0,0,0,0,0,3.01677e-05,6.03355e-05,0.00621455,6.03355e-05,0.000995535,9.05032e-05,0.000150839,9.05032e-05,6.03355e-05,0,0.00190057,3.01677e-05,0,0,0,6.03355e-05,0,3.01677e-05,0.000724026,0,3.01677e-05,6.03355e-05,3.01677e-05,3.01677e-05,0,3.01677e-05,0.0018704,0,0,0,0.000120671,0,0,0,0.000211174,0,0,0,0,0,0,0.000150839,0.00027151,0,0,0,6.03355e-05,0,0,0,0.000543019,0,0,0,0.00193073,0,0,0,0.00165923,0,3.01677e-05,0,0.000724026,0,9.05032e-05,0.000181006,0.000211174,0,6.03355e-05,3.01677e-05,0.000241342,3.01677e-05,0,0,0.000211174,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0.000724026,0,0,0,0,0,0,0,6.03355e-05,0,3.01677e-05,0,0,0,0,0,0.000784361,0,0,0,9.05032e-05,0,0,0,9.05032e-05,0,0,0,0,0,0,0,0.00108604,0,0,0,0,0,0,0,6.03355e-05,0,6.03355e-05,0,0.000181006,0,0,0,3.01677e-05,0,0,0,0,0,0,3.01677e-05,0.000181006,0,0,0,0,0,3.01677e-05,0,0.00165923,0,0,0,0.000392181,0,0,0,0.00168939,3.01677e-05,0,0,0,0,0,0.000181006,0.000724026,0,0,0,3.01677e-05,0,0,0,0.000874864,0,3.01677e-05,0,0,0,0,0,0.00111621,0,0,0,0,0,0,0,6.03355e-05,0,0,0,3.01677e-05,0,3.01677e-05,0,0.00404248,0,0,0,0,0,0,0,0.000301677,0,0,0,0,0,0,0,0.000905032,3.01677e-05,0,0,0,3.01677e-05,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0.000150839,3.01677e-05,3.01677e-05,0,9.05032e-05,3.01677e-05,3.01677e-05,0,0,0,0,3.01677e-05,0,0.000603355,0,0.000120671,0,0,0,0,0,0,0,3.01677e-05,0,0.000211174,0,0,0,0,0,0,0,0,0,0,0,0.00220224,0,0,0,0,0,0,0,0.000633522,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000452516,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000482684,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000784361,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,3.01677e-05,0,9.05032e-05,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0.000512851,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,3.01677e-05,0,0,0,0,0,0.00129721,0,0,0,0,0,0,0,0.0345722,0,3.01677e-05,0,0,0,3.01677e-05,0,0,0,0,0,0,0,3.01677e-05,0,3.01677e-05,0,0,0,3.01677e-05,0,0,0,0.00027151,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000120671,0,3.01677e-05,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0.000362013,0,3.01677e-05,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,9.05032e-05,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0.000181006,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0.000150839,0,0,0,0,0,6.03355e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000362013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,9.05032e-05,0,0,0,0,0,3.01677e-05,0,0,6.03355e-05,0,0,0,0,0,0.000362013,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.03355e-05,0,0,0,0,0,0,0,0,0,0,0,9.05032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.03355e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000120671,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.03355e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,6.03355e-05,0,0,0,0,0,0,0,9.05032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.05032e-05,0,0,0,0,0,0,0,0.000573187,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000482684,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.03355e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.05032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.01677e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000573187,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.03355e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000392181,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000301677,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00144805 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleD.csv b/libc/benchmarks/distributions/MemsetGoogleD.csv new file mode 100644 index 0000000000000..d32e449fb948d --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleD.csv @@ -0,0 +1 @@ +0.0243902,0,0,0,0,0,0,0,0.0487805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0243902,0,0,0,0,0,0,0.0609756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0121951,0,0,0,0.0121951,0,0,0,0.0365854,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0.0609756,0,0,0,0,0,0,0,0.0243902,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0.0609756,0,0,0,0,0,0,0,0.0487805,0,0,0,0,0,0,0,0.0243902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0853659,0,0,0,0,0,0,0,0.0487805,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0.0853659,0,0,0,0,0,0,0,0.0731707,0,0,0,0,0,0,0,0.0365854,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0243902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0365854,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0121951,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0365854,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0365854 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleL.csv b/libc/benchmarks/distributions/MemsetGoogleL.csv new file mode 100644 index 0000000000000..3961cef1c5d30 --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleL.csv @@ -0,0 +1 @@ +0.0002574,0.000772201,0,0,0.000772201,0,0,0,0.032175,0.000514801,0,0,0.001287,0.0002574,0,0.0002574,0.00746461,0.288546,0.0002574,0.0978121,0.000514801,0.000514801,0.0002574,0.0290862,0.0326898,0,0.0002574,0,0.000772201,0.0002574,0,0.0041184,0.015444,0.000514801,0,0.0002574,0.000514801,0.000514801,0,0,0.000514801,0,0,0,0,0,0,0.0010296,0.0468468,0,0,0,0,0,0,0,0.0033462,0.0002574,0,0,0,0,0,0,0.0404118,0,0,0,0.000514801,0,0,0,0.0579151,0,0,0.0002574,0,0.0002574,0,0.000514801,0.023166,0,0,0.0002574,0.0002574,0,0,0,0.0002574,0,0,0,0.0002574,0,0,0,0.0136422,0,0,0,0,0,0,0,0.000514801,0,0.0380952,0,0,0,0,0,0.000514801,0,0,0,0.0002574,0,0,0.0002574,0.00566281,0,0,0,0,0,0,0,0.0010296,0,0,0,0,0,0,0,0.000772201,0,0,0,0.0002574,0,0,0,0.001287,0,0,0,0,0,0.0002574,0,0,0,0,0,0.000514801,0,0,0,0.000514801,0,0,0,0,0,0,0,0.00643501,0,0,0,0.0002574,0,0,0,0.037323,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0.00978121,0,0,0,0,0,0,0,0.0962677,0,0,0,0.001287,0,0,0,0,0,0,0,0,0,0,0,0.000772201,0,0,0,0,0,0,0,0.000514801,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000772201,0,0,0,0.0015444,0,0,0,0,0,0,0,0.000772201,0,0,0,0,0,0,0,0.0023166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000772201,0,0,0,0,0,0,0,0.000514801,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0.000772201,0,0,0,0,0,0,0,0.000514801,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000772201,0,0,0,0,0,0,0,0.001287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000772201,0,0,0,0.0468468,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001287,0,0,0,0,0,0,0,0,0.0030888,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0010296,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0120978,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0023166,0,0,0,0,0,0,0,0.00952381,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002574 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleM.csv b/libc/benchmarks/distributions/MemsetGoogleM.csv new file mode 100644 index 0000000000000..d74526ef830c5 --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleM.csv @@ -0,0 +1 @@ +0,0.00140845,0.000970266,0.00109546,0.252488,0.000187793,0.00143975,0.000250391,0.0695462,0.000344288,0.00137715,0.000751174,0.00485133,0.000250391,0.000312989,0.000187793,0.0282316,0.120156,0.000907668,0.0461346,0.00165884,3.12989e-05,0,0.0287324,0.0225352,3.12989e-05,0,0,0.00103286,3.12989e-05,0.000344288,0.016651,0.0204695,6.25978e-05,0,0,0.000438185,3.12989e-05,0,0,0.00901408,0,3.12989e-05,3.12989e-05,0.000532081,0,3.12989e-05,0.00816901,0.00754304,0.000250391,0,0,0.000657277,3.12989e-05,3.12989e-05,0,0.00406886,0,0,0,3.12989e-05,0,0,0,0.0224413,0,0,0,9.38967e-05,0,0,0,0.00266041,0,0,0,0.000187793,0,0,0.0100782,0.00222222,0,0,0,0.000375587,0,0,0,0.00106416,0,0,0,0.000156495,0,0,0,0.0229421,0,0,0,9.38967e-05,0,0,0,0.00165884,3.12989e-05,3.12989e-05,0,0.000187793,0,0,0,0.000813772,0,0,0,0,0,0,0,0.00175274,0,0,0,0.000125196,0,0,0,0.0186541,0.000312989,0,0,0.00100156,0,0,0,0.00400626,0.000719875,0,0,0.00256651,0,3.12989e-05,0.00222222,0.00507042,0,0,0.000375587,0.000469484,0,0,0,0.000813772,0,0,0,0.000125196,0.00215962,0.00215962,0,0.0087011,0.00056338,0,0,0.000125196,0,0,0,0.00347418,0,0,0,0.000438185,0,0,0,0.000344288,0,0,0,0.00084507,0,0,0,0.00353678,0,0,0,0.000312989,0,0,0,0.00463224,0,0,9.38967e-05,0.000187793,0,0,0,0.00716745,0,0,0,0.000970266,0,0,0,0.000813772,0,0,0,0.00190923,0,0,0,0.00222222,0,0,0,0,0,0,0,0.00363067,0,0,0,0.000375587,0,0,0,0.00363067,0,0,0,0.00187793,0,0,0,0.000187793,0,0,0,6.25978e-05,0,0,0,0.000782473,0,0,0,0,0,0,0,0.005759,0,0,0,0,0,0,0,0.0151487,0,0,0,3.12989e-05,0,0,0.000438185,0.00488263,0,0,0,0.00028169,0,0,0,9.38967e-05,0,0,0,0.00394366,0.000250391,0,0,0.000688576,0,0,0,0.00203443,0,0,0,0.000187793,0,0,0,3.12989e-05,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0.000125196,0,0,0,3.12989e-05,0,0,0,0.000438185,0,0,0,0,0,0,0,0.00112676,0,0,0,0,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,0.000657277,0,0,0,0,0,0,0,9.38967e-05,0,0,0,0,0,0,0,9.38967e-05,0,0,0,3.12989e-05,0,0,0,0.00137715,0,0,0,0,0,0,0,0.00159624,0,0,0,0.0029421,0,0,0,0.000375587,0,0.00109546,0,0,0,3.12989e-05,0,0,0,0,0,3.12989e-05,0,0,0,0.00134585,0,0,0,3.12989e-05,0,0,0,0.000312989,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,6.25978e-05,0,0,0,0.000219092,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000250391,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,9.38967e-05,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0.00306729,0,0,0,3.12989e-05,0,3.12989e-05,0,3.12989e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,9.38967e-05,0,0,0,3.12989e-05,0,0,0,0.00381847,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,6.25978e-05,0,9.38967e-05,0,0,0,3.12989e-05,0,0,0,0.0102347,0,0,0,0,0,0,0,0.000625978,0,0,0,0,0,0,0,0.000125196,0,0,0,0,0,0,0,0.00175274,0,0,0,0,0,0,0,0.000907668,0,0,0,3.12989e-05,0,0,0,0.000125196,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0.00200313,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0.00194053,0,0,0,3.12989e-05,0,0,0,9.38967e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0.000813772,0,0,6.25978e-05,0,0,6.25978e-05,0,0,0,0,0,0.00125196,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0.00322379,0,0,0,0,0,0.000344288,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,3.12989e-05,0,0,0.000344288,0,0,3.12989e-05,0,0,0,0,0,3.12989e-05,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0.000594679,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,6.25978e-05,0,0,3.12989e-05,0,0,9.38967e-05,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,3.12989e-05,0,0,3.12989e-05,0,0,0,0.000125196,0,0,0,0,0,0,0,9.38967e-05,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0.000219092,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0.000125196,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,9.38967e-05,0,0,0,0,0,0,0,9.38967e-05,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,6.25978e-05,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00103286,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0.00485133,0,0,0,0,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0.000125196,0,0,0,0,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,0.00175274,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,3.12989e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,6.25978e-05,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,6.25978e-05,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,9.38967e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.38967e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,3.12989e-05,0,0,0,0,3.12989e-05,0,0,0,0,3.12989e-05,0,0,0,0,9.38967e-05,0,0,0,0,6.25978e-05,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0.000751174,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000125196,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000312989,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0917684,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,9.38967e-05,0,0,0,0,0,0,0.00147105,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0.00084507,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00356808,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000688576,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000156495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.25978e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.12989e-05 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleQ.csv b/libc/benchmarks/distributions/MemsetGoogleQ.csv new file mode 100644 index 0000000000000..74dc30775662f --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleQ.csv @@ -0,0 +1 @@ +0.000908969,0.114931,0.0166021,0.0172437,0.0440583,0.0101858,0.0132603,0.00355567,0.0442989,0.0114691,0.00657666,0.00417057,0.0371608,0.00149713,0.00237936,0.000989173,0.0682796,0.0102393,0.000775297,0.00665686,0.00352894,0.000802032,0.00141692,0.00315466,0.0105868,0.000374282,0.00125652,0.000374282,0.00654993,0.000481219,0.00267344,0.00157733,0.114904,0.00024061,0.000347547,0.000320813,0.00261997,0.000294078,0.000294078,0.000294078,0.00633605,0.000802032,0.00024061,0.000294078,0.00826093,0.00106938,0.000133672,0.00173774,0.0499398,0.00117631,0.000454485,0.000347547,0.00713808,8.02032e-05,0.000160406,0.000160406,0.0384173,0.00042775,0.000481219,0.000187141,0.0041171,0.000106938,0.000106938,2.67344e-05,0.037749,0.000641625,0.000187141,0.000133672,0.0032616,0.000160406,0.000133672,5.34688e-05,0.0146237,0,5.34688e-05,0,0.00470525,0.000320813,0.000133672,0.000802032,0.0148376,0.000106938,5.34688e-05,0,0.00261997,0,2.67344e-05,2.67344e-05,0.00705788,0.000187141,5.34688e-05,0,0.00347547,5.34688e-05,5.34688e-05,0,0.018019,0.000267344,2.67344e-05,5.34688e-05,0.00187141,0.000213875,5.34688e-05,5.34688e-05,0.00564096,0.000213875,0.00216549,0,0.00224569,2.67344e-05,8.02032e-05,0,0.00545382,0,0,2.67344e-05,0.00221895,0.000641625,0.000133672,0,0.00438444,2.67344e-05,2.67344e-05,0,0.00128325,0,0,0,0.00922337,8.02032e-05,0.000267344,5.34688e-05,0.00189814,0.000267344,0.000160406,0.000133672,0.00363588,0.00042775,0.000213875,0.000347547,0.000695094,5.34688e-05,2.67344e-05,0.00024061,0.0233659,0.000294078,2.67344e-05,0,0.000775297,0,0,0,0.00336853,2.67344e-05,2.67344e-05,0,0.000213875,0,0,0,0.00336853,0,0,0,0.000320813,0,2.67344e-05,2.67344e-05,0.000908969,2.67344e-05,0,0,0.000213875,2.67344e-05,0,0,0.003422,8.02032e-05,0,0,0.000160406,0,2.67344e-05,0,0.00173774,2.67344e-05,2.67344e-05,0,5.34688e-05,0,0,2.67344e-05,0.00272691,0,0,0,0.000133672,0,0.00024061,0.000133672,0.00251303,8.02032e-05,2.67344e-05,0,2.67344e-05,0,0,0,0.00652319,0.000106938,0,2.67344e-05,0.00066836,0,0,0,0.000935704,2.67344e-05,0,0,2.67344e-05,0,0,2.67344e-05,0.00112284,0,0,2.67344e-05,5.34688e-05,2.67344e-05,0,0,0.000294078,0,0,0,5.34688e-05,0,0,0,0.000374282,0,0,2.67344e-05,0.000187141,0,0,0,0.000401016,2.67344e-05,0,0,8.02032e-05,0,0,2.67344e-05,0.00628258,0,0,0,2.67344e-05,0,0,0,0.000989173,0,2.67344e-05,0,2.67344e-05,0,0,0.00700441,0.00211202,0,0,2.67344e-05,0.000213875,0,0,0,0.000267344,0,0,0,0,0,2.67344e-05,0,0.000213875,0,0,0,5.34688e-05,0,0,0,2.67344e-05,0,0,0,2.67344e-05,0,0,2.67344e-05,0.000908969,0,0,0,2.67344e-05,0,0,0,0.00120305,0,2.67344e-05,0,2.67344e-05,0,0,0,0.00152386,2.67344e-05,0,0,2.67344e-05,0,0,0,0.000160406,0,0,0,2.67344e-05,0,0,0,2.67344e-05,0,0,0,2.67344e-05,0,0,0,0.00104264,0,0,2.67344e-05,0,0,0,0,0.000374282,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,0,0.000401016,5.34688e-05,0,0,0,0,0,0,0.000294078,0,0,0,0,0,0,0,0.00122978,0,0,0,0,0,0,0,0.000106938,0,0,0,2.67344e-05,0,0,0,0.00104264,0,0,0,0,0,0,0,5.34688e-05,0,2.67344e-05,0,2.67344e-05,0,0,0,0.000160406,0,0,0,0,0,0,0,0.000133672,0,0,0,0,0,0,0,8.02032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000213875,0,0,0,0,0,0,0,2.67344e-05,0,0,0,2.67344e-05,0,0,0,0.00024061,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,2.67344e-05,0,0,0,0,0,0.00168427,0,0,0,0,0,0,0,0.00494586,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,2.67344e-05,0,0,0,8.02032e-05,0,0,0,0,0,0,0,0,0,0,0,0.000133672,0,0,0,0,0,0,0,0.000133672,0,0,0,0,0,0,0,8.02032e-05,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0.000133672,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0.00147039,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,2.67344e-05,0,0,2.67344e-05,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000989173,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,8.02032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0456356,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0.00379628,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.02032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00315466,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.02032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000481219,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.02032e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000106938,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0.000133672,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00360914,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.34688e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.67344e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00376955 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleS.csv b/libc/benchmarks/distributions/MemsetGoogleS.csv new file mode 100644 index 0000000000000..ce31d4e0f27de --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleS.csv @@ -0,0 +1 @@ +0,0.235764,0.0320205,0.00038165,0.00568659,0.000362568,0.000209908,0.000190825,0.0593848,0.00148844,0.000286238,7.63301e-05,0.00368292,0.000133578,0.000114495,3.8165e-05,0.122834,0.0382795,1.90825e-05,0.079784,0.00103046,1.90825e-05,3.8165e-05,0.0148844,0.0976834,7.63301e-05,0,1.90825e-05,3.8165e-05,1.90825e-05,0,0.00669796,0.0484314,0.00110679,9.54126e-05,0,1.90825e-05,0.000209908,0.00038165,1.90825e-05,0.0258377,3.8165e-05,1.90825e-05,1.90825e-05,7.63301e-05,0,3.8165e-05,0.0204946,0.00601099,0,5.72475e-05,0,0,0,0,0,0.00318678,3.8165e-05,1.90825e-05,1.90825e-05,1.90825e-05,0,5.72475e-05,1.90825e-05,0.0268491,1.90825e-05,0,0,1.90825e-05,0,1.90825e-05,1.90825e-05,0.00219449,1.90825e-05,5.72475e-05,5.72475e-05,9.54126e-05,0,1.90825e-05,0.000973208,0.00131669,1.90825e-05,1.90825e-05,0,1.90825e-05,1.90825e-05,7.63301e-05,1.90825e-05,0.000801466,0,0,0,0,3.8165e-05,0,3.8165e-05,0.00410274,0,5.72475e-05,1.90825e-05,3.8165e-05,0,1.90825e-05,1.90825e-05,0.000725135,1.90825e-05,0.000133578,0,1.90825e-05,0,1.90825e-05,5.72475e-05,0.00498054,3.8165e-05,0,0,0,1.90825e-05,0,0,0.00139302,1.90825e-05,3.8165e-05,0,0,0,0,0,0.0195596,0,1.90825e-05,0,0.00366384,0,0,0,0.00249981,0,0,0,0,0,0,0.000572475,0.00166018,0.00788108,0,0,0,0,0,0,0.00106862,0,0,0,3.8165e-05,0,0,0,0.0080719,0,1.90825e-05,0,3.8165e-05,0,0,0,0.000343485,0,0,0,1.90825e-05,0,0,0,0.00124036,0,5.72475e-05,0,0,0,0,0,0.000515228,0,0,0,0.000171743,0,0,0,0.00139302,3.8165e-05,0,0,0,0,0,0,0.00427448,0,0,0,1.90825e-05,0,0,0,0.00125945,0,0,1.90825e-05,0.000400733,0,0,0,9.54126e-05,0,0,0,3.8165e-05,0,0,0,0.001851,0,0,0,0,0,0,0,0.000114495,0,1.90825e-05,0,0,0,0,0,0.000114495,0,0,0,0,0,0,0,0.000114495,0,0,0,0,0,0,3.8165e-05,0.0175559,0,0,0,0,0,0,0,0.000324403,0,0,0,0,7.63301e-05,1.90825e-05,0.000133578,0.000591558,0,0,0,0,0,0,0,0.0024044,0,0,0,0,0,0,0,0.00177467,0,0,0,0,0,0,0,5.72475e-05,0,0,0,0,0,0,0,0.000362568,0,0,0,0,0,0,0,0.00015266,0,0,0,0,0,0,0,0.000114495,0,0,0,1.90825e-05,0,0,0,1.90825e-05,0.000706053,0,0,0,0,0,0,1.90825e-05,0,1.90825e-05,0,0,0,3.8165e-05,0,1.90825e-05,0,0,0,0,0,0,1.90825e-05,0.000171743,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0.000343485,0,0,0,3.8165e-05,0,0,0,0,0,0,0,0.000954126,0,0,0,0,0,0,0,0.000324403,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00540035,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000324403,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0.000209908,0,1.90825e-05,0,0,0,0,0,1.90825e-05,0,0,0,1.90825e-05,0,0,0,0.000477063,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0.00267155,0,0,0,0,0,0,0,0.00112587,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00858713,0,0,0,0,0,0,0,0.0227845,0,0,0,0,0,9.54126e-05,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000706053,0,0,0,0,0,0,0,0.000114495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000324403,0,9.54126e-05,0,1.90825e-05,0,1.90825e-05,0,0,0,3.8165e-05,0,5.72475e-05,0,1.90825e-05,0,0,0,5.72475e-05,0,1.90825e-05,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0.000667888,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000343485,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00038165,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000992291,0,0,0,0,0,0,0,0,0.00845355,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00045798,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000553393,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00015266,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.8165e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.63301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.72475e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000114495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00030532,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000133578,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0.000133578,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00341577,0,0,0,0,0,0,0,0.000706053,0,0,0,0,0,0,0,5.72475e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000114495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.63301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.8165e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7.63301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.8165e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.8165e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000973208,0,0,0,0,0,0,0,1.90825e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00068697,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00061064,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00141211 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleU.csv b/libc/benchmarks/distributions/MemsetGoogleU.csv new file mode 100644 index 0000000000000..b23c79ce3d8f0 --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleU.csv @@ -0,0 +1 @@ +0.017497,0.00311245,0.00839099,0.0142163,0.0314399,0.0162562,0.00365923,0.00208198,0.0189691,0.0170133,0.00834893,0.00290215,0.00130386,0.0012618,0.0042691,0.00174549,0.00693992,0.348489,0.00107253,0.120208,0.000651932,0.000778112,0.000988412,0.0530378,0.00498412,0.000399571,0.000504721,0.000630902,0.000630902,0.000252361,0.000588841,0.0434271,0.0878425,0.000336481,0.00018927,0.00012618,0.000231331,0.00010515,0.00012618,0.00010515,0.00454249,6.30902e-05,0.000210301,0.000210301,0.000862232,0.00018927,6.30902e-05,0.0303253,0.00550987,0.00010515,0.00010515,0.000252361,0.000210301,0.000252361,0.0012618,0.00637211,0.00805451,0.00010515,4.20601e-05,0,0.00010515,4.20601e-05,0.00012618,4.20601e-05,0.00780215,0,6.30902e-05,0,6.30902e-05,4.20601e-05,6.30902e-05,2.10301e-05,0.00128283,2.10301e-05,2.10301e-05,2.10301e-05,8.41202e-05,0.00012618,6.30902e-05,0.0146159,0.000525751,2.10301e-05,2.10301e-05,0,0.00012618,6.30902e-05,0,0,0.00254464,0,2.10301e-05,2.10301e-05,6.30902e-05,4.20601e-05,0,6.30902e-05,0.00225022,4.20601e-05,2.10301e-05,6.30902e-05,6.30902e-05,0,2.10301e-05,0,0.000273391,4.20601e-05,0.000862232,0,6.30902e-05,2.10301e-05,0,2.10301e-05,0.00218713,4.20601e-05,0,6.30902e-05,0,2.10301e-05,2.10301e-05,0,0.000441631,0,0,0,6.30902e-05,2.10301e-05,0,2.10301e-05,0.00210301,0,2.10301e-05,0,2.10301e-05,4.20601e-05,2.10301e-05,4.20601e-05,0.00195579,8.41202e-05,0,2.10301e-05,8.41202e-05,4.20601e-05,0,0.00929528,0.00103047,0,0,0,2.10301e-05,0,2.10301e-05,0,0.000357511,0,0,0,0,0.00018927,0.000399571,2.10301e-05,0.0036382,8.41202e-05,4.20601e-05,0,0.000231331,0,0,0,0.00117768,6.30902e-05,2.10301e-05,6.30902e-05,4.20601e-05,0,0,4.20601e-05,0.00018927,0,0,0,2.10301e-05,0,0,0,0.000883262,0,0,0,0,0,4.20601e-05,0,0.000252361,0,0.000546781,0,2.10301e-05,0,0,0,0.00283906,0,0,2.10301e-05,0,4.20601e-05,0,2.10301e-05,0.00391159,0,2.10301e-05,0,0.00016824,2.10301e-05,0,2.10301e-05,0.000462661,0,0,0,2.10301e-05,0,0,0,0.0046897,2.10301e-05,2.10301e-05,0,0,0,0,0,8.41202e-05,0,0,0,0,0,0,0,0.000231331,0,0,2.10301e-05,0,2.10301e-05,0,0,0,0,0,0,2.10301e-05,0,0,2.10301e-05,0.00485794,0,0,2.10301e-05,0,0,0,0,0.000378541,0,0,0,0,0,0,0.00286009,0.00330172,2.10301e-05,0,0,2.10301e-05,0,0,2.10301e-05,0.00206095,0,0,0,0,0,2.10301e-05,0,0.000525751,0,0,2.10301e-05,2.10301e-05,0,0,0,6.30902e-05,0,0,2.10301e-05,0,0,0,0,0.00218713,0,2.10301e-05,0,0,0,2.10301e-05,0,0.00012618,0,2.10301e-05,0,8.41202e-05,0,0,0,0.00010515,4.20601e-05,0,0,0.00018927,0,0,0,0.00012618,0,0,0,0,0,0,0,0.00153519,0,0,0,0,0,0,0,0.00010515,0,0,0,2.10301e-05,0,0,0,0.00016824,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0.000546781,0,0,0,0,0,0,0,0.00525751,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0.000504721,0,0,0,0,0,0,0,8.41202e-05,0,2.10301e-05,0,0,0,0,0,0.00016824,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,2.10301e-05,0,2.10301e-05,0,0,0,0,0,0.000210301,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0.000483691,0,0,0,0,0,0,0,0.00014721,0,0,0,0,0,0,0,0.000210301,0,0,0,2.10301e-05,0,0,0,6.30902e-05,0,0,0,2.10301e-05,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0.00145107,0,0,0,0,0,0,0,0.00018927,0,0,0,0,0,0.00100944,0,4.20601e-05,0,0,0,2.10301e-05,0,0,0,4.20601e-05,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0.00275494,0,0,0,8.41202e-05,0,0,0,0.00010515,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0.00164034,0,0,0,0,0,0,0,2.10301e-05,0,0,0,2.10301e-05,0,0,0,4.20601e-05,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0.00010515,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0.000231331,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00010515,0,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0010515,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00157725,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0.000483691,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00246052,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0.00012618,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.41202e-05,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.20601e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000357511,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0.00012618,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0.000210301,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6.30902e-05,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.10301e-05,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0021661 \ No newline at end of file diff --git a/libc/benchmarks/distributions/MemsetGoogleW.csv b/libc/benchmarks/distributions/MemsetGoogleW.csv new file mode 100644 index 0000000000000..0b03e27accb36 --- /dev/null +++ b/libc/benchmarks/distributions/MemsetGoogleW.csv @@ -0,0 +1 @@ +0,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.675079,0,0.116719,0.00315457,0,0,0.00630915,0.00315457,0,0,0.00315457,0,0,0,0.0126183,0,0,0,0,0,0,0,0,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.022082,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0378549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0126183,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0157729,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00315457,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.022082,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00315457,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0126183 \ No newline at end of file diff --git a/libc/benchmarks/distributions/README.md b/libc/benchmarks/distributions/README.md new file mode 100644 index 0000000000000..135ba7bc82221 --- /dev/null +++ b/libc/benchmarks/distributions/README.md @@ -0,0 +1,34 @@ +# Size distributions for memory functions under specific workloads + +This folder contains a set of files that are included from `libc/benchmarks/MemorySizeDistributions.cpp`. + +Offloading this data to individual files helps + - C++ editors (large arrays are usually not well handled by editors), + - and allows processing data by other tools to perform analysis or graph rendering. + + ## Format + +Most filenames are of the form `{MemoryFunctionName}{WorkloadID}.csv`. They contain a single line of comma separated real values representing the probability that a particular size occurs. e.g. + - `"0,1"` indicates that only the size `1` occurs, + - `"0.5,0.5"` indicates sizes `0` and `1` occur with the same frequency. + + These files usually contains sizes from `0` to `4096` inclusive. To save on space trailing zeros are discarded. + + ## Workloads + +As identified in the [automemcpy](https://research.google/pubs/pub50338/) paper: + - `GoogleA` <-> `service 4` + - `GoogleB` <-> `database 1` + - `GoogleD` <-> `storage` + - `GoogleL` <-> `logging` + - `GoogleM` <-> `service 2` + - `GoogleQ` <-> `database 2` + - `GoogleS` <-> `database 3` + - `GoogleU` <-> `service 3` + - `GoogleW` <-> `service 1` + +`Uniform384To4096` is an additional synthetic workload that simply returns a uniform repartition of the sizes from `384` to `4096` inclusive. + +## Note + +Except for `GoogleD`, all distributions are gathered over one week worth of data. \ No newline at end of file diff --git a/libc/benchmarks/distributions/Uniform384To4096.csv b/libc/benchmarks/distributions/Uniform384To4096.csv new file mode 100644 index 0000000000000..25b1de051ff41 --- /dev/null +++ b/libc/benchmarks/distributions/Uniform384To4096.csv @@ -0,0 +1 @@ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 \ No newline at end of file diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake index 8c4e6bf8cb244..55761ee238fbb 100644 --- a/libc/cmake/modules/LLVMLibCObjectRules.cmake +++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake @@ -1,7 +1,11 @@ set(OBJECT_LIBRARY_TARGET_TYPE "OBJECT_LIBRARY") function(_get_common_compile_options output_var) - set(${output_var} -fpie ${LLVM_CXX_STD_default} -ffreestanding ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN} PARENT_SCOPE) + set(compile_options ${LLVM_CXX_STD_default} ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN}) + if(NOT ${LIBC_TARGET_OS} STREQUAL "windows") + set(compile_options ${compile_options} -fpie -ffreestanding) + endif() + set(${output_var} ${compile_options} PARENT_SCOPE) endfunction() # Rule which is essentially a wrapper over add_library to compile a set of diff --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h index 046ec04f130dc..2b820e4d25eb8 100644 --- a/libc/test/src/math/LdExpTest.h +++ b/libc/test/src/math/LdExpTest.h @@ -121,7 +121,7 @@ class LdExpTestTemplate : public __llvm_libc::testing::Test { FPBits resultBits(result); ASSERT_FALSE(resultBits.isZero()); // Verify that the result is indeed subnormal. - ASSERT_EQ(resultBits.encoding.exponent, uint16_t(0)); + ASSERT_EQ(resultBits.getUnbiasedExponent(), uint16_t(0)); // But if the exp is so less that normalization leads to zero, then // the result should be zero. result = func(x, -FPBits::maxExponent - int(mantissaWidth) - 5); diff --git a/libc/test/src/math/NextAfterTest.h b/libc/test/src/math/NextAfterTest.h index 9c53ab7197185..4fa135d9cb259 100644 --- a/libc/test/src/math/NextAfterTest.h +++ b/libc/test/src/math/NextAfterTest.h @@ -163,31 +163,29 @@ class NextAfterTestTemplate : public __llvm_libc::testing::Test { result = func(x, 0); FPBits xBits = FPBits(x); FPBits resultBits = FPBits(result); - ASSERT_EQ(resultBits.encoding.exponent, - uint16_t(xBits.encoding.exponent - 1)); - ASSERT_EQ(resultBits.encoding.mantissa, + ASSERT_EQ(resultBits.getUnbiasedExponent(), + uint16_t(xBits.getUnbiasedExponent() - 1)); + ASSERT_EQ(resultBits.getMantissa(), (UIntType(1) << MantissaWidth::value) - 1); result = func(x, T(33.0)); resultBits = FPBits(result); - ASSERT_EQ(resultBits.encoding.exponent, xBits.encoding.exponent); - ASSERT_EQ(resultBits.encoding.mantissa, - xBits.encoding.mantissa + UIntType(1)); + ASSERT_EQ(resultBits.getUnbiasedExponent(), xBits.getUnbiasedExponent()); + ASSERT_EQ(resultBits.getMantissa(), xBits.getMantissa() + UIntType(1)); x = -x; result = func(x, 0); resultBits = FPBits(result); - ASSERT_EQ(resultBits.encoding.exponent, - uint16_t(xBits.encoding.exponent - 1)); - ASSERT_EQ(resultBits.encoding.mantissa, + ASSERT_EQ(resultBits.getUnbiasedExponent(), + uint16_t(xBits.getUnbiasedExponent() - 1)); + ASSERT_EQ(resultBits.getMantissa(), (UIntType(1) << MantissaWidth::value) - 1); result = func(x, T(-33.0)); resultBits = FPBits(result); - ASSERT_EQ(resultBits.encoding.exponent, xBits.encoding.exponent); - ASSERT_EQ(resultBits.encoding.mantissa, - xBits.encoding.mantissa + UIntType(1)); + ASSERT_EQ(resultBits.getUnbiasedExponent(), xBits.getUnbiasedExponent()); + ASSERT_EQ(resultBits.getMantissa(), xBits.getMantissa() + UIntType(1)); } }; diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h index c3d035195394a..2dcb2c9a6bf98 100644 --- a/libc/test/src/math/RoundToIntegerTest.h +++ b/libc/test/src/math/RoundToIntegerTest.h @@ -135,9 +135,9 @@ class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test { // We start with 1.0 so that the implicit bit for x86 long doubles // is set. FPBits bits(F(1.0)); - bits.encoding.exponent = exponentLimit + FPBits::exponentBias; - bits.encoding.sign = 1; - bits.encoding.mantissa = 0; + bits.setUnbiasedExponent(exponentLimit + FPBits::exponentBias); + bits.setSign(1); + bits.setMantissa(0); F x = F(bits); long mpfrResult; @@ -199,10 +199,9 @@ class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test { // We start with 1.0 so that the implicit bit for x86 long doubles // is set. FPBits bits(F(1.0)); - bits.encoding.exponent = exponentLimit + FPBits::exponentBias; - bits.encoding.sign = 1; - bits.encoding.mantissa = - UIntType(0x1) << (__llvm_libc::fputil::MantissaWidth::value - 1); + bits.setUnbiasedExponent(exponentLimit + FPBits::exponentBias); + bits.setSign(1); + bits.setMantissa(UIntType(0x1) << (__llvm_libc::fputil::MantissaWidth::value - 1)); F x = F(bits); if (TestModes) { diff --git a/libc/test/src/math/SqrtTest.h b/libc/test/src/math/SqrtTest.h index 56a16bb09754c..77f5374f579b1 100644 --- a/libc/test/src/math/SqrtTest.h +++ b/libc/test/src/math/SqrtTest.h @@ -39,7 +39,7 @@ template class SqrtTest : public __llvm_libc::testing::Test { void testDenormalValues(SqrtFunc func) { for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) { FPBits denormal(T(0.0)); - denormal.encoding.mantissa = mant; + denormal.setMantissa(mant); ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, T(denormal), func(T(denormal)), T(0.5)); diff --git a/libc/utils/FPUtil/BasicOperations.h b/libc/utils/FPUtil/BasicOperations.h index 248f120a89cea..43ccd12fdb70e 100644 --- a/libc/utils/FPUtil/BasicOperations.h +++ b/libc/utils/FPUtil/BasicOperations.h @@ -20,7 +20,7 @@ template ::Value, int> = 0> static inline T abs(T x) { FPBits bits(x); - bits.encoding.sign = 0; + bits.setSign(0); return T(bits); } @@ -33,11 +33,11 @@ static inline T fmin(T x, T y) { return y; } else if (bity.isNaN()) { return x; - } else if (bitx.encoding.sign != bity.encoding.sign) { + } else if (bitx.getSign() != bity.getSign()) { // To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and // y has different signs and both are not NaNs, we return the number // with negative sign. - return (bitx.encoding.sign ? x : y); + return (bitx.getSign() ? x : y); } else { return (x < y ? x : y); } @@ -52,11 +52,11 @@ static inline T fmax(T x, T y) { return y; } else if (bity.isNaN()) { return x; - } else if (bitx.encoding.sign != bity.encoding.sign) { + } else if (bitx.getSign() != bity.getSign()) { // To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and // y has different signs and both are not NaNs, we return the number // with positive sign. - return (bitx.encoding.sign ? y : x); + return (bitx.getSign() ? y : x); } else { return (x > y ? x : y); } diff --git a/libc/utils/FPUtil/DivisionAndRemainderOperations.h b/libc/utils/FPUtil/DivisionAndRemainderOperations.h index 5a1c6566b28d5..d23a8daabbe63 100644 --- a/libc/utils/FPUtil/DivisionAndRemainderOperations.h +++ b/libc/utils/FPUtil/DivisionAndRemainderOperations.h @@ -43,12 +43,13 @@ static inline T remquo(T x, T y, int &q) { return x; } - bool resultSign = (xbits.encoding.sign == ybits.encoding.sign ? false : true); + bool resultSign = (xbits.getSign() == ybits.getSign() ? false : true); // Once we know the sign of the result, we can just operate on the absolute // values. The correct sign can be applied to the result after the result // is evaluated. - xbits.encoding.sign = ybits.encoding.sign = 0; + xbits.setSign(0); + ybits.setSign(0); NormalFloat normalx(xbits), normaly(ybits); int exp = normalx.exponent - normaly.exponent; diff --git a/libc/utils/FPUtil/FPBits.h b/libc/utils/FPUtil/FPBits.h index 2e05c23120292..9ee870dc9983d 100644 --- a/libc/utils/FPUtil/FPBits.h +++ b/libc/utils/FPUtil/FPBits.h @@ -13,48 +13,20 @@ #include "utils/CPP/TypeTraits.h" +#include "FloatProperties.h" #include namespace __llvm_libc { namespace fputil { -template struct MantissaWidth {}; -template <> struct MantissaWidth { - static constexpr unsigned value = 23; -}; -template <> struct MantissaWidth { - static constexpr unsigned value = 52; +template struct MantissaWidth { + static constexpr unsigned value = FloatProperties::mantissaWidth; }; -template struct ExponentWidth {}; -template <> struct ExponentWidth { - static constexpr unsigned value = 8; -}; -template <> struct ExponentWidth { - static constexpr unsigned value = 11; -}; -template <> struct ExponentWidth { - static constexpr unsigned value = 15; +template struct ExponentWidth { + static constexpr unsigned value = FloatProperties::exponentWidth; }; -template struct FPUIntType {}; -template <> struct FPUIntType { using Type = uint32_t; }; -template <> struct FPUIntType { using Type = uint64_t; }; - -#ifdef LONG_DOUBLE_IS_DOUBLE -template <> struct MantissaWidth { - static constexpr unsigned value = MantissaWidth::value; -}; -template <> struct FPUIntType { - using Type = FPUIntType::Type; -}; -#elif !defined(SPECIAL_X86_LONG_DOUBLE) -template <> struct MantissaWidth { - static constexpr unsigned value = 112; -}; -template <> struct FPUIntType { using Type = __uint128_t; }; -#endif - // A generic class to represent single precision, double precision, and quad // precision IEEE 754 floating point formats. // On most platforms, the 'float' type corresponds to single precision floating @@ -70,20 +42,44 @@ template union FPBits { // Reinterpreting bits as an integer value and interpreting the bits of an // integer value as a floating point value is used in tests. So, a convenient // type is provided for such reinterpretations. - using UIntType = typename FPUIntType::Type; - - struct __attribute__((packed)) { - UIntType mantissa : MantissaWidth::value; - uint16_t exponent : ExponentWidth::value; - uint8_t sign : 1; - } encoding; - UIntType integer; + using FloatProp = FloatProperties; + // TODO: Change UintType name to BitsType for consistency. + using UIntType = typename FloatProp::BitsType; + + UIntType bits; + + void setMantissa(UIntType mantVal) { + mantVal &= (FloatProp::mantissaMask); + bits &= ~(FloatProp::mantissaMask); + bits |= mantVal; + } + + UIntType getMantissa() const { return bits & FloatProp::mantissaMask; } + + void setUnbiasedExponent(UIntType expVal) { + expVal = (expVal << (FloatProp::mantissaWidth)) & FloatProp::exponentMask; + bits &= ~(FloatProp::exponentMask); + bits |= expVal; + } + + uint16_t getUnbiasedExponent() const { + return uint16_t((bits & FloatProp::exponentMask) >> + (FloatProp::mantissaWidth)); + } + + void setSign(bool signVal) { + bits &= ~(FloatProp::signMask); + UIntType sign = UIntType(signVal) << (FloatProp::bitWidth - 1); + bits |= sign; + } + + bool getSign() const { + return ((bits & FloatProp::signMask) >> (FloatProp::bitWidth - 1)); + } T val; - static_assert(sizeof(encoding) == sizeof(UIntType), - "Encoding and integral representation have different sizes."); - static_assert(sizeof(integer) == sizeof(UIntType), - "Integral representation and value type have different sizes."); + static_assert(sizeof(T) == sizeof(UIntType), + "Data type and integral representation have different sizes."); static constexpr int exponentBias = (1 << (ExponentWidth::value - 1)) - 1; static constexpr int maxExponent = (1 << ExponentWidth::value) - 1; @@ -104,29 +100,29 @@ template union FPBits { template ::Value, int> = 0> - explicit FPBits(XType x) : integer(x) {} + explicit FPBits(XType x) : bits(x) {} - FPBits() : integer(0) {} + FPBits() : bits(0) {} explicit operator T() { return val; } - UIntType uintval() const { return integer; } + UIntType uintval() const { return bits; } - int getExponent() const { return int(encoding.exponent) - exponentBias; } + int getExponent() const { return int(getUnbiasedExponent()) - exponentBias; } bool isZero() const { - return encoding.mantissa == 0 && encoding.exponent == 0; + return getMantissa() == 0 && getUnbiasedExponent() == 0; } bool isInf() const { - return encoding.mantissa == 0 && encoding.exponent == maxExponent; + return getMantissa() == 0 && getUnbiasedExponent() == maxExponent; } bool isNaN() const { - return encoding.exponent == maxExponent && encoding.mantissa != 0; + return getUnbiasedExponent() == maxExponent && getMantissa() != 0; } - bool isInfOrNaN() const { return encoding.exponent == maxExponent; } + bool isInfOrNaN() const { return getUnbiasedExponent() == maxExponent; } static FPBits zero() { return FPBits(); } @@ -136,19 +132,19 @@ template union FPBits { static FPBits inf() { FPBits bits; - bits.encoding.exponent = maxExponent; + bits.setUnbiasedExponent(maxExponent); return bits; } static FPBits negInf() { FPBits bits = inf(); - bits.encoding.sign = 1; + bits.setSign(1); return bits; } static T buildNaN(UIntType v) { FPBits bits = inf(); - bits.encoding.mantissa = v; + bits.setMantissa(v); return T(bits); } }; diff --git a/libc/utils/FPUtil/FloatProperties.h b/libc/utils/FPUtil/FloatProperties.h index fb0917259b915..ecf2ff10bd027 100644 --- a/libc/utils/FPUtil/FloatProperties.h +++ b/libc/utils/FPUtil/FloatProperties.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H #define LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H +#include "PlatformDefs.h" #include namespace __llvm_libc { @@ -24,10 +25,12 @@ template <> struct FloatProperties { static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; static constexpr uint32_t mantissaWidth = 23; - static constexpr BitsType mantissaMask = 0x007fffffU; - static constexpr BitsType signMask = 0x80000000U; + static constexpr uint32_t exponentWidth = 8; + static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; + static constexpr BitsType signMask = BitsType(1) + << (exponentWidth + mantissaWidth); static constexpr BitsType exponentMask = ~(signMask | mantissaMask); - static constexpr uint32_t exponentOffset = 127; + static constexpr uint32_t exponentBias = 127; // If a number x is a NAN, then it is a quiet NAN if: // QuietNaNMask & bits(x) != 0 @@ -43,10 +46,12 @@ template <> struct FloatProperties { static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; static constexpr uint32_t mantissaWidth = 52; - static constexpr BitsType mantissaMask = 0x000fffffffffffffU; - static constexpr BitsType signMask = 0x8000000000000000ULL; + static constexpr uint32_t exponentWidth = 11; + static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; + static constexpr BitsType signMask = BitsType(1) + << (exponentWidth + mantissaWidth); static constexpr BitsType exponentMask = ~(signMask | mantissaMask); - static constexpr uint32_t exponentOffset = 1023; + static constexpr uint32_t exponentBias = 1023; // If a number x is a NAN, then it is a quiet NAN if: // QuietNaNMask & bits(x) != 0 @@ -54,6 +59,67 @@ template <> struct FloatProperties { static constexpr BitsType quietNaNMask = 0x0008000000000000ULL; }; +#if defined(LONG_DOUBLE_IS_DOUBLE) +// Properties for numbers represented in 64 bits long double on Windows +// platform. +template <> struct FloatProperties { + typedef uint64_t BitsType; + static_assert(sizeof(BitsType) == sizeof(double), + "Unexpected size of 'double' type."); + + static constexpr uint32_t bitWidth = FloatProperties::bitWidth; + + static constexpr uint32_t mantissaWidth = + FloatProperties::mantissaWidth; + static constexpr uint32_t exponentWidth = + FloatProperties::exponentWidth; + static constexpr BitsType mantissaMask = + FloatProperties::mantissaMask; + static constexpr BitsType signMask = FloatProperties::signMask; + static constexpr BitsType exponentMask = + FloatProperties::exponentMask; + static constexpr uint32_t exponentBias = + FloatProperties::exponentBias; +}; +#elif defined(SPECIAL_X86_LONG_DOUBLE) +// Properties for numbers represented in 80 bits long double on non-Windows x86 +// platforms. +template <> struct FloatProperties { + typedef __uint128_t BitsType; + static_assert(sizeof(BitsType) == sizeof(long double), + "Unexpected size of 'long double' type."); + + static constexpr uint32_t bitWidth = (sizeof(BitsType) << 3) - 48; + + static constexpr uint32_t mantissaWidth = 63; + static constexpr uint32_t exponentWidth = 15; + static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; + static constexpr BitsType signMask = BitsType(1) + << (exponentWidth + mantissaWidth + 1); + static constexpr BitsType exponentMask = ((BitsType(1) << exponentWidth) - 1) + << (mantissaWidth + 1); + static constexpr uint32_t exponentBias = 16383; +}; +#else +// Properties for numbers represented in 128 bits long double on non x86 +// platform. +template <> struct FloatProperties { + typedef __uint128_t BitsType; + static_assert(sizeof(BitsType) == sizeof(long double), + "Unexpected size of 'long double' type."); + + static constexpr uint32_t bitWidth = sizeof(BitsType) << 3; + + static constexpr uint32_t mantissaWidth = 112; + static constexpr uint32_t exponentWidth = 15; + static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1; + static constexpr BitsType signMask = BitsType(1) + << (exponentWidth + mantissaWidth); + static constexpr BitsType exponentMask = ~(signMask | mantissaMask); + static constexpr uint32_t exponentBias = 16383; +}; +#endif + // Define the float type corresponding to the BitsType. template struct FloatType; diff --git a/libc/utils/FPUtil/Hypot.h b/libc/utils/FPUtil/Hypot.h index adbd9f531db53..8d108a74761de 100644 --- a/libc/utils/FPUtil/Hypot.h +++ b/libc/utils/FPUtil/Hypot.h @@ -139,27 +139,27 @@ static inline T hypot(T x, T y) { DUIntType a_mant_sq, b_mant_sq; bool sticky_bits; - if ((x_bits.encoding.exponent >= - y_bits.encoding.exponent + MantissaWidth::value + 2) || + if ((x_bits.getUnbiasedExponent() >= + y_bits.getUnbiasedExponent() + MantissaWidth::value + 2) || (y == 0)) { return abs(x); - } else if ((y_bits.encoding.exponent >= - x_bits.encoding.exponent + MantissaWidth::value + 2) || + } else if ((y_bits.getUnbiasedExponent() >= + x_bits.getUnbiasedExponent() + MantissaWidth::value + 2) || (x == 0)) { - y_bits.encoding.sign = 0; + y_bits.setSign(0); return abs(y); } if (x >= y) { - a_exp = x_bits.encoding.exponent; - a_mant = x_bits.encoding.mantissa; - b_exp = y_bits.encoding.exponent; - b_mant = y_bits.encoding.mantissa; + a_exp = x_bits.getUnbiasedExponent(); + a_mant = x_bits.getMantissa(); + b_exp = y_bits.getUnbiasedExponent(); + b_mant = y_bits.getMantissa(); } else { - a_exp = y_bits.encoding.exponent; - a_mant = y_bits.encoding.mantissa; - b_exp = x_bits.encoding.exponent; - b_mant = x_bits.encoding.mantissa; + a_exp = y_bits.getUnbiasedExponent(); + a_mant = y_bits.getMantissa(); + b_exp = x_bits.getUnbiasedExponent(); + b_mant = x_bits.getMantissa(); } out_exp = a_exp; diff --git a/libc/utils/FPUtil/LongDoubleBitsX86.h b/libc/utils/FPUtil/LongDoubleBitsX86.h index 7fd025a2f5907..ce7fdb1b0fa8a 100644 --- a/libc/utils/FPUtil/LongDoubleBitsX86.h +++ b/libc/utils/FPUtil/LongDoubleBitsX86.h @@ -16,10 +16,6 @@ namespace __llvm_libc { namespace fputil { -template <> struct MantissaWidth { - static constexpr unsigned value = 63; -}; - template struct Padding; // i386 padding. @@ -43,25 +39,61 @@ template <> union FPBits { ((UIntType(maxExponent) - 1) << (MantissaWidth::value + 1)) | (UIntType(1) << MantissaWidth::value) | maxSubnormal; - struct __attribute__((packed)) { - UIntType mantissa : MantissaWidth::value; - uint8_t implicitBit : 1; - uint16_t exponent : ExponentWidth::value; - uint8_t sign : 1; - uint64_t padding : Padding::value; - } encoding; - UIntType integer; + using FloatProp = FloatProperties; + + UIntType bits; + + void setMantissa(UIntType mantVal) { + mantVal &= (FloatProp::mantissaMask); + bits &= ~(FloatProp::mantissaMask); + bits |= mantVal; + } + + UIntType getMantissa() const { return bits & FloatProp::mantissaMask; } + + void setUnbiasedExponent(UIntType expVal) { + expVal = (expVal << (FloatProp::bitWidth - 1 - FloatProp::exponentWidth)) & + FloatProp::exponentMask; + bits &= ~(FloatProp::exponentMask); + bits |= expVal; + } + + uint16_t getUnbiasedExponent() const { + return uint16_t((bits & FloatProp::exponentMask) >> + (FloatProp::bitWidth - 1 - FloatProp::exponentWidth)); + } + + void setImplicitBit(bool implicitVal) { + bits &= ~(UIntType(1) << FloatProp::mantissaWidth); + bits |= (UIntType(implicitVal) << FloatProp::mantissaWidth); + } + + bool getImplicitBit() const { + return ((bits & (UIntType(1) << FloatProp::mantissaWidth)) >> + FloatProp::mantissaWidth); + } + + void setSign(bool signVal) { + bits &= ~(FloatProp::signMask); + UIntType sign1 = UIntType(signVal) << (FloatProp::bitWidth - 1); + bits |= sign1; + } + + bool getSign() const { + return ((bits & FloatProp::signMask) >> (FloatProp::bitWidth - 1)); + } + long double val; - FPBits() : integer(0) {} + FPBits() : bits(0) {} template ::Value, int> = 0> - explicit FPBits(XType x) : val(x) {} + explicit FPBits(XType x) : val(x) {} template ::Value, int> = 0> - explicit FPBits(XType x) : integer(x) {} + explicit FPBits(XType x) : bits(x) {} operator long double() { return val; } @@ -71,37 +103,37 @@ template <> union FPBits { (UIntType(1) << (sizeof(long double) * 8 - Padding::value)) - 1; - return integer & mask; + return bits & mask; } int getExponent() const { - if (encoding.exponent == 0) + if (getUnbiasedExponent() == 0) return int(1) - exponentBias; - return int(encoding.exponent) - exponentBias; + return int(getUnbiasedExponent()) - exponentBias; } bool isZero() const { - return encoding.exponent == 0 && encoding.mantissa == 0 && - encoding.implicitBit == 0; + return getUnbiasedExponent() == 0 && getMantissa() == 0 && + getImplicitBit() == 0; } bool isInf() const { - return encoding.exponent == maxExponent && encoding.mantissa == 0 && - encoding.implicitBit == 1; + return getUnbiasedExponent() == maxExponent && getMantissa() == 0 && + getImplicitBit() == 1; } bool isNaN() const { - if (encoding.exponent == maxExponent) { - return (encoding.implicitBit == 0) || encoding.mantissa != 0; - } else if (encoding.exponent != 0) { - return encoding.implicitBit == 0; + if (getUnbiasedExponent() == maxExponent) { + return (getImplicitBit() == 0) || getMantissa() != 0; + } else if (getUnbiasedExponent() != 0) { + return getImplicitBit() == 0; } return false; } bool isInfOrNaN() const { - return (encoding.exponent == maxExponent) || - (encoding.exponent != 0 && encoding.implicitBit == 0); + return (getUnbiasedExponent() == maxExponent) || + (getUnbiasedExponent() != 0 && getImplicitBit() == 0); } // Methods below this are used by tests. @@ -110,30 +142,30 @@ template <> union FPBits { static FPBits negZero() { FPBits bits(0.0l); - bits.encoding.sign = 1; + bits.setSign(1); return bits; } static FPBits inf() { FPBits bits(0.0l); - bits.encoding.exponent = maxExponent; - bits.encoding.implicitBit = 1; + bits.setUnbiasedExponent(maxExponent); + bits.setImplicitBit(1); return bits; } static FPBits negInf() { FPBits bits(0.0l); - bits.encoding.exponent = maxExponent; - bits.encoding.implicitBit = 1; - bits.encoding.sign = 1; + bits.setUnbiasedExponent(maxExponent); + bits.setImplicitBit(1); + bits.setSign(1); return bits; } static long double buildNaN(UIntType v) { FPBits bits(0.0l); - bits.encoding.exponent = maxExponent; - bits.encoding.implicitBit = 1; - bits.encoding.mantissa = v; + bits.setUnbiasedExponent(maxExponent); + bits.setImplicitBit(1); + bits.setMantissa(v); return bits; } }; diff --git a/libc/utils/FPUtil/ManipulationFunctions.h b/libc/utils/FPUtil/ManipulationFunctions.h index 2dfd8e1b71084..545e5f0f24288 100644 --- a/libc/utils/FPUtil/ManipulationFunctions.h +++ b/libc/utils/FPUtil/ManipulationFunctions.h @@ -48,14 +48,13 @@ static inline T modf(T x, T &iptr) { return x; } else if (bits.isInf()) { iptr = x; - return bits.encoding.sign ? T(FPBits::negZero()) : T(FPBits::zero()); + return bits.getSign() ? T(FPBits::negZero()) : T(FPBits::zero()); } else { iptr = trunc(x); if (x == iptr) { // If x is already an integer value, then return zero with the right // sign. - return bits.encoding.sign ? T(FPBits::negZero()) - : T(FPBits::zero()); + return bits.getSign() ? T(FPBits::negZero()) : T(FPBits::zero()); } else { return x - iptr; } @@ -66,7 +65,7 @@ template ::Value, int> = 0> static inline T copysign(T x, T y) { FPBits xbits(x); - xbits.encoding.sign = FPBits(y).encoding.sign; + xbits.setSign(FPBits(y).getSign()); return T(xbits); } @@ -133,11 +132,11 @@ static inline T ldexp(T x, int exp) { // calculating the limit. int expLimit = FPBits::maxExponent + MantissaWidth::value + 1; if (exp > expLimit) - return bits.encoding.sign ? T(FPBits::negInf()) : T(FPBits::inf()); + return bits.getSign() ? T(FPBits::negInf()) : T(FPBits::inf()); // Similarly on the negative side we return zero early if |exp| is too small. if (exp < -expLimit) - return bits.encoding.sign ? T(FPBits::negZero()) : T(FPBits::zero()); + return bits.getSign() ? T(FPBits::negZero()) : T(FPBits::zero()); // For all other values, NormalFloat to T conversion handles it the right way. NormalFloat normal(bits); diff --git a/libc/utils/FPUtil/NearestIntegerOperations.h b/libc/utils/FPUtil/NearestIntegerOperations.h index 5ea4b41ccffbb..a5f7e17d2304b 100644 --- a/libc/utils/FPUtil/NearestIntegerOperations.h +++ b/libc/utils/FPUtil/NearestIntegerOperations.h @@ -43,14 +43,14 @@ static inline T trunc(T x) { // If the exponent is such that abs(x) is less than 1, then return 0. if (exponent <= -1) { - if (bits.encoding.sign) + if (bits.getSign()) return T(-0.0); else return T(0.0); } int trimSize = MantissaWidth::value - exponent; - bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize; + bits.setMantissa((bits.getMantissa() >> trimSize) << trimSize); return T(bits); } @@ -63,7 +63,7 @@ static inline T ceil(T x) { if (bits.isInfOrNaN() || bits.isZero()) return x; - bool isNeg = bits.encoding.sign; + bool isNeg = bits.getSign(); int exponent = bits.getExponent(); // If the exponent is greater than the most negative mantissa @@ -79,7 +79,7 @@ static inline T ceil(T x) { } uint32_t trimSize = MantissaWidth::value - exponent; - bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize; + bits.setMantissa((bits.getMantissa() >> trimSize) << trimSize); T truncValue = T(bits); // If x is already an integer, return it. @@ -97,7 +97,7 @@ template ::Value, int> = 0> static inline T floor(T x) { FPBits bits(x); - if (bits.encoding.sign) { + if (bits.getSign()) { return -ceil(-x); } else { return trunc(x); @@ -114,7 +114,7 @@ static inline T round(T x) { if (bits.isInfOrNaN() || bits.isZero()) return x; - bool isNeg = bits.encoding.sign; + bool isNeg = bits.getSign(); int exponent = bits.getExponent(); // If the exponent is greater than the most negative mantissa @@ -139,8 +139,8 @@ static inline T round(T x) { } uint32_t trimSize = MantissaWidth::value - exponent; - bool halfBitSet = bits.encoding.mantissa & (UIntType(1) << (trimSize - 1)); - bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize; + bool halfBitSet = bits.getMantissa() & (UIntType(1) << (trimSize - 1)); + bits.setMantissa((bits.getMantissa() >> trimSize) << trimSize); T truncValue = T(bits); // If x is already an integer, return it. @@ -166,7 +166,7 @@ static inline T roundUsingCurrentRoundingMode(T x) { if (bits.isInfOrNaN() || bits.isZero()) return x; - bool isNeg = bits.encoding.sign; + bool isNeg = bits.getSign(); int exponent = bits.getExponent(); int roundingMode = getRound(); @@ -184,7 +184,7 @@ static inline T roundUsingCurrentRoundingMode(T x) { case FE_TOWARDZERO: return isNeg ? T(-0.0) : T(0.0); case FE_TONEAREST: - if (exponent <= -2 || bits.encoding.mantissa == 0) + if (exponent <= -2 || bits.getMantissa() == 0) return isNeg ? T(-0.0) : T(0.0); // abs(x) <= 0.5 else return isNeg ? T(-1.0) : T(1.0); // abs(x) > 0.5 @@ -195,19 +195,19 @@ static inline T roundUsingCurrentRoundingMode(T x) { uint32_t trimSize = MantissaWidth::value - exponent; FPBits newBits = bits; - newBits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize; + newBits.setMantissa((bits.getMantissa() >> trimSize) << trimSize); T truncValue = T(newBits); // If x is already an integer, return it. if (truncValue == x) return x; - UIntType trimValue = bits.encoding.mantissa & ((UIntType(1) << trimSize) - 1); + UIntType trimValue = bits.getMantissa() & ((UIntType(1) << trimSize) - 1); UIntType halfValue = (UIntType(1) << (trimSize - 1)); // If exponent is 0, trimSize will be equal to the mantissa width, and // truncIsOdd` will not be correct. So, we handle it as a special case // below. - UIntType truncIsOdd = newBits.encoding.mantissa & (UIntType(1) << trimSize); + UIntType truncIsOdd = newBits.getMantissa() & (UIntType(1) << trimSize); switch (roundingMode) { case FE_DOWNWARD: @@ -255,18 +255,18 @@ static inline I roundedFloatToSignedInteger(F x) { if (bits.isInfOrNaN()) { setDomainErrorAndRaiseInvalid(); - return bits.encoding.sign ? IntegerMin : IntegerMax; + return bits.getSign() ? IntegerMin : IntegerMax; } int exponent = bits.getExponent(); constexpr int exponentLimit = sizeof(I) * 8 - 1; if (exponent > exponentLimit) { setDomainErrorAndRaiseInvalid(); - return bits.encoding.sign ? IntegerMin : IntegerMax; + return bits.getSign() ? IntegerMin : IntegerMax; } else if (exponent == exponentLimit) { - if (bits.encoding.sign == 0 || bits.encoding.mantissa != 0) { + if (bits.getSign() == 0 || bits.getMantissa() != 0) { setDomainErrorAndRaiseInvalid(); - return bits.encoding.sign ? IntegerMin : IntegerMax; + return bits.getSign() ? IntegerMin : IntegerMax; } // If the control reaches here, then it means that the rounded // value is the most negative number for the signed integer type I. diff --git a/libc/utils/FPUtil/NextAfterLongDoubleX86.h b/libc/utils/FPUtil/NextAfterLongDoubleX86.h index 6ae6dfb9f29f7..80ca9ad084cb2 100644 --- a/libc/utils/FPUtil/NextAfterLongDoubleX86.h +++ b/libc/utils/FPUtil/NextAfterLongDoubleX86.h @@ -30,8 +30,8 @@ static inline long double nextafter(long double from, long double to) { return to; // Convert pseudo subnormal number to normal number. - if (fromBits.encoding.implicitBit == 1 && fromBits.encoding.exponent == 0) { - fromBits.encoding.exponent = 1; + if (fromBits.getImplicitBit() == 1 && fromBits.getUnbiasedExponent() == 0) { + fromBits.setUnbiasedExponent(1); } using UIntType = FPBits::UIntType; @@ -46,11 +46,11 @@ static inline long double nextafter(long double from, long double to) { // dealing with the implicit bit. intVal = signVal + FPBits::minNormal; } else if ((intVal & mantissaMask) == mantissaMask) { - fromBits.encoding.mantissa = 0; + fromBits.setMantissa(0); // Incrementing exponent might overflow the value to infinity, // which is what is expected. Since NaNs are handling separately, // it will never overflow "beyond" infinity. - ++fromBits.encoding.exponent; + fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() + 1); return fromBits; } else { ++intVal; @@ -61,10 +61,10 @@ static inline long double nextafter(long double from, long double to) { // dealing with the implicit bit. intVal = signVal + FPBits::maxSubnormal; } else if ((intVal & mantissaMask) == 0) { - fromBits.encoding.mantissa = mantissaMask; + fromBits.setMantissa(mantissaMask); // from == 0 is handled separately so decrementing the exponent will not // lead to underflow. - --fromBits.encoding.exponent; + fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() - 1); return fromBits; } else { --intVal; @@ -80,10 +80,10 @@ static inline long double nextafter(long double from, long double to) { if (intVal == FPBits::minNormal) { intVal = FPBits::maxSubnormal; } else if ((intVal & mantissaMask) == 0) { - fromBits.encoding.mantissa = mantissaMask; + fromBits.setMantissa(mantissaMask); // from == 0 is handled separately so decrementing the exponent will not // lead to underflow. - --fromBits.encoding.exponent; + fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() - 1); return fromBits; } else { --intVal; @@ -92,11 +92,11 @@ static inline long double nextafter(long double from, long double to) { if (intVal == FPBits::maxSubnormal) { intVal = FPBits::minNormal; } else if ((intVal & mantissaMask) == mantissaMask) { - fromBits.encoding.mantissa = 0; + fromBits.setMantissa(0); // Incrementing exponent might overflow the value to infinity, // which is what is expected. Since NaNs are handling separately, // it will never overflow "beyond" infinity. - ++fromBits.encoding.exponent; + fromBits.setUnbiasedExponent(fromBits.getUnbiasedExponent() + 1); return fromBits; } else { ++intVal; diff --git a/libc/utils/FPUtil/NormalFloat.h b/libc/utils/FPUtil/NormalFloat.h index c0fb85746f70a..2d50e88db9167 100644 --- a/libc/utils/FPUtil/NormalFloat.h +++ b/libc/utils/FPUtil/NormalFloat.h @@ -97,7 +97,7 @@ template struct NormalFloat { } FPBits result(T(0.0)); - result.encoding.sign = sign; + result.setSign(sign); constexpr int subnormalExponent = -FPBits::exponentBias + 1; if (exponent < subnormalExponent) { @@ -110,36 +110,36 @@ template struct NormalFloat { const UIntType shiftOutMask = (UIntType(1) << shift) - 1; const UIntType shiftOutValue = mantissa & shiftOutMask; const UIntType halfwayValue = UIntType(1) << (shift - 1); - result.encoding.exponent = 0; - result.encoding.mantissa = mantissa >> shift; - UIntType newMantissa = result.encoding.mantissa; + result.setUnbiasedExponent(0); + result.setMantissa(mantissa >> shift); + UIntType newMantissa = result.getMantissa(); if (shiftOutValue > halfwayValue) { newMantissa += 1; } else if (shiftOutValue == halfwayValue) { // Round to even. - if (result.encoding.mantissa & 0x1) + if (result.getMantissa() & 0x1) newMantissa += 1; } - result.encoding.mantissa = newMantissa; + result.setMantissa(newMantissa); // Adding 1 to mantissa can lead to overflow. This can only happen if // mantissa was all ones (0b111..11). For such a case, we will carry // the overflow into the exponent. if (newMantissa == one) - result.encoding.exponent = 1; + result.setUnbiasedExponent(1); return T(result); } else { return T(result); } } - result.encoding.exponent = exponent + FPBits::exponentBias; - result.encoding.mantissa = mantissa; + result.setUnbiasedExponent(exponent + FPBits::exponentBias); + result.setMantissa(mantissa); return T(result); } private: void initFromBits(FPBits bits) { - sign = bits.encoding.sign; + sign = bits.getSign(); if (bits.isInfOrNaN() || bits.isZero()) { // Ignore special bit patterns. Implementations deal with them separately @@ -150,13 +150,13 @@ template struct NormalFloat { } // Normalize subnormal numbers. - if (bits.encoding.exponent == 0) { - unsigned shift = evaluateNormalizationShift(bits.encoding.mantissa); - mantissa = UIntType(bits.encoding.mantissa) << shift; + if (bits.getUnbiasedExponent() == 0) { + unsigned shift = evaluateNormalizationShift(bits.getMantissa()); + mantissa = UIntType(bits.getMantissa()) << shift; exponent = 1 - FPBits::exponentBias - shift; } else { - exponent = bits.encoding.exponent - FPBits::exponentBias; - mantissa = one | bits.encoding.mantissa; + exponent = bits.getUnbiasedExponent() - FPBits::exponentBias; + mantissa = one | bits.getMantissa(); } } @@ -172,7 +172,7 @@ template struct NormalFloat { #ifdef SPECIAL_X86_LONG_DOUBLE template <> inline void NormalFloat::initFromBits(FPBits bits) { - sign = bits.encoding.sign; + sign = bits.getSign(); if (bits.isInfOrNaN() || bits.isZero()) { // Ignore special bit patterns. Implementations deal with them separately @@ -182,25 +182,24 @@ inline void NormalFloat::initFromBits(FPBits bits) { return; } - if (bits.encoding.exponent == 0) { - if (bits.encoding.implicitBit == 0) { + if (bits.getUnbiasedExponent() == 0) { + if (bits.getImplicitBit() == 0) { // Since we ignore zero value, the mantissa in this case is non-zero. - int normalizationShift = - evaluateNormalizationShift(bits.encoding.mantissa); + int normalizationShift = evaluateNormalizationShift(bits.getMantissa()); exponent = -16382 - normalizationShift; - mantissa = (bits.encoding.mantissa << normalizationShift); + mantissa = (bits.getMantissa() << normalizationShift); } else { exponent = -16382; - mantissa = one | bits.encoding.mantissa; + mantissa = one | bits.getMantissa(); } } else { - if (bits.encoding.implicitBit == 0) { + if (bits.getImplicitBit() == 0) { // Invalid number so just store 0 similar to a NaN. exponent = 0; mantissa = 0; } else { - exponent = bits.encoding.exponent - 16383; - mantissa = one | bits.encoding.mantissa; + exponent = bits.getUnbiasedExponent() - 16383; + mantissa = one | bits.getMantissa(); } } } @@ -214,7 +213,7 @@ template <> inline NormalFloat::operator long double() const { } FPBits result(0.0l); - result.encoding.sign = sign; + result.setSign(sign); constexpr int subnormalExponent = -FPBits::exponentBias + 1; if (exponent < subnormalExponent) { @@ -225,25 +224,25 @@ template <> inline NormalFloat::operator long double() const { const UIntType shiftOutMask = (UIntType(1) << shift) - 1; const UIntType shiftOutValue = mantissa & shiftOutMask; const UIntType halfwayValue = UIntType(1) << (shift - 1); - result.encoding.exponent = 0; - result.encoding.mantissa = mantissa >> shift; - UIntType newMantissa = result.encoding.mantissa; + result.setUnbiasedExponent(0); + result.setMantissa(mantissa >> shift); + UIntType newMantissa = result.getMantissa(); if (shiftOutValue > halfwayValue) { newMantissa += 1; } else if (shiftOutValue == halfwayValue) { // Round to even. - if (result.encoding.mantissa & 0x1) + if (result.getMantissa() & 0x1) newMantissa += 1; } - result.encoding.mantissa = newMantissa; + result.setMantissa(newMantissa); // Adding 1 to mantissa can lead to overflow. This can only happen if // mantissa was all ones (0b111..11). For such a case, we will carry // the overflow into the exponent and set the implicit bit to 1. if (newMantissa == one) { - result.encoding.exponent = 1; - result.encoding.implicitBit = 1; + result.setUnbiasedExponent(1); + result.setImplicitBit(1); } else { - result.encoding.implicitBit = 0; + result.setImplicitBit(0); } return static_cast(result); } else { @@ -251,9 +250,9 @@ template <> inline NormalFloat::operator long double() const { } } - result.encoding.exponent = biasedExponent; - result.encoding.mantissa = mantissa; - result.encoding.implicitBit = 1; + result.setUnbiasedExponent(biasedExponent); + result.setMantissa(mantissa); + result.setImplicitBit(1); return static_cast(result); } #endif // SPECIAL_X86_LONG_DOUBLE diff --git a/libc/utils/FPUtil/Sqrt.h b/libc/utils/FPUtil/Sqrt.h index 2986e8483bde5..b977bc2ef8773 100644 --- a/libc/utils/FPUtil/Sqrt.h +++ b/libc/utils/FPUtil/Sqrt.h @@ -102,7 +102,7 @@ static inline T sqrt(T x) { FPBits bits(x); if (bits.isInfOrNaN()) { - if (bits.encoding.sign && (bits.encoding.mantissa == 0)) { + if (bits.getSign() && (bits.getMantissa() == 0)) { // sqrt(-Inf) = NaN return FPBits::buildNaN(One >> 1); } else { @@ -114,15 +114,15 @@ static inline T sqrt(T x) { // sqrt(+0) = +0 // sqrt(-0) = -0 return x; - } else if (bits.encoding.sign) { + } else if (bits.getSign()) { // sqrt( negative numbers ) = NaN return FPBits::buildNaN(One >> 1); } else { int xExp = bits.getExponent(); - UIntType xMant = bits.encoding.mantissa; + UIntType xMant = bits.getMantissa(); // Step 1a: Normalize denormal input and append hiddent bit to the mantissa - if (bits.encoding.exponent == 0) { + if (bits.getUnbiasedExponent() == 0) { ++xExp; // let xExp be the correct exponent of One bit. internal::normalize(xExp, xMant); } else { diff --git a/libc/utils/FPUtil/SqrtLongDoubleX86.h b/libc/utils/FPUtil/SqrtLongDoubleX86.h index 953c4a476105f..58326183678b8 100644 --- a/libc/utils/FPUtil/SqrtLongDoubleX86.h +++ b/libc/utils/FPUtil/SqrtLongDoubleX86.h @@ -50,7 +50,7 @@ template <> inline long double sqrt(long double x) { FPBits bits(x); if (bits.isInfOrNaN()) { - if (bits.encoding.sign && (bits.encoding.mantissa == 0)) { + if (bits.getSign() && (bits.getMantissa() == 0)) { // sqrt(-Inf) = NaN return FPBits::buildNaN(One >> 1); } else { @@ -62,17 +62,17 @@ template <> inline long double sqrt(long double x) { // sqrt(+0) = +0 // sqrt(-0) = -0 return x; - } else if (bits.encoding.sign) { + } else if (bits.getSign()) { // sqrt( negative numbers ) = NaN return FPBits::buildNaN(One >> 1); } else { int xExp = bits.getExponent(); - UIntType xMant = bits.encoding.mantissa; + UIntType xMant = bits.getMantissa(); // Step 1a: Normalize denormal input - if (bits.encoding.implicitBit) { + if (bits.getImplicitBit()) { xMant |= One; - } else if (bits.encoding.exponent == 0) { + } else if (bits.getUnbiasedExponent() == 0) { internal::normalize(xExp, xMant); } @@ -128,9 +128,9 @@ template <> inline long double sqrt(long double x) { // Extract output FPBits out(0.0L); - out.encoding.exponent = xExp; - out.encoding.implicitBit = 1; - out.encoding.mantissa = (y & (One - 1)); + out.setUnbiasedExponent(xExp); + out.setImplicitBit(1); + out.setMantissa((y & (One - 1))); return out; } diff --git a/libc/utils/FPUtil/TestHelpers.cpp b/libc/utils/FPUtil/TestHelpers.cpp index cfee2bd0e743c..2c7614e93053f 100644 --- a/libc/utils/FPUtil/TestHelpers.cpp +++ b/libc/utils/FPUtil/TestHelpers.cpp @@ -40,7 +40,7 @@ describeValue(const char *label, ValType value, if (bits.isNaN()) { stream << "(NaN)"; } else if (bits.isInf()) { - if (bits.encoding.sign) + if (bits.getSign()) stream << "(-Infinity)"; else stream << "(+Infinity)"; @@ -50,13 +50,14 @@ describeValue(const char *label, ValType value, constexpr int mantissaWidthInHex = (fputil::MantissaWidth::value - 1) / 4 + 1; - stream << "Sign: " << (bits.encoding.sign ? '1' : '0') << ", " + stream << "Sign: " << (bits.getSign() ? '1' : '0') << ", " << "Exponent: 0x" - << uintToHex(bits.encoding.exponent, exponentWidthInHex) + << uintToHex(bits.getUnbiasedExponent(), + exponentWidthInHex) << ", " << "Mantissa: 0x" << uintToHex::UIntType>( - bits.encoding.mantissa, mantissaWidthInHex); + bits.getMantissa(), mantissaWidthInHex); } stream << '\n'; diff --git a/libc/utils/FPUtil/generic/FMA.h b/libc/utils/FPUtil/generic/FMA.h index 9471830af2c7d..269a5073f29f5 100644 --- a/libc/utils/FPUtil/generic/FMA.h +++ b/libc/utils/FPUtil/generic/FMA.h @@ -47,17 +47,17 @@ static inline cpp::EnableIfType::Value, T> fma(T x, T y, // bit of sum, so that the sticky bits used when rounding sum to float are // correct (when it matters). fputil::FPBits t( - (bit_prod.encoding.exponent >= bitz.encoding.exponent) + (bit_prod.getUnbiasedExponent() >= bitz.getUnbiasedExponent()) ? ((double(bit_sum) - double(bit_prod)) - double(bitz)) : ((double(bit_sum) - double(bitz)) - double(bit_prod))); // Update sticky bits if t != 0.0 and the least (52 - 23 - 1 = 28) bits are // zero. - if (!t.isZero() && ((bit_sum.encoding.mantissa & 0xfff'ffffULL) == 0)) { - if (bit_sum.encoding.sign != t.encoding.sign) { - ++bit_sum.encoding.mantissa; - } else if (bit_sum.encoding.mantissa) { - --bit_sum.encoding.mantissa; + if (!t.isZero() && ((bit_sum.getMantissa() & 0xfff'ffffULL) == 0)) { + if (bit_sum.getSign() != t.getSign()) { + bit_sum.setMantissa(bit_sum.getMantissa() + 1); + } else if (bit_sum.getMantissa()) { + bit_sum.setMantissa(bit_sum.getMantissa() - 1); } } } diff --git a/libc/utils/FPUtil/x86_64/FEnv.h b/libc/utils/FPUtil/x86_64/FEnv.h index 47e9dce7508e1..6718ef5f03a1a 100644 --- a/libc/utils/FPUtil/x86_64/FEnv.h +++ b/libc/utils/FPUtil/x86_64/FEnv.h @@ -66,7 +66,7 @@ static inline uint16_t getStatusValueForExcept(int excepts) { // bit flags in the control registers. return (excepts & FE_INVALID ? ExceptionFlags::Invalid : 0) | #ifdef __FE_DENORM - (excepts & __FE_DENORM ? ExceptionFalgs::Denormal : 0) | + (excepts & __FE_DENORM ? ExceptionFlags::Denormal : 0) | #endif // __FE_DENORM (excepts & FE_DIVBYZERO ? ExceptionFlags::DivByZero : 0) | (excepts & FE_OVERFLOW ? ExceptionFlags::Overflow : 0) | @@ -77,7 +77,7 @@ static inline uint16_t getStatusValueForExcept(int excepts) { static inline int exceptionStatusToMacro(uint16_t status) { return (status & ExceptionFlags::Invalid ? FE_INVALID : 0) | #ifdef __FE_DENORM - (status & ExceptionFalgs::Denormal ? __FE_DENORM : 0) | + (status & ExceptionFlags::Denormal ? __FE_DENORM : 0) | #endif // __FE_DENORM (status & ExceptionFlags::DivByZero ? FE_DIVBYZERO : 0) | (status & ExceptionFlags::Overflow ? FE_OVERFLOW : 0) | diff --git a/libc/utils/UnitTest/LibcTest.h b/libc/utils/UnitTest/LibcTest.h index d50f88d191a7e..f72d6c17fd5c7 100644 --- a/libc/utils/UnitTest/LibcTest.h +++ b/libc/utils/UnitTest/LibcTest.h @@ -380,12 +380,12 @@ template using TypeList = internal::TypeList; if (!EXPECT_DEATH(FUNC, EXIT)) \ return +#endif // ENABLE_SUBPROCESS_TESTS + #define __CAT1(a, b) a##b #define __CAT(a, b) __CAT1(a, b) #define UNIQUE_VAR(prefix) __CAT(prefix, __LINE__) -#endif // ENABLE_SUBPROCESS_TESTS - #define EXPECT_THAT(MATCH, MATCHER) \ do { \ auto UNIQUE_VAR(__matcher) = (MATCHER); \ diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 5a944358a3392..10959ee6cbe64 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -144,6 +144,13 @@ set( CMAKE_CLC_ARCHIVE ${LLVM_LINK} ) set( CMAKE_LLAsm_PREPROCESSOR ${LLVM_CLANG} ) set( CMAKE_LLAsm_COMPILER ${LLVM_AS} ) set( CMAKE_LLAsm_ARCHIVE ${LLVM_LINK} ) + +# LLVM 13 enables standard includes by default +if( ${LLVM_VERSION} VERSION_GREATER "12.99.99" ) + set( CMAKE_LLAsm_FLAGS ${CMAKE_LLAsm_FLAGS} -cl-no-stdinc ) + set( CMAKE_CLC_FLAGS ${CMAKE_CLC_FLAGS} -cl-no-stdinc ) +endif() + enable_language( CLC LLAsm ) # Configure prepare_builtins diff --git a/libclc/generic/include/as_type.h b/libclc/generic/include/as_type.h index 0e31dc4bdd796..51f347b4b5cbe 100644 --- a/libclc/generic/include/as_type.h +++ b/libclc/generic/include/as_type.h @@ -1,12 +1,89 @@ #ifndef CLC_AS_TYPE #define CLC_AS_TYPE +#define as_char(x) __builtin_astype(x, char) #define as_schar(x) __builtin_astype(x, schar) +#define as_uchar(x) __builtin_astype(x, uchar) +#define as_short(x) __builtin_astype(x, short) +#define as_ushort(x) __builtin_astype(x, ushort) +#define as_int(x) __builtin_astype(x, int) +#define as_uint(x) __builtin_astype(x, uint) +#define as_long(x) __builtin_astype(x, long) +#define as_ulong(x) __builtin_astype(x, ulong) +#define as_float(x) __builtin_astype(x, float) + +#define as_char2(x) __builtin_astype(x, char2) #define as_schar2(x) __builtin_astype(x, schar2) +#define as_uchar2(x) __builtin_astype(x, uchar2) +#define as_short2(x) __builtin_astype(x, short2) +#define as_ushort2(x) __builtin_astype(x, ushort2) +#define as_int2(x) __builtin_astype(x, int2) +#define as_uint2(x) __builtin_astype(x, uint2) +#define as_long2(x) __builtin_astype(x, long2) +#define as_ulong2(x) __builtin_astype(x, ulong2) +#define as_float2(x) __builtin_astype(x, float2) + +#define as_char3(x) __builtin_astype(x, char3) #define as_schar3(x) __builtin_astype(x, schar3) +#define as_uchar3(x) __builtin_astype(x, uchar3) +#define as_short3(x) __builtin_astype(x, short3) +#define as_ushort3(x) __builtin_astype(x, ushort3) +#define as_int3(x) __builtin_astype(x, int3) +#define as_uint3(x) __builtin_astype(x, uint3) +#define as_long3(x) __builtin_astype(x, long3) +#define as_ulong3(x) __builtin_astype(x, ulong3) +#define as_float3(x) __builtin_astype(x, float3) + +#define as_char4(x) __builtin_astype(x, char4) #define as_schar4(x) __builtin_astype(x, schar4) +#define as_uchar4(x) __builtin_astype(x, uchar4) +#define as_short4(x) __builtin_astype(x, short4) +#define as_ushort4(x) __builtin_astype(x, ushort4) +#define as_int4(x) __builtin_astype(x, int4) +#define as_uint4(x) __builtin_astype(x, uint4) +#define as_long4(x) __builtin_astype(x, long4) +#define as_ulong4(x) __builtin_astype(x, ulong4) +#define as_float4(x) __builtin_astype(x, float4) + +#define as_char8(x) __builtin_astype(x, char8) #define as_schar8(x) __builtin_astype(x, schar8) +#define as_uchar8(x) __builtin_astype(x, uchar8) +#define as_short8(x) __builtin_astype(x, short8) +#define as_ushort8(x) __builtin_astype(x, ushort8) +#define as_int8(x) __builtin_astype(x, int8) +#define as_uint8(x) __builtin_astype(x, uint8) +#define as_long8(x) __builtin_astype(x, long8) +#define as_ulong8(x) __builtin_astype(x, ulong8) +#define as_float8(x) __builtin_astype(x, float8) + +#define as_char16(x) __builtin_astype(x, char16) #define as_schar16(x) __builtin_astype(x, schar16) +#define as_uchar16(x) __builtin_astype(x, uchar16) +#define as_short16(x) __builtin_astype(x, short16) +#define as_ushort16(x) __builtin_astype(x, ushort16) +#define as_int16(x) __builtin_astype(x, int16) +#define as_uint16(x) __builtin_astype(x, uint16) +#define as_long16(x) __builtin_astype(x, long16) +#define as_ulong16(x) __builtin_astype(x, ulong16) +#define as_float16(x) __builtin_astype(x, float16) + +#ifdef cl_khr_fp64 +#define as_double(x) __builtin_astype(x, double) +#define as_double2(x) __builtin_astype(x, double2) +#define as_double3(x) __builtin_astype(x, double3) +#define as_double4(x) __builtin_astype(x, double4) +#define as_double8(x) __builtin_astype(x, double8) +#define as_double16(x) __builtin_astype(x, double16) +#endif + +#ifdef cl_khr_fp16 +#define as_half(x) __builtin_astype(x, half) +#define as_half2(x) __builtin_astype(x, half2) +#define as_half3(x) __builtin_astype(x, half3) +#define as_half4(x) __builtin_astype(x, half4) +#define as_half8(x) __builtin_astype(x, half8) +#define as_half16(x) __builtin_astype(x, half16) +#endif #ifdef __CLC_HAS_FLOAT16 #define as_float16_t(x) __builtin_astype(x, __clc_float16_t) diff --git a/libclc/generic/include/clc/clc.h b/libclc/generic/include/clc/clc.h index faa450519d8fa..8ff94f8c89ea8 100644 --- a/libclc/generic/include/clc/clc.h +++ b/libclc/generic/include/clc/clc.h @@ -205,6 +205,7 @@ #include /* 6.11.8 Synchronization Functions */ +#include #include /* 6.11.9 Explicit Memory Fence Functions */ diff --git a/libclc/generic/include/clc/float/definitions.h b/libclc/generic/include/clc/float/definitions.h index 7e46d45221406..15d436b26484e 100644 --- a/libclc/generic/include/clc/float/definitions.h +++ b/libclc/generic/include/clc/float/definitions.h @@ -1,4 +1,7 @@ #define MAXFLOAT 0x1.fffffep127f +#define HUGE_VALF __builtin_huge_valf() +#define INFINITY __builtin_inff() +#define NAN __builtin_nanf("") #define FLT_DIG 6 #define FLT_MANT_DIG 24 @@ -7,15 +10,35 @@ #define FLT_MIN_10_EXP -37 #define FLT_MIN_EXP -125 #define FLT_RADIX 2 +#define FLT_MAX MAXFLOAT #define FLT_MIN 0x1.0p-126f #define FLT_EPSILON 0x1.0p-23f +#define FP_ILOGB0 (-2147483647 - 1) +#define FP_ILOGBNAN 2147483647 + +#define M_E_F 0x1.5bf0a8p+1f +#define M_LOG2E_F 0x1.715476p+0f +#define M_LOG10E_F 0x1.bcb7b2p-2f +#define M_LN2_F 0x1.62e430p-1f +#define M_LN10_F 0x1.26bb1cp+1f +#define M_PI_F 0x1.921fb6p+1f +#define M_PI_2_F 0x1.921fb6p+0f +#define M_PI_4_F 0x1.921fb6p-1f +#define M_1_PI_F 0x1.45f306p-2f +#define M_2_PI_F 0x1.45f306p-1f +#define M_2_SQRTPI_F 0x1.20dd76p+0f +#define M_SQRT2_F 0x1.6a09e6p+0f +#define M_SQRT1_2_F 0x1.6a09e6p-1f + #ifdef __CLC_INTERNAL #define M_LOG210_F 0x1.a934f0p+1f #endif #ifdef cl_khr_fp64 +#define HUGE_VAL __builtin_huge_val() + #define DBL_DIG 15 #define DBL_MANT_DIG 53 #define DBL_MAX_10_EXP +308 @@ -56,6 +79,9 @@ #define HALF_MIN_EXP -13 #define HALF_RADIX 2 +#define HALF_MAX 0x1.ffcp15h +#define HALF_MIN 0x1.0p-14h +#define HALF_EPSILON 0x1.0p-10h #define HALF_MAX_SQRT 0x1.0p+8h #define HALF_MIN_SQRT 0x1.0p-8h diff --git a/libclc/generic/include/clc/image/image_defines.h b/libclc/generic/include/clc/image/image_defines.h index 934386c14470b..0b3350b7694d7 100644 --- a/libclc/generic/include/clc/image/image_defines.h +++ b/libclc/generic/include/clc/image/image_defines.h @@ -30,7 +30,20 @@ #define CLK_RGx 0x10BB #define CLK_RGBx 0x10BC -/* sampler masks */ +/* sampler normalized coords */ +#define CLK_NORMALIZED_COORDS_FALSE 0x0000 +#define CLK_NORMALIZED_COORDS_TRUE 0x0001 +#define __CLC_NORMALIZED_COORDS_MASK 0x0001 + +/* sampler addressing mode */ +#define CLK_ADDRESS_NONE 0x0000 +#define CLK_ADDRESS_CLAMP_TO_EDGE 0x0002 +#define CLK_ADDRESS_CLAMP 0x0004 +#define CLK_ADDRESS_REPEAT 0x0006 +#define CLK_ADDRESS_MIRRORED_REPEAT 0x0008 #define __CLC_ADDRESS_MASK 0x000E + +/* sampler filter mode */ +#define CLK_FILTER_NEAREST 0x0000 +#define CLK_FILTER_LINEAR 0x0010 #define __CLC_FILTER_MASK 0x0010 -#define __CLC_NORMALIZED_COORDS_MASK 0x0001 diff --git a/libclc/generic/include/clc/integer/definitions.h b/libclc/generic/include/clc/integer/definitions.h index 5d3a6508a6c7d..0079c30123db8 100644 --- a/libclc/generic/include/clc/integer/definitions.h +++ b/libclc/generic/include/clc/integer/definitions.h @@ -1,10 +1,14 @@ #define CHAR_BIT 8 #define INT_MAX 2147483647 +#define INT_MIN (-2147483647 - 1) #define LONG_MAX 0x7fffffffffffffffL +#define LONG_MIN (-0x7fffffffffffffffL - 1) #define CHAR_MAX SCHAR_MAX #define CHAR_MIN SCHAR_MIN #define SCHAR_MAX 127 +#define SCHAR_MIN (-127 - 1) #define SHRT_MAX 32767 +#define SHRT_MIN (-32767 - 1) #define UCHAR_MAX 255 #define USHRT_MAX 65535 #define UINT_MAX 0xffffffff diff --git a/libclc/generic/include/clc/synchronization/cl_mem_fence_flags.h b/libclc/generic/include/clc/synchronization/cl_mem_fence_flags.h new file mode 100644 index 0000000000000..c57eb4249a413 --- /dev/null +++ b/libclc/generic/include/clc/synchronization/cl_mem_fence_flags.h @@ -0,0 +1,4 @@ +typedef uint cl_mem_fence_flags; + +#define CLK_LOCAL_MEM_FENCE 1 +#define CLK_GLOBAL_MEM_FENCE 2 diff --git a/libclc/generic/include/macros.h b/libclc/generic/include/macros.h index 6e1c5ceddff6b..ba70db7365e5a 100644 --- a/libclc/generic/include/macros.h +++ b/libclc/generic/include/macros.h @@ -14,4 +14,10 @@ #define NULL ((void*)0) +#define __kernel_exec(X, typen) __kernel \ + __attribute__((work_group_size_hint(X, 1, 1))) \ + __attribute__((vec_type_hint(typen))) + +#define kernel_exec(X, typen) __kernel_exec(X, typen) + #endif // CLC_MACROS diff --git a/libclc/generic/include/spirv/image/image_defines.h b/libclc/generic/include/spirv/image/image_defines.h index 1f002b86206ab..07a02e11fb470 100644 --- a/libclc/generic/include/spirv/image/image_defines.h +++ b/libclc/generic/include/spirv/image/image_defines.h @@ -38,7 +38,20 @@ #define CLK_RGx 0x10BB #define CLK_RGBx 0x10BC -/* sampler masks */ +/* sampler normalized coords */ +#define CLK_NORMALIZED_COORDS_FALSE 0x0000 +#define CLK_NORMALIZED_COORDS_TRUE 0x0001 +#define __SPIRV_NORMALIZED_COORDS_MASK 0x0001 + +/* sampler addressing mode */ +#define CLK_ADDRESS_NONE 0x0000 +#define CLK_ADDRESS_CLAMP_TO_EDGE 0x0002 +#define CLK_ADDRESS_CLAMP 0x0004 +#define CLK_ADDRESS_REPEAT 0x0006 +#define CLK_ADDRESS_MIRRORED_REPEAT 0x0008 #define __SPIRV_ADDRESS_MASK 0x000E + +/* sampler filter mode */ +#define CLK_FILTER_NEAREST 0x0000 +#define CLK_FILTER_LINEAR 0x0010 #define __SPIRV_FILTER_MASK 0x0010 -#define __SPIRV_NORMALIZED_COORDS_MASK 0x0001 diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index ab1a5b5361a7c..80c240dfc0b0d 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -251,7 +251,7 @@ option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF) # Target options -------------------------------------------------------------- option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++." ${LLVM_BUILD_32_BITS}) -set(LIBCXX_TARGET_TRIPLE "" CACHE STRING "Use alternate target triple.") +set(LIBCXX_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" CACHE STRING "Use alternate target triple.") set(LIBCXX_SYSROOT "" CACHE STRING "Use alternate sysroot.") set(LIBCXX_GCC_TOOLCHAIN "" CACHE STRING "Use alternate GCC toolchain.") @@ -407,9 +407,12 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1") set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1") - set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1") - set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1") + set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + "Path where built libc++ libraries should be installed.") + set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1" CACHE PATH + "Path where target-agnostic libc++ headers should be installed.") + set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE PATH + "Path where target-specific libc++ headers should be installed.") if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBCXX_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) string(APPEND LIBCXX_INSTALL_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) @@ -418,16 +421,22 @@ elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1") set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}") - set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX}) - set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1") - set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}") + set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH + "Path where built libc++ libraries should be installed.") + set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1" CACHE PATH + "Path where target-agnostic libc++ headers should be installed.") + set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}" CACHE PATH + "Path where target-specific libc++ headers should be installed.") else() set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX}) set(LIBCXX_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1") set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}") - set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX}) - set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1") - set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}") + set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH + "Path where built libc++ libraries should be installed.") + set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1" CACHE PATH + "Path where target-agnostic libc++ headers should be installed.") + set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}" CACHE PATH + "Path where target-specific libc++ headers should be installed.") endif() file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}") @@ -456,25 +465,21 @@ include(HandleLibcxxFlags) add_target_flags_if(LIBCXX_BUILD_32_BITS "-m32") if(LIBCXX_TARGET_TRIPLE) - add_target_flags("--target=${LIBCXX_TARGET_TRIPLE}") + add_target_flags_if_supported("--target=${LIBCXX_TARGET_TRIPLE}") elseif(CMAKE_CXX_COMPILER_TARGET) set(LIBCXX_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}") endif() if(LIBCXX_SYSROOT) - add_target_flags("--sysroot=${LIBCXX_SYSROOT}") + add_target_flags_if_supported("--sysroot=${LIBCXX_SYSROOT}") elseif(CMAKE_SYSROOT) set(LIBCXX_SYSROOT "${CMAKE_SYSROOT}") endif() if(LIBCXX_GCC_TOOLCHAIN) - add_target_flags("--gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") + add_target_flags_if_supported("--gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN) set(LIBCXX_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}") endif() -if(LIBCXX_TARGET_TRIPLE) - set(TARGET_TRIPLE "${LIBCXX_TARGET_TRIPLE}") -endif() - # Configure compiler. include(config-ix) @@ -921,6 +926,7 @@ endfunction() #=============================================================================== add_subdirectory(include) add_subdirectory(src) +add_subdirectory(utils) set(LIBCXX_TEST_DEPS "") diff --git a/libcxx/cmake/Modules/HandleLibcxxFlags.cmake b/libcxx/cmake/Modules/HandleLibcxxFlags.cmake index a5b4df6600ee3..859cfc4a51559 100644 --- a/libcxx/cmake/Modules/HandleLibcxxFlags.cmake +++ b/libcxx/cmake/Modules/HandleLibcxxFlags.cmake @@ -121,6 +121,17 @@ macro(add_target_flags_if condition) endif() endmacro() +# Add all the flags supported by the compiler to all of +# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXX_COMPILE_FLAGS' +# and 'LIBCXX_LINK_FLAGS'. +macro(add_target_flags_if_supported) + foreach(flag ${ARGN}) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG") + add_target_flags_if(LIBCXX_SUPPORTS_${flagname}_FLAG ${flag}) + endforeach() +endmacro() + # Add a specified list of flags to both 'LIBCXX_COMPILE_FLAGS' and # 'LIBCXX_LINK_FLAGS'. macro(add_flags) diff --git a/libcxx/docs/AddingNewCIJobs.rst b/libcxx/docs/AddingNewCIJobs.rst index 4a07393096b16..bd94a9d709211 100644 --- a/libcxx/docs/AddingNewCIJobs.rst +++ b/libcxx/docs/AddingNewCIJobs.rst @@ -32,14 +32,15 @@ An example of a job definition is: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost limit: 2 -If you've created your own agents, you should provide the tag that you used -when creating them in the ``queue`` entry -- this will instruct Buildkite to -run that job only on agents that have that tag. +If you create your own agents, put them in the ``libcxx-builders`` queue and +use agent tags to allow targetting your agents from the Buildkite pipeline +config appropriately. We try to keep the pipeline definition file as simple as possible, and to keep any script used for CI inside ``libcxx/utils/ci``. This ensures that diff --git a/libcxx/docs/BuildingLibcxx.rst b/libcxx/docs/BuildingLibcxx.rst index 629e4c8355ba5..34e82f2bc01da 100644 --- a/libcxx/docs/BuildingLibcxx.rst +++ b/libcxx/docs/BuildingLibcxx.rst @@ -251,6 +251,28 @@ libc++ specific options This option can be used to enable or disable the filesystem components on platforms that may not support them. For example on Windows. +.. option:: LIBCXX_INSTALL_LIBRARY_DIR:PATH + + **Default**: ``lib${LIBCXX_LIBDIR_SUFFIX}`` + + Path where built libc++ libraries should be installed. If a relative path, + relative to ``CMAKE_INSTALL_PREFIX``. + +.. option:: LIBCXX_INSTALL_INCLUDE_DIR:PATH + + **Default**: ``include/c++/v1`` + + Path where target-agnostic libc++ headers should be installed. If a relative + path, relative to ``CMAKE_INSTALL_PREFIX``. + +.. option:: LIBCXX_INSTALL_INCLUDE_TARGET_DIR:PATH + + **Default**: ``include/c++/v1`` or + ``include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1`` + + Path where target-specific libc++ headers should be installed. If a relative + path, relative to ``CMAKE_INSTALL_PREFIX``. + .. _libc++experimental options: libc++experimental Specific Options diff --git a/libcxx/docs/Contributing.rst b/libcxx/docs/Contributing.rst index 6bad6a656115c..0cf752f7cc907 100644 --- a/libcxx/docs/Contributing.rst +++ b/libcxx/docs/Contributing.rst @@ -4,15 +4,13 @@ Contributing to libc++ ====================== -.. contents:: - :local: +This file contains notes about various tasks and processes specific to contributing +to libc++. If this is your first time contributing, please also read `this document +`__ on general rules for contributing to LLVM. -Please read `this document `__ on general rules to contribute to LLVM projects. - -Tasks and processes -=================== - -This file contains notes about various tasks and processes specific to libc++. +For libc++, please make sure you follow `these instructions `_ +for submitting a code review from the command-line using ``arc``, since we have some +automation (e.g. CI) that depends on the review being submitted that way. Looking for pre-existing reviews ================================ @@ -24,36 +22,33 @@ and clicking on ``Libc++ Open Reviews`` in the sidebar to the left. If you see that your feature is already being worked on, please consider chiming in instead of duplicating work! -Post-Release TODO -================= +Pre-commit check list +===================== -After branching for an LLVM release: +Before committing or creating a review, please go through this check-list to make +sure you don't forget anything: -1. Update ``_LIBCPP_VERSION`` in ``include/__config`` -2. Update the ``include/__libcpp_version`` file -3. Update the version number in ``docs/conf.py`` +- Do you have tests for every public class and/or function you're adding or modifying? +- Did you update the synopsis of the relevant headers? +- Did you update the relevant files to track implementation status (in ``docs/Status/``)? +- If you added a header: -Modifying feature-test macros -============================= + - Did you add it to ``include/module.modulemap``? + - Did you add it to ``include/CMakeLists.txt``? + - If it's a public header, did you add a test under ``test/libcxx`` that the new header defines ``_LIBCPP_VERSION``? See ``test/libcxx/algorithms/version.pass.cpp`` for an example. NOTE: This should be automated. + - If it's a public header, did you update ``utils/generate_header_inclusion_tests.py``? -When adding or updating feature-test macros, you should update the corresponding tests. -To do that, modify ``feature_test_macros`` table in the script -``utils/generate_feature_test_macro_components.py``, run it, and commit updated -files. Running ``utils/generate_feature_test_macro_components.py`` should never -generate diffs in a clean checkout; feel free to run it in your local checkout -any time you want. +- Did you add the relevant feature test macro(s) for your feature? Did you update the ``generate_feature_test_macro_components.py`` script with it? +- Did you run the ``libcxx-generate-files`` target and verify its output? +Post-release check list +======================= -Adding a new header TODO -======================== - -When adding a new header to libc++: +After branching for an LLVM release: -1. Add a test under ``test/libcxx`` that the new header defines ``_LIBCPP_VERSION``. See ``test/libcxx/algorithms/version.pass.cpp`` for an example. -2. Run ``python utils/generate_header_tests.py``; verify and commit the changes. -3. Modify ``python utils/generate_header_inclusion_tests.py``; run it; verify and commit the changes. -4. Create a submodule in ``include/module.modulemap`` for the new header. -5. Update the ``include/CMakeLists.txt`` file to include the new header. +1. Update ``_LIBCPP_VERSION`` in ``include/__config`` +2. Update the ``include/__libcpp_version`` file +3. Update the version number in ``docs/conf.py`` Exporting new symbols from the library ====================================== diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv index 55ec1836480f2..4ee8d0d74b1d1 100644 --- a/libcxx/docs/Status/RangesPaper.csv +++ b/libcxx/docs/Status/RangesPaper.csv @@ -77,12 +77,12 @@ Section,Description,Dependencies,Assignee,Complete [move.sentinel],,[predef.iterators],Unassigned,Not started [common.iterator],,"| [iterator.concepts] | [iterator.cust.swap] -| [iterator.cust.move]",Zoe Carver,Not started -[default.sentinels],std::default_sentinel_t.,No dependencies,Unassigned,Not started +| [iterator.cust.move]",Zoe Carver,In Progress +[default.sentinels],std::default_sentinel_t.,No dependencies,Zoe Carver,✅ [counted.iterator],,"| [iterator.concepts] | [iterator.cust.swap] | [iterator.cust.move] -| [default.sentinels]",Unassigned,Not started +| [default.sentinels]",Zoe Carver,In Progress [stream.iterators],,[default.sentinels],Unassigned,Not started `[range.access] `_,"| `ranges::begin `_ | `ranges::end `_ @@ -119,31 +119,31 @@ Section,Description,Dependencies,Assignee,Complete | `ranges::bidirectional_range `_ | `ranges::random_access_range `_ | ranges::contiguous_range -| `ranges::common_range `_ -| ranges::viewable_range",[range.range],Christopher Di Bella,In progress +| `ranges::common_range `_",[range.range],Christopher Di Bella,✅ +`[range.refinements]`_,`ranges::viewable_range `_,[range.range],Louis Dionne,✅ `[range.utility.helpers] `_,"| *simple-view* | *has-arrow* | *not-same-as*","| [range.range] -| [iterator.concept.input]",Zoe Carver,In progress +| [iterator.concept.input]",Zoe Carver,✅ `[view.interface] `_,"`ranges::view_interface `_","| [ranges.range] | [range.view] | [range.iterator.op.prev] -| [range.refinements]",Zoe Carver,In progress -`[range.subrange] `_,`ranges::subrange `_,[view.interface],Zoe Carver,In progress +| [range.refinements]",Zoe Carver,✅ +`[range.subrange] `_,`ranges::subrange `_,[view.interface],Zoe Carver,✅ `[range.dangling] `_,"| ranges::dangling | ranges::borrowed_iterator_t | ranges::borrowed_subrange_t","| [range.range] | [range.subrange]",Unassigned,Not started -`[range.all] `_,`view::all `_,"[range.subrange], [range.view.ref]",Zoe Carver,In progress -`[range.view.ref] `_,`ref-view `_,[view.interface],Zoe Carver,In progress +`[range.all] `_,`view::all `_,"[range.subrange], [range.view.ref]",Zoe Carver,✅ +`[range.view.ref] `_,`ref-view `_,[view.interface],Zoe Carver,✅ `[range.filter] `_,filter_view,[range.all],Louis Dionne,Not started `[range.transform] `_,`transform_view `_,[range.all],Zoe Carver,✅ `[range.iota] `_,iota_view,[range.all],Louis Dionne,Not started -`[range.take] `_,take_view,[range.all],Zoe Carver,Not started +`[range.take] `_,take_view,[range.all],Zoe Carver,In Progress `[range.join] `_,join_view,[range.all],Christopher Di Bella,Not started `[range.empty] `_,`empty_view `_,[view.interface],Zoe Carver,✅ `[range.single] `_,single_view,[view.interface],Unassigned,Not started `[range.split] `_,split_view,[range.all],Unassigned,Not started -`[range.counted] `_,view::counted,[range.subrange],Unassigned,Not started -`[range.common] `_,common_view,[range.all],Zoe Carver,Not started +`[range.counted] `_,view::counted,[range.subrange],Zoe Carver,Not started +`[range.common] `_,common_view,[range.all],Zoe Carver,In Progress `[range.reverse] `_,reverse_view,[range.all],Unassigned,Not started diff --git a/libcxx/docs/index.rst b/libcxx/docs/index.rst index a6e9bc647ea1d..d4205a1bcc275 100644 --- a/libcxx/docs/index.rst +++ b/libcxx/docs/index.rst @@ -125,8 +125,10 @@ systems that provide incomplete support. However, libc++ aims to provide a high-quality implementation of the C++ Standard Library, especially when it comes to correctness. As such, we aim to have test coverage for all the platforms and compilers that we claim to support. If a platform or compiler -is not listed here, it is not officially supported. It may happen to work, but we don't -make any guarantees. If you would like your compiler and/or platform to be listed here, +is not listed here, it is not officially supported. It may happen to work, and +in practice the library is known to work on some platforms not listed here, but +we don't make any guarantees. If you would like your compiler and/or platform +to be formally supported and listed here, please work with the libc++ team to set up testing for your configuration. diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h index 4f2228c893d76..e35a372b42678 100644 --- a/libcxx/include/__iterator/wrap_iter.h +++ b/libcxx/include/__iterator/wrap_iter.h @@ -164,6 +164,13 @@ class __wrap_iter template friend class _LIBCPP_TEMPLATE_VIS span; }; +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return __x.base() == __y.base(); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -171,6 +178,17 @@ bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) return __x.base() == __y.base(); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ +#if _LIBCPP_DEBUG_LEVEL == 2 + _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), + "Attempted to compare incomparable iterators"); +#endif + return __x.base() < __y.base(); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -182,6 +200,13 @@ bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _ return __x.base() < __y.base(); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return !(__x == __y); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -189,6 +214,13 @@ bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) return !(__x == __y); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return __y < __x; +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -196,6 +228,13 @@ bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _ return __y < __x; } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return !(__x < __y); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT @@ -203,6 +242,13 @@ bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) return !(__x < __y); } +template +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT +{ + return !(__y < __x); +} + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT diff --git a/libcxx/include/__ranges/all.h b/libcxx/include/__ranges/all.h index d1312d1a213d5..6cfe3b8358ecd 100644 --- a/libcxx/include/__ranges/all.h +++ b/libcxx/include/__ranges/all.h @@ -17,6 +17,7 @@ #include <__ranges/ref_view.h> #include <__ranges/subrange.h> #include <__utility/__decay_copy.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include @@ -68,6 +69,9 @@ inline namespace __cpo { inline constexpr auto all = __all::__fn{}; } // namespace __cpo +template +using all_t = decltype(views::all(declval<_Range>())); + } // namespace views #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h index 364275da813b3..f314685e3dc9d 100644 --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -112,6 +112,13 @@ namespace ranges { template concept common_range = range<_Tp> && same_as, sentinel_t<_Tp> >; + + template + concept viewable_range = + range<_Tp> && ( + (view> && constructible_from, _Tp>) || + (!view> && borrowed_range<_Tp>) + ); } // namespace ranges #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h index 43ac36bd8e112..7ba74e54f6a80 100644 --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -10,14 +10,17 @@ #define _LIBCPP___RANGES_DROP_VIEW_H #include <__config> -#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__ranges/access.h> -#include <__ranges/view_interface.h> #include <__ranges/all.h> -#include +#include <__ranges/concepts.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> #include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -140,9 +143,7 @@ namespace ranges { }; template - drop_view(_Range&&, range_difference_t<_Range>) - // TODO: this is just recreating all_t. - -> drop_view()))>; + drop_view(_Range&&, range_difference_t<_Range>) -> drop_view>; template inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Tp>; diff --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h index 8ce20bd180bf3..7001c52073b69 100644 --- a/libcxx/include/__ranges/subrange.h +++ b/libcxx/include/__ranges/subrange.h @@ -226,6 +226,9 @@ namespace ranges { else return __subrange.end(); } + + template + inline constexpr bool enable_borrowed_range> = true; } // namespace ranges using ranges::get; diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h index e059cbf3b18cf..2d6f62deebc47 100644 --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -10,14 +10,17 @@ #define _LIBCPP___RANGES_TRANSFORM_VIEW_H #include <__config> -#include <__iterator/iterator_traits.h> #include <__iterator/concepts.h> #include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> #include <__ranges/access.h> +#include <__ranges/all.h> #include <__ranges/concepts.h> #include <__ranges/copyable_box.h> #include <__ranges/empty.h> +#include <__ranges/size.h> #include <__ranges/view_interface.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -93,10 +96,8 @@ class transform_view : public view_interface> { constexpr auto size() const requires sized_range { return ranges::size(__base_); } }; -// TODO: replace the decltype with all_t when that's implemented. template -transform_view(_Range&&, _Fn) - -> transform_view())), _Fn>; +transform_view(_Range&&, _Fn) -> transform_view, _Fn>; template struct __transform_view_iterator_concept { using type = input_iterator_tag; }; diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index c2e6564bb1247..1d22f866dea79 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -219,97 +219,99 @@ module std [system] { export * module __algorithm { - module adjacent_find { header "__algorithm/adjacent_find.h" } - module all_of { header "__algorithm/all_of.h" } - module any_of { header "__algorithm/any_of.h" } - module binary_search { header "__algorithm/binary_search.h" } - module clamp { header "__algorithm/clamp.h" } - module comp { header "__algorithm/comp.h" } - module comp_ref_type { header "__algorithm/comp_ref_type.h" } - module copy { header "__algorithm/copy.h" } - module copy_backward { header "__algorithm/copy_backward.h" } - module copy_if { header "__algorithm/copy_if.h" } - module copy_n { header "__algorithm/copy_n.h" } - module count { header "__algorithm/count.h" } - module count_if { header "__algorithm/count_if.h" } - module equal { header "__algorithm/equal.h" } - module equal_range { header "__algorithm/equal_range.h" } - module fill { header "__algorithm/fill.h" } - module fill_n { header "__algorithm/fill_n.h" } - module find { header "__algorithm/find.h" } - module find_end { header "__algorithm/find_end.h" } - module find_first_of { header "__algorithm/find_first_of.h" } - module find_if { header "__algorithm/find_if.h" } - module find_if_not { header "__algorithm/find_if_not.h" } - module for_each { header "__algorithm/for_each.h" } - module for_each_n { header "__algorithm/for_each_n.h" } - module generate { header "__algorithm/generate.h" } - module generate_n { header "__algorithm/generate_n.h" } - module half_positive { header "__algorithm/half_positive.h" } - module includes { header "__algorithm/includes.h" } - module inplace_merge { header "__algorithm/inplace_merge.h" } - module is_heap { header "__algorithm/is_heap.h" } - module is_heap_until { header "__algorithm/is_heap_until.h" } - module is_partitioned { header "__algorithm/is_partitioned.h" } - module is_permutation { header "__algorithm/is_permutation.h" } - module is_sorted { header "__algorithm/is_sorted.h" } - module is_sorted_until { header "__algorithm/is_sorted_until.h" } - module lexicographical_compare { header "__algorithm/lexicographical_compare.h" } - module lower_bound { header "__algorithm/lower_bound.h" } - module make_heap { header "__algorithm/make_heap.h" } - module max { header "__algorithm/max.h" } - module max_element { header "__algorithm/max_element.h" } - module merge { header "__algorithm/merge.h" } - module min { header "__algorithm/min.h" } - module min_element { header "__algorithm/min_element.h" } - module minmax { header "__algorithm/minmax.h" } - module minmax_element { header "__algorithm/minmax_element.h" } - module mismatch { header "__algorithm/mismatch.h" } - module move { header "__algorithm/move.h" } - module move_backward { header "__algorithm/move_backward.h" } - module next_permutation { header "__algorithm/next_permutation.h" } - module none_of { header "__algorithm/none_of.h" } - module nth_element { header "__algorithm/nth_element.h" } - module partial_sort { header "__algorithm/partial_sort.h" } - module partial_sort_copy { header "__algorithm/partial_sort_copy.h" } - module partition { header "__algorithm/partition.h" } - module partition_copy { header "__algorithm/partition_copy.h" } - module partition_point { header "__algorithm/partition_point.h" } - module pop_heap { header "__algorithm/pop_heap.h" } - module prev_permutation { header "__algorithm/prev_permutation.h" } - module push_heap { header "__algorithm/push_heap.h" } - module remove { header "__algorithm/remove.h" } - module remove_copy { header "__algorithm/remove_copy.h" } - module remove_copy_if { header "__algorithm/remove_copy_if.h" } - module remove_if { header "__algorithm/remove_if.h" } - module replace { header "__algorithm/replace.h" } - module replace_copy { header "__algorithm/replace_copy.h" } - module replace_copy_if { header "__algorithm/replace_copy_if.h" } - module replace_if { header "__algorithm/replace_if.h" } - module reverse { header "__algorithm/reverse.h" } - module reverse_copy { header "__algorithm/reverse_copy.h" } - module rotate { header "__algorithm/rotate.h" } - module rotate_copy { header "__algorithm/rotate_copy.h" } - module sample { header "__algorithm/sample.h" } - module search { header "__algorithm/search.h" } - module search_n { header "__algorithm/search_n.h" } - module set_difference { header "__algorithm/set_difference.h" } - module set_intersection { header "__algorithm/set_intersection.h" } - module set_symmetric_difference { header "__algorithm/set_symmetric_difference.h" } - module set_union { header "__algorithm/set_union.h" } - module shift_left { header "__algorithm/shift_left.h" } - module shift_right { header "__algorithm/shift_right.h" } - module shuffle { header "__algorithm/shuffle.h" } - module sift_down { header "__algorithm/sift_down.h" } - module sort { header "__algorithm/sort.h" } - module sort_heap { header "__algorithm/sort_heap.h" } - module stable_partition { header "__algorithm/stable_partition.h" } - module stable_sort { header "__algorithm/stable_sort.h" } - module transform { header "__algorithm/transform.h" } - module unique { header "__algorithm/unique.h" } - module unique_copy { header "__algorithm/unique_copy.h" } - module unwrap_iter { header "__algorithm/unwrap_iter.h" } - module upper_bound { header "__algorithm/upper_bound.h" } + module adjacent_find { private header "__algorithm/adjacent_find.h" } + module all_of { private header "__algorithm/all_of.h" } + module any_of { private header "__algorithm/any_of.h" } + module binary_search { private header "__algorithm/binary_search.h" } + module clamp { private header "__algorithm/clamp.h" } + module comp { private header "__algorithm/comp.h" } + module comp_ref_type { private header "__algorithm/comp_ref_type.h" } + module copy { private header "__algorithm/copy.h" } + module copy_backward { private header "__algorithm/copy_backward.h" } + module copy_if { private header "__algorithm/copy_if.h" } + module copy_n { private header "__algorithm/copy_n.h" } + module count { private header "__algorithm/count.h" } + module count_if { private header "__algorithm/count_if.h" } + module equal { private header "__algorithm/equal.h" } + module equal_range { private header "__algorithm/equal_range.h" } + module fill { private header "__algorithm/fill.h" } + module fill_n { private header "__algorithm/fill_n.h" } + module find { private header "__algorithm/find.h" } + module find_end { private header "__algorithm/find_end.h" } + module find_first_of { private header "__algorithm/find_first_of.h" } + module find_if { private header "__algorithm/find_if.h" } + module find_if_not { private header "__algorithm/find_if_not.h" } + module for_each { private header "__algorithm/for_each.h" } + module for_each_n { private header "__algorithm/for_each_n.h" } + module generate { private header "__algorithm/generate.h" } + module generate_n { private header "__algorithm/generate_n.h" } + module half_positive { private header "__algorithm/half_positive.h" } + module includes { private header "__algorithm/includes.h" } + module inplace_merge { private header "__algorithm/inplace_merge.h" } + module is_heap { private header "__algorithm/is_heap.h" } + module is_heap_until { private header "__algorithm/is_heap_until.h" } + module is_partitioned { private header "__algorithm/is_partitioned.h" } + module is_permutation { private header "__algorithm/is_permutation.h" } + module is_sorted { private header "__algorithm/is_sorted.h" } + module is_sorted_until { private header "__algorithm/is_sorted_until.h" } + module iter_swap { private header "__algorithm/iter_swap.h" } + module lexicographical_compare { private header "__algorithm/lexicographical_compare.h" } + module lower_bound { private header "__algorithm/lower_bound.h" } + module make_heap { private header "__algorithm/make_heap.h" } + module max { private header "__algorithm/max.h" } + module max_element { private header "__algorithm/max_element.h" } + module merge { private header "__algorithm/merge.h" } + module min { private header "__algorithm/min.h" } + module min_element { private header "__algorithm/min_element.h" } + module minmax { private header "__algorithm/minmax.h" } + module minmax_element { private header "__algorithm/minmax_element.h" } + module mismatch { private header "__algorithm/mismatch.h" } + module move { private header "__algorithm/move.h" } + module move_backward { private header "__algorithm/move_backward.h" } + module next_permutation { private header "__algorithm/next_permutation.h" } + module none_of { private header "__algorithm/none_of.h" } + module nth_element { private header "__algorithm/nth_element.h" } + module partial_sort { private header "__algorithm/partial_sort.h" } + module partial_sort_copy { private header "__algorithm/partial_sort_copy.h" } + module partition { private header "__algorithm/partition.h" } + module partition_copy { private header "__algorithm/partition_copy.h" } + module partition_point { private header "__algorithm/partition_point.h" } + module pop_heap { private header "__algorithm/pop_heap.h" } + module prev_permutation { private header "__algorithm/prev_permutation.h" } + module push_heap { private header "__algorithm/push_heap.h" } + module remove { private header "__algorithm/remove.h" } + module remove_copy { private header "__algorithm/remove_copy.h" } + module remove_copy_if { private header "__algorithm/remove_copy_if.h" } + module remove_if { private header "__algorithm/remove_if.h" } + module replace { private header "__algorithm/replace.h" } + module replace_copy { private header "__algorithm/replace_copy.h" } + module replace_copy_if { private header "__algorithm/replace_copy_if.h" } + module replace_if { private header "__algorithm/replace_if.h" } + module reverse { private header "__algorithm/reverse.h" } + module reverse_copy { private header "__algorithm/reverse_copy.h" } + module rotate { private header "__algorithm/rotate.h" } + module rotate_copy { private header "__algorithm/rotate_copy.h" } + module sample { private header "__algorithm/sample.h" } + module search { private header "__algorithm/search.h" } + module search_n { private header "__algorithm/search_n.h" } + module set_difference { private header "__algorithm/set_difference.h" } + module set_intersection { private header "__algorithm/set_intersection.h" } + module set_symmetric_difference { private header "__algorithm/set_symmetric_difference.h" } + module set_union { private header "__algorithm/set_union.h" } + module shift_left { private header "__algorithm/shift_left.h" } + module shift_right { private header "__algorithm/shift_right.h" } + module shuffle { private header "__algorithm/shuffle.h" } + module sift_down { private header "__algorithm/sift_down.h" } + module sort { private header "__algorithm/sort.h" } + module sort_heap { private header "__algorithm/sort_heap.h" } + module stable_partition { private header "__algorithm/stable_partition.h" } + module stable_sort { private header "__algorithm/stable_sort.h" } + module swap_ranges { private header "__algorithm/swap_ranges.h" } + module transform { private header "__algorithm/transform.h" } + module unique { private header "__algorithm/unique.h" } + module unique_copy { private header "__algorithm/unique_copy.h" } + module unwrap_iter { private header "__algorithm/unwrap_iter.h" } + module upper_bound { private header "__algorithm/upper_bound.h" } } } module any { @@ -391,8 +393,8 @@ module std [system] { export * module __format { - module format_error { header "__format/format_error.h" } - module format_parse_context { header "__format/format_parse_context.h" } + module format_error { private header "__format/format_error.h" } + module format_parse_context { private header "__format/format_parse_context.h" } } } module forward_list { @@ -409,30 +411,31 @@ module std [system] { export * module __functional { - module binary_function { header "__functional/binary_function.h" } - module binary_negate { header "__functional/binary_negate.h" } - module bind { header "__functional/bind.h" } - module bind_front { header "__functional/bind_front.h" } - module binder1st { header "__functional/binder1st.h" } - module binder2nd { header "__functional/binder2nd.h" } - module default_searcher { header "__functional/default_searcher.h" } - module function { header "__functional/function.h" } - module hash { header "__functional/hash.h" } - module identity { header "__functional/identity.h" } - module invoke { header "__functional/invoke.h" } - module mem_fn { header "__functional/mem_fn.h" } - module mem_fun_ref { header "__functional/mem_fun_ref.h" } - module not_fn { header "__functional/not_fn.h" } - module operations { header "__functional/operations.h" } - module perfect_forward { header "__functional/perfect_forward.h" } - module pointer_to_binary_function { header "__functional/pointer_to_binary_function.h" } - module pointer_to_unary_function { header "__functional/pointer_to_unary_function.h" } - module ranges_operations { header "__functional/ranges_operations.h" } - module reference_wrapper { header "__functional/reference_wrapper.h" } - module unary_function { header "__functional/unary_function.h" } - module unary_negate { header "__functional/unary_negate.h" } - module unwrap_ref { header "__functional/unwrap_ref.h" } - module weak_result_type { header "__functional/weak_result_type.h" } + module binary_function { private header "__functional/binary_function.h" } + module binary_negate { private header "__functional/binary_negate.h" } + module bind { private header "__functional/bind.h" } + module bind_front { private header "__functional/bind_front.h" } + module binder1st { private header "__functional/binder1st.h" } + module binder2nd { private header "__functional/binder2nd.h" } + module default_searcher { private header "__functional/default_searcher.h" } + module function { private header "__functional/function.h" } + module hash { private header "__functional/hash.h" } + module identity { private header "__functional/identity.h" } + module is_transparent { private header "__functional/is_transparent.h" } + module invoke { private header "__functional/invoke.h" } + module mem_fn { private header "__functional/mem_fn.h" } + module mem_fun_ref { private header "__functional/mem_fun_ref.h" } + module not_fn { private header "__functional/not_fn.h" } + module operations { private header "__functional/operations.h" } + module perfect_forward { private header "__functional/perfect_forward.h" } + module pointer_to_binary_function { private header "__functional/pointer_to_binary_function.h" } + module pointer_to_unary_function { private header "__functional/pointer_to_unary_function.h" } + module ranges_operations { private header "__functional/ranges_operations.h" } + module reference_wrapper { private header "__functional/reference_wrapper.h" } + module unary_function { private header "__functional/unary_function.h" } + module unary_negate { private header "__functional/unary_negate.h" } + module unwrap_ref { private header "__functional/unwrap_ref.h" } + module weak_result_type { private header "__functional/weak_result_type.h" } } } module future { @@ -474,35 +477,35 @@ module std [system] { export * module __iterator { - module access { header "__iterator/access.h" } - module advance { header "__iterator/advance.h" } - module back_insert_iterator { header "__iterator/back_insert_iterator.h" } - module concepts { header "__iterator/concepts.h" } - module data { header "__iterator/data.h" } - module default_sentinel { header "__iterator/default_sentinel.h" } - module distance { header "__iterator/distance.h" } - module empty { header "__iterator/empty.h" } - module erase_if_container { header "__iterator/erase_if_container.h" } - module front_insert_iterator { header "__iterator/front_insert_iterator.h" } - module incrementable_traits { header "__iterator/incrementable_traits.h" } - module insert_iterator { header "__iterator/insert_iterator.h" } - module istream_iterator { header "__iterator/istream_iterator.h" } - module istreambuf_iterator { header "__iterator/istreambuf_iterator.h" } - module iter_move { header "__iterator/iter_move.h" } - module iter_swap { header "__iterator/iter_swap.h" } - module iterator { header "__iterator/iterator.h" } - module iterator_traits { header "__iterator/iterator_traits.h" } - module move_iterator { header "__iterator/move_iterator.h" } - module next { header "__iterator/next.h" } - module ostream_iterator { header "__iterator/ostream_iterator.h" } - module ostreambuf_iterator { header "__iterator/ostreambuf_iterator.h" } - module prev { header "__iterator/prev.h" } - module projected { header "__iterator/projected.h" } - module readable_traits { header "__iterator/readable_traits.h" } - module reverse_access { header "__iterator/reverse_access.h" } - module reverse_iterator { header "__iterator/reverse_iterator.h" } - module size { header "__iterator/size.h" } - module wrap_iter { header "__iterator/wrap_iter.h" } + module access { private header "__iterator/access.h" } + module advance { private header "__iterator/advance.h" } + module back_insert_iterator { private header "__iterator/back_insert_iterator.h" } + module concepts { private header "__iterator/concepts.h" } + module data { private header "__iterator/data.h" } + module default_sentinel { private header "__iterator/default_sentinel.h" } + module distance { private header "__iterator/distance.h" } + module empty { private header "__iterator/empty.h" } + module erase_if_container { private header "__iterator/erase_if_container.h" } + module front_insert_iterator { private header "__iterator/front_insert_iterator.h" } + module incrementable_traits { private header "__iterator/incrementable_traits.h" } + module insert_iterator { private header "__iterator/insert_iterator.h" } + module istream_iterator { private header "__iterator/istream_iterator.h" } + module istreambuf_iterator { private header "__iterator/istreambuf_iterator.h" } + module iter_move { private header "__iterator/iter_move.h" } + module iter_swap { private header "__iterator/iter_swap.h" } + module iterator { private header "__iterator/iterator.h" } + module iterator_traits { private header "__iterator/iterator_traits.h" } + module move_iterator { private header "__iterator/move_iterator.h" } + module next { private header "__iterator/next.h" } + module ostream_iterator { private header "__iterator/ostream_iterator.h" } + module ostreambuf_iterator { private header "__iterator/ostreambuf_iterator.h" } + module prev { private header "__iterator/prev.h" } + module projected { private header "__iterator/projected.h" } + module readable_traits { private header "__iterator/readable_traits.h" } + module reverse_access { private header "__iterator/reverse_access.h" } + module reverse_iterator { private header "__iterator/reverse_iterator.h" } + module size { private header "__iterator/size.h" } + module wrap_iter { private header "__iterator/wrap_iter.h" } } } module latch { @@ -533,21 +536,22 @@ module std [system] { export * module __memory { - module addressof { header "__memory/addressof.h" } - module allocation_guard { header "__memory/allocation_guard.h" } - module allocator { header "__memory/allocator.h" } - module allocator_arg_t { header "__memory/allocator_arg_t.h" } - module allocator_traits { header "__memory/allocator_traits.h" } - module auto_ptr { header "__memory/auto_ptr.h" } - module compressed_pair { header "__memory/compressed_pair.h" } - module construct_at { header "__memory/construct_at.h" } - module pointer_safety { header "__memory/pointer_safety.h" } - module pointer_traits { header "__memory/pointer_traits.h" } - module raw_storage_iterator { header "__memory/raw_storage_iterator.h" } - module shared_ptr { header "__memory/shared_ptr.h" } - module temporary_buffer { header "__memory/temporary_buffer.h" } - module uninitialized_algorithms { header "__memory/uninitialized_algorithms.h" } - module unique_ptr { header "__memory/unique_ptr.h" } + module addressof { private header "__memory/addressof.h" } + module allocation_guard { private header "__memory/allocation_guard.h" } + module allocator { private header "__memory/allocator.h" } + module allocator_arg_t { private header "__memory/allocator_arg_t.h" } + module allocator_traits { private header "__memory/allocator_traits.h" } + module auto_ptr { private header "__memory/auto_ptr.h" } + module compressed_pair { private header "__memory/compressed_pair.h" } + module construct_at { private header "__memory/construct_at.h" } + module pointer_safety { private header "__memory/pointer_safety.h" } + module pointer_traits { private header "__memory/pointer_traits.h" } + module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" } + module shared_ptr { private header "__memory/shared_ptr.h" } + module temporary_buffer { private header "__memory/temporary_buffer.h" } + module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } + module unique_ptr { private header "__memory/unique_ptr.h" } + module uses_allocator { private header "__memory/uses_allocator.h" } } } module mutex { @@ -586,7 +590,7 @@ module std [system] { export * module __random { - module uniform_int_distribution { header "__random/uniform_int_distribution.h" } + module uniform_int_distribution { private header "__random/uniform_int_distribution.h" } } } module ranges { @@ -597,19 +601,21 @@ module std [system] { export * module __ranges { - module access { header "__ranges/access.h" } - module all { header "__ranges/all.h" } - module concepts { header "__ranges/concepts.h" } - module copyable_box { header "__ranges/copyable_box.h" } - module data { header "__ranges/data.h" } - module empty { header "__ranges/empty.h" } - module empty_view { header "__ranges/empty_view.h" } - module enable_borrowed_range { header "__ranges/enable_borrowed_range.h" } - module enable_view { header "__ranges/enable_view.h" } - module ref_view { header "__ranges/ref_view.h" } - module size { header "__ranges/size.h" } - module subrange { header "__ranges/subrange.h" } - module view_interface { header "__ranges/view_interface.h" } + module access { private header "__ranges/access.h" } + module all { private header "__ranges/all.h" } + module concepts { private header "__ranges/concepts.h" } + module copyable_box { private header "__ranges/copyable_box.h" } + module data { private header "__ranges/data.h" } + module drop_view { private header "__ranges/drop_view.h" } + module empty { private header "__ranges/empty.h" } + module empty_view { private header "__ranges/empty_view.h" } + module enable_borrowed_range { private header "__ranges/enable_borrowed_range.h" } + module enable_view { private header "__ranges/enable_view.h" } + module ref_view { private header "__ranges/ref_view.h" } + module size { private header "__ranges/size.h" } + module subrange { private header "__ranges/subrange.h" } + module transform_view { private header "__ranges/transform_view.h" } + module view_interface { private header "__ranges/view_interface.h" } } } module ratio { @@ -635,6 +641,15 @@ module std [system] { export initializer_list export * } + module shared_mutex { + header "shared_mutex" + export version + } + module span { + header "span" + export ranges.__ranges.enable_borrowed_range + export version + } module sstream { header "sstream" // FIXME: should re-export istream, ostream, ios, streambuf, string? @@ -711,20 +726,20 @@ module std [system] { export * module __utility { - module __decay_copy { header "__utility/__decay_copy.h" } - module as_const { header "__utility/as_const.h" } - module cmp { header "__utility/cmp.h" } - module declval { header "__utility/declval.h" } - module exchange { header "__utility/exchange.h" } - module forward { header "__utility/forward.h" } - module in_place { header "__utility/in_place.h" } - module integer_sequence { header "__utility/integer_sequence.h" } - module move { header "__utility/move.h" } - module pair { header "__utility/pair.h" } - module piecewise_construct { header "__utility/piecewise_construct.h" } - module rel_ops { header "__utility/rel_ops.h" } - module swap { header "__utility/swap.h" } - module to_underlying { header "__utility/to_underlying.h" } + module __decay_copy { private header "__utility/__decay_copy.h" } + module as_const { private header "__utility/as_const.h" } + module cmp { private header "__utility/cmp.h" } + module declval { private header "__utility/declval.h" } + module exchange { private header "__utility/exchange.h" } + module forward { private header "__utility/forward.h" } + module in_place { private header "__utility/in_place.h" } + module integer_sequence { private header "__utility/integer_sequence.h" } + module move { private header "__utility/move.h" } + module pair { private header "__utility/pair.h" } + module piecewise_construct { private header "__utility/piecewise_construct.h" } + module rel_ops { private header "__utility/rel_ops.h" } + module swap { private header "__utility/swap.h" } + module to_underlying { private header "__utility/to_underlying.h" } } } module valarray { @@ -737,7 +752,7 @@ module std [system] { export * module __variant { - module monostate { header "__variant/monostate.h" } + module monostate { private header "__variant/monostate.h" } } } module vector { @@ -752,23 +767,23 @@ module std [system] { // __config not modularised due to a bug in Clang // FIXME: These should be private. - module __availability { header "__availability" export * } - module __bit_reference { header "__bit_reference" export * } - module __bits { header "__bits" export * } + module __availability { private header "__availability" export * } + module __bit_reference { private header "__bit_reference" export * } + module __bits { private header "__bits" export * } module __debug { header "__debug" export * } - module __errc { header "__errc" export * } - module __function_like { header "__function_like.h" export * } + module __errc { private header "__errc" export * } + module __function_like { private header "__function_like.h" export * } module __hash_table { header "__hash_table" export * } - module __locale { header "__locale" export * } - module __mutex_base { header "__mutex_base" export * } - module __node_handle { header "__node_handle" export * } + module __locale { private header "__locale" export * } + module __mutex_base { private header "__mutex_base" export * } + module __node_handle { private header "__node_handle" export * } module __nullptr { header "__nullptr" export * } - module __split_buffer { header "__split_buffer" export * } - module __std_stream { header "__std_stream" export * } - module __string { header "__string" export * } + module __split_buffer { private header "__split_buffer" export * } + module __std_stream { private header "__std_stream" export * } + module __string { private header "__string" export * } module __threading_support { header "__threading_support" export * } module __tree { header "__tree" export * } - module __tuple { header "__tuple" export * } + module __tuple { private header "__tuple" export * } module __undef_macros { header "__undef_macros" export * } module experimental { diff --git a/libcxx/include/ranges b/libcxx/include/ranges index 90711cb7d05c1..367ad60226d4e 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -50,7 +50,7 @@ namespace std::ranges { template using range_rvalue_reference_t = iter_rvalue_reference_t>; - // [range.sized] + // [range.sized], sized ranges template inline constexpr bool disable_sized_range = false; @@ -85,16 +85,44 @@ namespace std::ranges { template concept common_range = see below; + template + concept viewable_range = see below; + // [view.interface], class template view_interface template requires is_class_v && same_as> class view_interface; + // [range.subrange], sub-ranges + enum class subrange_kind : bool { unsized, sized }; + + template S = I, subrange_kind K = see below> + requires (K == subrange_kind::sized || !sized_sentinel_for) + class subrange; + + template + inline constexpr bool enable_borrowed_range> = true; + // [range.empty], empty view template requires is_object_v class empty_view; + // [range.all], all view + namespace views { + inline constexpr unspecified all = unspecified; + + template + using all_t = decltype(all(declval())); + } + + template + requires is_object_v + class ref_view; + + template + inline constexpr bool enable_borrowed_range> = true; + // [range.drop], drop view template class drop_view; diff --git a/libcxx/include/span b/libcxx/include/span index 0892e25a59bc2..260a74404fe58 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -137,6 +137,7 @@ template #include // for iterators #include #include // for remove_cv, etc +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/lib/abi/CMakeLists.txt b/libcxx/lib/abi/CMakeLists.txt index 3d19c0bd16f25..c406330426d0f 100644 --- a/libcxx/lib/abi/CMakeLists.txt +++ b/libcxx/lib/abi/CMakeLists.txt @@ -41,7 +41,7 @@ function(cxx_abi_list_identifier result triple abi_library abi_version unstable endfunction() cxx_abi_list_identifier(abi_list_identifier - "${TARGET_TRIPLE}" + "${LIBCXX_TARGET_TRIPLE}" "${LIBCXX_CXX_ABI_LIBNAME}" "${LIBCXX_ABI_VERSION}" "${LIBCXX_ABI_UNSTABLE}" diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist new file mode 100644 index 0000000000000..f2dbb6e660915 --- /dev/null +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.no_new_in_libcxx.abilist @@ -0,0 +1,2540 @@ +{'is_defined': False, 'name': '__ZNKSt10bad_typeid4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt11logic_error4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt13bad_exception4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt13runtime_error4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt20bad_array_new_length4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt8bad_cast4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt9bad_alloc4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNKSt9exception4whatEv', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt10bad_typeidC1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt10bad_typeidC2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt10bad_typeidD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt10bad_typeidD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt10bad_typeidD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt11logic_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt11logic_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt11logic_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt11range_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt11range_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt11range_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12domain_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12domain_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12domain_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12length_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12length_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12length_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12out_of_rangeD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12out_of_rangeD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt12out_of_rangeD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt13runtime_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt13runtime_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt13runtime_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt14overflow_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt14overflow_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt14overflow_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt15underflow_errorD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt15underflow_errorD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt15underflow_errorD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt16invalid_argumentD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt16invalid_argumentD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt16invalid_argumentD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthC1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthC2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt8bad_castC1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt8bad_castC2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt8bad_castD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt8bad_castD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt8bad_castD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9bad_allocC1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9bad_allocC2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9bad_allocD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9bad_allocD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9bad_allocD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9exceptionD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9exceptionD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9exceptionD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9type_infoD0Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9type_infoD1Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZNSt9type_infoD2Ev', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt10unexpectedv', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt13get_terminatev', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt13set_terminatePFvvE', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt14get_unexpectedv', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt14set_unexpectedPFvvE', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt15get_new_handlerv', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt15set_new_handlerPFvvE', 'type': 'U'} +{'is_defined': False, 'name': '__ZSt9terminatev', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIDi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIDn', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIDs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPDi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPDn', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPDs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKDi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKDn', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKDs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKa', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKb', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKd', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKe', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKf', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKh', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKj', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKl', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKm', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKt', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKv', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKw', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKx', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPKy', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPa', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPb', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPd', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPe', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPf', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPh', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPj', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPl', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPm', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPt', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPv', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPw', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPx', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIPy', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt10bad_typeid', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt11logic_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt11range_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt12domain_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt12length_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt12out_of_range', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt13bad_exception', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt13runtime_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt14overflow_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt15underflow_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt16invalid_argument', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt20bad_array_new_length', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt8bad_cast', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt9bad_alloc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt9exception', 'type': 'U'} +{'is_defined': False, 'name': '__ZTISt9type_info', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIa', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIb', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTId', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIe', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIf', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIh', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIj', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIl', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIm', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIt', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIv', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIw', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIx', 'type': 'U'} +{'is_defined': False, 'name': '__ZTIy', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSDi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSDn', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSDs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv116__enum_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv117__array_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv117__class_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv117__pbase_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv119__pointer_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv120__function_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv120__si_class_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv121__vmi_class_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv123__fundamental_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSN10__cxxabiv129__pointer_to_member_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPDi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPDn', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPDs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKDi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKDn', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKDs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKa', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKb', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKd', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKe', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKf', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKh', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKj', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKl', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKm', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKt', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKv', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKw', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKx', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPKy', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPa', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPb', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPd', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPe', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPf', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPh', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPj', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPl', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPm', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPt', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPv', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPw', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPx', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSPy', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt10bad_typeid', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt11logic_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt11range_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt12domain_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt12length_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt12out_of_range', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt13bad_exception', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt13runtime_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt14overflow_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt15underflow_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt16invalid_argument', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt20bad_array_new_length', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt8bad_cast', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt9bad_alloc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt9exception', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSSt9type_info', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSa', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSb', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSd', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSe', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSf', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSh', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSi', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSj', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSl', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSm', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSs', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSt', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSv', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSw', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSx', 'type': 'U'} +{'is_defined': False, 'name': '__ZTSy', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv116__enum_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv117__array_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv117__class_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv117__pbase_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv119__pointer_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv120__function_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv120__si_class_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv121__vmi_class_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv123__fundamental_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVN10__cxxabiv129__pointer_to_member_type_infoE', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt10bad_typeid', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt11logic_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt11range_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt12domain_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt12length_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt12out_of_range', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt13bad_exception', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt13runtime_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt14overflow_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt15underflow_error', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt16invalid_argument', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt20bad_array_new_length', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt8bad_cast', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt9bad_alloc', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt9exception', 'type': 'U'} +{'is_defined': False, 'name': '__ZTVSt9type_info', 'type': 'U'} +{'is_defined': False, 'name': '__ZdaPv', 'type': 'U'} +{'is_defined': False, 'name': '__ZdaPvRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdaPvSt11align_val_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdaPvSt11align_val_tRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdaPvm', 'type': 'U'} +{'is_defined': False, 'name': '__ZdaPvmSt11align_val_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdlPv', 'type': 'U'} +{'is_defined': False, 'name': '__ZdlPvRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdlPvSt11align_val_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdlPvSt11align_val_tRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZdlPvm', 'type': 'U'} +{'is_defined': False, 'name': '__ZdlPvmSt11align_val_t', 'type': 'U'} +{'is_defined': False, 'name': '__Znam', 'type': 'U'} +{'is_defined': False, 'name': '__ZnamRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZnamSt11align_val_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZnamSt11align_val_tRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__Znwm', 'type': 'U'} +{'is_defined': False, 'name': '__ZnwmRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZnwmSt11align_val_t', 'type': 'U'} +{'is_defined': False, 'name': '__ZnwmSt11align_val_tRKSt9nothrow_t', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_allocate_dependent_exception', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_allocate_exception', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_atexit', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_bad_cast', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_bad_typeid', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_begin_catch', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_call_unexpected', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_current_exception_type', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_current_primary_exception', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_decrement_exception_refcount', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_deleted_virtual', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_demangle', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_end_catch', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_free_dependent_exception', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_free_exception', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_get_exception_ptr', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_get_globals', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_get_globals_fast', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_guard_abort', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_guard_acquire', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_guard_release', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_increment_exception_refcount', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_pure_virtual', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_rethrow', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_rethrow_primary_exception', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_throw', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_throw_bad_array_new_length', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_uncaught_exceptions', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_cctor', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_cleanup', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_ctor', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_delete', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_delete2', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_delete3', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_dtor', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_new', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_new2', 'type': 'U'} +{'is_defined': False, 'name': '___cxa_vec_new3', 'type': 'U'} +{'is_defined': False, 'name': '___dynamic_cast', 'type': 'U'} +{'is_defined': False, 'name': '___gxx_personality_v0', 'type': 'U'} +{'is_defined': True, 'name': '__ZNKSt10bad_typeid4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt11logic_error4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt12bad_any_cast4whatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt12experimental15fundamentals_v112bad_any_cast4whatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt13bad_exception4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt13runtime_error4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt20bad_array_new_length4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110error_code7messageEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb0EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIcLb1EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb0EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__110moneypunctIwLb1EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db15__decrementableEPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db15__find_c_from_iEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db15__subscriptableEPKvl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db17__dereferenceableEPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db17__find_c_and_lockEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db22__less_than_comparableEPKvS2_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db8__find_cEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__111__libcpp_db9__addableEPKvl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112bad_weak_ptr4whatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE12find_last_ofEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13find_first_ofEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16find_last_not_ofEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE17find_first_not_ofEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE2atEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4copyEPcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4findEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4findEcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5rfindEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5rfindEcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmRKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE12find_last_ofEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE13find_first_ofEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE16find_last_not_ofEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE17find_first_not_ofEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE2atEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4copyEPwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4findEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4findEwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5rfindEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5rfindEwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmPKwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmRKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIcE10do_tolowerEPcPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIcE10do_tolowerEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIcE10do_toupperEPcPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIcE10do_toupperEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE10do_scan_isEjPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE10do_tolowerEPwPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE10do_tolowerEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE10do_toupperEPwPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE10do_toupperEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE11do_scan_notEjPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE5do_isEPKwS3_Pj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE5do_isEjw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE8do_widenEPKcS3_Pw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE8do_widenEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE9do_narrowEPKwS3_cPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112ctype_bynameIwE9do_narrowEwc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__112strstreambuf6pcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__113random_device7entropyEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDiE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IDsE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114__codecvt_utf8IwE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114collate_bynameIcE10do_compareEPKcS3_S3_S3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114collate_bynameIcE12do_transformEPKcS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114collate_bynameIwE10do_compareEPKwS3_S3_S3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114collate_bynameIwE12do_transformEPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114error_category10equivalentERKNS_10error_codeEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114error_category10equivalentEiRKNS_15error_conditionE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__114error_category23default_error_conditionEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb0EE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDiLb1EE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb0EE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IDsLb1EE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb0EE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115__codecvt_utf16IwLb1EE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115basic_streambufIcNS_11char_traitsIcEEE6getlocEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__115error_condition7messageEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb0EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIcLb1EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb0EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE13do_neg_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE13do_pos_formatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE14do_curr_symbolEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE14do_frac_digitsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE16do_negative_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE16do_positive_signEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__117moneypunct_bynameIwLb1EE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__118__time_get_storageIcE15__do_date_orderEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__118__time_get_storageIwE15__do_date_orderEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__119__libcpp_debug_info4whatEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__119__shared_weak_count13__get_deleterERKSt9type_info', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDiE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IDsE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE10do_unshiftER11__mbstate_tPcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__codecvt_utf8_utf16IwE9do_lengthER11__mbstate_tPKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE3__XEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE3__cEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE3__rEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE3__xEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE7__am_pmEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE7__weeksEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIcE8__monthsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE3__XEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE3__cEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE3__rEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE3__xEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE7__am_pmEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE7__weeksEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__time_get_c_storageIwE8__monthsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__120__vector_base_commonILb1EE20__throw_out_of_rangeEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__121__basic_string_commonILb1EE20__throw_length_errorEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__121__basic_string_commonILb1EE20__throw_out_of_rangeEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__123__match_any_but_newlineIcE6__execERNS_7__stateIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__123__match_any_but_newlineIwE6__execERNS_7__stateIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem18directory_iterator13__dereferenceEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem28recursive_directory_iterator13__dereferenceEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem28recursive_directory_iterator5depthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem28recursive_directory_iterator7optionsEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path10__filenameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path11__extensionEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path11__root_nameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path13__parent_pathEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path15__relative_pathEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path15__root_path_rawEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path16__root_directoryEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path16lexically_normalEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path18lexically_relativeERKS2_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path3endEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path5beginEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path6__stemEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path9__compareENS_17basic_string_viewIcNS_11char_traitsIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_tolowerEPcPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_tolowerEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_toupperEPcPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE10do_toupperEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE8do_widenEPKcS3_Pc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE8do_widenEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE9do_narrowEPKcS3_cPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIcE9do_narrowEcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE10do_scan_isEjPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE10do_tolowerEPwPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE10do_tolowerEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE10do_toupperEPwPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE10do_toupperEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE11do_scan_notEjPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE5do_isEPKwS3_Pj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE5do_isEjw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE8do_widenEPKcS3_Pw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE8do_widenEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE9do_narrowEPKwS3_cPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__15ctypeIwE9do_narrowEwc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__16locale4nameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__16locale9has_facetERNS0_2idE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__16locale9use_facetERNS0_2idE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__16localeeqERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE10do_unshiftERS1_PDuS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE5do_inERS1_PKDuS5_RS5_PDiS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE6do_outERS1_PKDiS5_RS5_PDuS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDiDu11__mbstate_tE9do_lengthERS1_PKDuS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE10do_unshiftERS1_PcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE5do_inERS1_PKcS5_RS5_PDiS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE6do_outERS1_PKDiS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDic11__mbstate_tE9do_lengthERS1_PKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE10do_unshiftERS1_PDuS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE5do_inERS1_PKDuS5_RS5_PDsS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE6do_outERS1_PKDsS5_RS5_PDuS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsDu11__mbstate_tE9do_lengthERS1_PKDuS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE10do_unshiftERS1_PcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE5do_inERS1_PKcS5_RS5_PDsS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE6do_outERS1_PKDsS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIDsc11__mbstate_tE9do_lengthERS1_PKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE10do_unshiftERS1_PcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE5do_inERS1_PKcS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE6do_outERS1_PKcS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIcc11__mbstate_tE9do_lengthERS1_PKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE10do_unshiftERS1_PcS4_RS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE11do_encodingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE13do_max_lengthEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE16do_always_noconvEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE5do_inERS1_PKcS5_RS5_PwS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE6do_outERS1_PKwS5_RS5_PcS7_RS7_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17codecvtIwc11__mbstate_tE9do_lengthERS1_PKcS5_m', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17collateIcE10do_compareEPKcS3_S3_S3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17collateIcE12do_transformEPKcS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17collateIcE7do_hashEPKcS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17collateIwE10do_compareEPKwS3_S3_S3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17collateIwE12do_transformEPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17collateIwE7do_hashEPKwS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRt', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjS8_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRt', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjS8_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEce', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18ios_base6getlocEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18messagesIcE6do_getEliiRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18messagesIcE7do_openERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18messagesIcE8do_closeEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18messagesIwE6do_getEliiRKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18messagesIwE7do_openERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18messagesIwE8do_closeEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIcE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIcE11do_truenameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIcE12do_falsenameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIcE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIcE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIwE11do_groupingEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIwE11do_truenameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIwE12do_falsenameEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIwE16do_decimal_pointEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18numpunctIwE16do_thousands_sepEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE10__get_hourERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE10__get_yearERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11__get_am_pmERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11__get_monthERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11__get_year4ERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11do_get_dateES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11do_get_timeES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11do_get_yearES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE12__get_minuteERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE12__get_secondERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13__get_12_hourERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13__get_percentERS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13__get_weekdayERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13do_date_orderEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE14do_get_weekdayES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE15__get_monthnameERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE16do_get_monthnameES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE17__get_weekdaynameERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE17__get_white_spaceERS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE18__get_day_year_numERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE3getES4_S4_RNS_8ios_baseERjP2tmPKcSC_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjP2tmcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE9__get_dayERiRS4_S4_RjRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE10__get_hourERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE10__get_yearERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11__get_am_pmERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11__get_monthERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11__get_year4ERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11do_get_dateES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11do_get_timeES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11do_get_yearES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE12__get_minuteERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE12__get_secondERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13__get_12_hourERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13__get_percentERS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13__get_weekdayERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13do_date_orderEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE14do_get_weekdayES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE15__get_monthnameERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE16do_get_monthnameES4_S4_RNS_8ios_baseERjP2tm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE17__get_weekdaynameERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE17__get_white_spaceERS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE18__get_day_year_numERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE3getES4_S4_RNS_8ios_baseERjP2tmPKwSC_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjP2tmcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE9__get_dayERiRS4_S4_RjRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE3putES4_RNS_8ios_baseEcPK2tmPKcSC_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcPK2tmcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE3putES4_RNS_8ios_baseEwPK2tmPKwSC_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__18time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwPK2tmcc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_bRNS_8ios_baseERjRNS_12basic_stringIcS3_NS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_bRNS_8ios_baseERjRe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_bRNS_8ios_baseERjRNS_12basic_stringIwS3_NS_9allocatorIwEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_bRNS_8ios_baseERjRe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_bRNS_8ios_baseEcRKNS_12basic_stringIcS3_NS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_bRNS_8ios_baseEce', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_bRNS_8ios_baseEwRKNS_12basic_stringIwS3_NS_9allocatorIwEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt3__19money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_bRNS_8ios_baseEwe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNKSt8bad_cast4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt9bad_alloc4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNKSt9exception4whatEv', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt10bad_typeidC1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt10bad_typeidC2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt10bad_typeidD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt10bad_typeidD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt10bad_typeidD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt11logic_errorC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11logic_errorC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11logic_errorC1ERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11logic_errorC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11logic_errorC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11logic_errorC2ERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11logic_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt11logic_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt11logic_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt11logic_erroraSERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt11range_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt11range_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt11range_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12domain_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12domain_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12domain_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt12length_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12length_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12length_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12out_of_rangeD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12out_of_rangeD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt12out_of_rangeD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptrD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptraSERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorC1ERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorC2ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorC2ERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13runtime_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13runtime_erroraSERKS_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt14overflow_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt14overflow_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt14overflow_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt15underflow_errorD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt15underflow_errorD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt15underflow_errorD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt16invalid_argumentD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt16invalid_argumentD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt16invalid_argumentD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt16nested_exceptionC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt16nested_exceptionC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt16nested_exceptionD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt16nested_exceptionD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt16nested_exceptionD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt19bad_optional_accessD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt19bad_optional_accessD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthC1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthC2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt3__110__time_getC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_getC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_getC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_getC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_getD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_getD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_putC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_putC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_putC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_putD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110__time_putD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110adopt_lockE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5alnumE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5alphaE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5blankE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5cntrlE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5digitE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5graphE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5lowerE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5printE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5punctE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5spaceE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base5upperE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ctype_base6xdigitE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110defer_lockE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110istrstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110istrstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110istrstreamD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIcLb0EE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIcLb0EE4intlE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIcLb1EE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIcLb1EE4intlE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIwLb0EE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIwLb0EE4intlE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIwLb1EE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110moneypunctIwLb1EE4intlE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__110ostrstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110ostrstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110ostrstreamD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__110to_wstringEy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__call_onceERVmPvPFvS2_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db10__insert_cEPvPFPNS_8__c_nodeES1_S1_S3_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db10__insert_iEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db11__insert_icEPvPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db15__iterator_copyEPvPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db16__invalidate_allEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db4swapEPvS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db9__erase_cEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_db9__erase_iEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_dbC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_dbC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_dbD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__libcpp_dbD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__money_putIcE8__formatEPcRS2_S3_jPKcS5_RKNS_5ctypeIcEEbRKNS_10money_base7patternEccRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESL_SL_i', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__money_putIwE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_Ri', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111__money_putIwE8__formatEPwRS2_S3_jPKwS5_RKNS_5ctypeIwEEbRKNS_10money_base7patternEwwRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNSE_IwNSF_IwEENSH_IwEEEESQ_i', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111regex_errorC1ENS_15regex_constants10error_typeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111regex_errorC2ENS_15regex_constants10error_typeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111regex_errorD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111regex_errorD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111regex_errorD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111this_thread9sleep_forERKNS_6chrono8durationIxNS_5ratioILl1ELl1000000000EEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutex4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutex6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutex8try_lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutexC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutexC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutexD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111timed_mutexD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__111try_to_lockE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112__do_nothingEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__get_sp_mutEPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__next_primeEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_default4__c_E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultC1ERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultC2ERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112__rs_defaultclEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112bad_weak_ptrD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112bad_weak_ptrD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112bad_weak_ptrD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE21__grow_by_and_replaceEmmmmmmPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE2atEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4nposE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5eraseEmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendERKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEmc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignERKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEmc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertENS_11__wrap_iterIPKcEEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmRKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmmc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6resizeEmc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_RKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_mmRKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_RKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_mmRKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSERKS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE21__grow_by_and_replaceEmmmmmmPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE2atEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4nposE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5eraseEmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEmw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEPKwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendERKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEmw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEPKwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignERKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEmw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertENS_11__wrap_iterIPKwEEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmPKwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmRKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmmw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_RKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_mmRKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_RKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_mmRKS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEaSERKS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEaSEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIcED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112ctype_bynameIwED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112format_errorD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112format_errorD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112format_errorD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112future_errorC1ENS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112future_errorC2ENS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112future_errorD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112future_errorD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112future_errorD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_1E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_2E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_3E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_4E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_5E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_6E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_7E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_8E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders2_9E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112placeholders3_10E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf3strEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf4swapERS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf6__initEPclS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf6freezeEb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf7seekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf7seekposENS_4fposI11__mbstate_tEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf8overflowEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf9pbackfailEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambuf9underflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPFPvmEPFvS1_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPKal', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPKcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPKhl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPalS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPclS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1EPhlS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC1El', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPFPvmEPFvS1_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPKal', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPKcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPKhl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPalS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPclS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2EPhlS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufC2El', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112strstreambufD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_error6__initERKNS_10error_codeENS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC1ENS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC1ENS_10error_codeEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC1ENS_10error_codeERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC1EiRKNS_14error_categoryE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC1EiRKNS_14error_categoryEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC1EiRKNS_14error_categoryERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC2ENS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC2ENS_10error_codeEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC2ENS_10error_codeERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC2EiRKNS_14error_categoryE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC2EiRKNS_14error_categoryEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorC2EiRKNS_14error_categoryERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__112system_errorD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113allocator_argE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE11__read_modeEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE12__write_modeEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE4syncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE5closeEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE5imbueERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE6setbufEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE7seekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE7seekposENS_4fposI11__mbstate_tEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE8overflowEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE9pbackfailEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEE9underflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEEC1EOS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEEC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEEC2EOS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEEC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_filebufIcNS_11char_traitsIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getEPclc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4peekEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4readEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4syncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE5seekgENS_4fposI11__mbstate_tEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE5seekgExNS_8ios_base7seekdirE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE5tellgEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE5ungetEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE6ignoreEli', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE6sentryC1ERS3_b', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE6sentryC2ERS3_b', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE7getlineEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE7getlineEPclc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE7putbackEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE8readsomeEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_8ios_baseES5_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_9basic_iosIcS2_EES6_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRS3_S4_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERs', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERt', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getEPwlw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4peekEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4readEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4syncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE5seekgENS_4fposI11__mbstate_tEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE5seekgExNS_8ios_base7seekdirE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE5tellgEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE5ungetEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE6ignoreEli', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE6sentryC1ERS3_b', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE6sentryC2ERS3_b', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE7getlineEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE7getlineEPwlw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE7putbackEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE8readsomeEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_8ios_baseES5_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_9basic_iosIwS2_EES6_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRS3_S4_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERs', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERt', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsERy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpENS_4fposI11__mbstate_tEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpExNS_8ios_base7seekdirE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5tellpEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5writeEPKcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryC1ERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryC2ERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_8ios_baseES5_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_9basic_iosIcS2_EES6_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEs', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEt', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE3putEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5flushEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpENS_4fposI11__mbstate_tEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpExNS_8ios_base7seekdirE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5tellpEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5writeEPKwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE6sentryC1ERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE6sentryC2ERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE6sentryD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE6sentryD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_8ios_baseES5_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_9basic_iosIwS2_EES6_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRS3_S4_E', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPNS_15basic_streambufIwS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEs', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEt', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113random_deviceC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113random_deviceC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113random_deviceD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113random_deviceD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113random_deviceclEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__get_const_dbEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__num_get_base5__srcE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__num_put_base14__format_floatEPcPKcj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__num_put_base18__identify_paddingEPcS1_RKNS_8ios_baseE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__shared_count12__add_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__shared_count16__release_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__shared_countD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__shared_countD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114__shared_countD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_ifstreamIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_ifstreamIcNS_11char_traitsIcEEE4openERKNS_12basic_stringIcS2_NS_9allocatorIcEEEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_ofstreamIcNS_11char_traitsIcEEE4openEPKcj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114basic_ofstreamIcNS_11char_traitsIcEEE4openERKNS_12basic_stringIcS2_NS_9allocatorIcEEEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDiDu11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDiDu11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDiDu11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDic11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDic11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDic11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDsDu11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDsDu11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDsDu11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDsc11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDsc11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIDsc11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIcc11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIcc11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIcc11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIwc11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIwc11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114codecvt_bynameIwc11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIcED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114collate_bynameIwED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114error_categoryC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114error_categoryD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114error_categoryD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__114error_categoryD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__get_classnameEPKcb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__thread_struct25notify_all_at_thread_exitEPNS_18condition_variableEPNS_5mutexE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__thread_struct27__make_ready_at_thread_exitEPNS_17__assoc_sub_stateE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__thread_structC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__thread_structC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__thread_structD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115__thread_structD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekposENS_4fposI11__mbstate_tEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setgEPcS4_S4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setpEPcS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4syncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5gbumpEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5imbueERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5pbumpEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetnEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputcEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputnEPKcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5uflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6sbumpcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6setbufEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6snextcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6xsgetnEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6xsputnEPKcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7pubsyncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7seekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7seekposENS_4fposI11__mbstate_tEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7sungetcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8in_availEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8overflowEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8pubimbueERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9pbackfailEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9pubsetbufEPcl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9showmanycEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9sputbackcEc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9underflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEEC1ERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEEC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEEC2ERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEEC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIcNS_11char_traitsIcEEEaSERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekposENS_4fposI11__mbstate_tEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setgEPwS4_S4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setpEPwS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4swapERS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4syncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5gbumpEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5imbueERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5pbumpEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetnEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputcEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputnEPKwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5uflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6sbumpcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6setbufEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6snextcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6xsgetnEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6xsputnEPKwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7pubsyncEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7seekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7seekposENS_4fposI11__mbstate_tEEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7sungetcEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8in_availEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8overflowEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8pubimbueERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9pbackfailEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9pubsetbufEPwl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9showmanycEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9sputbackcEw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9underflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEEC1ERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEEC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEEC2ERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEEC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_streambufIwNS_11char_traitsIwEEEaSERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE3strERKNS_12basic_stringIcS2_S4_EE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE4swapERS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE7seekoffExNS_8ios_base7seekdirEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE8overflowEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE9pbackfailEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEE9underflowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEC1EOS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEC2EOS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115future_categoryEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcE6__initEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIcED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwE6__initEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115numpunct_bynameIwED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutex4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutex6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutex8try_lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutexC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutexC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutexD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115recursive_mutexD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__115system_categoryEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__check_groupingERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjS8_Rj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__narrow_to_utf8ILm16EED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__narrow_to_utf8ILm16EED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__narrow_to_utf8ILm16EED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__narrow_to_utf8ILm32EED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__narrow_to_utf8ILm32EED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116__narrow_to_utf8ILm32EED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__116generic_categoryEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state10__sub_waitERNS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state12__make_readyEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state13set_exceptionESt13exception_ptr', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state16__on_zero_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state24set_value_at_thread_exitEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state28set_exception_at_thread_exitESt13exception_ptr', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state4copyEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state4waitEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state9__executeEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__assoc_sub_state9set_valueEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__widen_from_utf8ILm16EED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__widen_from_utf8ILm16EED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__widen_from_utf8ILm16EED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__widen_from_utf8ILm32EED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__widen_from_utf8ILm32EED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117__widen_from_utf8ILm32EED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117declare_reachableEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117iostream_categoryEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117moneypunct_bynameIcLb0EE4initEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117moneypunct_bynameIcLb1EE4initEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117moneypunct_bynameIwLb0EE4initEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__117moneypunct_bynameIwLb1EE4initEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIcE4initERKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIcE9__analyzeEcRKNS_5ctypeIcEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIcEC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIcEC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIwE4initERKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIwE9__analyzeEcRKNS_5ctypeIwEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIwEC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIwEC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118__time_get_storageIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118condition_variable10notify_allEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118condition_variable10notify_oneEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118condition_variable15__do_timed_waitERNS_11unique_lockINS_5mutexEEENS_6chrono10time_pointINS5_12system_clockENS5_8durationIxNS_5ratioILl1ELl1000000000EEEEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118condition_variable4waitERNS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118condition_variableD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118condition_variableD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex11lock_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex13unlock_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex15try_lock_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex8try_lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutexC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutexC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base8try_lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_baseC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_baseC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_count10__add_weakEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_count12__add_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_count14__release_weakEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_count16__release_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_count4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119__thread_local_dataEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119declare_no_pointersEPcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__119piecewise_constructE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__120__get_collation_nameEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEEx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__120__libcpp_atomic_waitEPVKvx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__120__throw_system_errorEiPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121__throw_runtime_errorEPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121__undeclare_reachableEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutex4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutex6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutex8try_lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutexD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__121undeclare_no_pointersEPcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__cxx_atomic_notify_allEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__cxx_atomic_notify_allEPVKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__cxx_atomic_notify_oneEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__123__libcpp_debug_functionE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIeeEEPeEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIffEEPfEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIhhEEPhEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIiiEEPiEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIjjEEPjEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIllEEPlEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessImmEEPmEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIssEEPsEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIttEEPtEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIwwEEPwEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIxxEEPxEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__insertion_sort_incompleteIRNS_6__lessIyyEEPyEEbT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__129__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__13cinE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem10__absoluteERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem10hash_valueERKNS1_4pathE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem11__canonicalERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem11__copy_fileERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem11__file_sizeERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem12__equivalentERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem12__remove_allERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem13__fs_is_emptyERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem13__permissionsERKNS1_4pathENS1_5permsENS1_12perm_optionsEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem13__resize_fileERKNS1_4pathEmPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__copy_symlinkERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__current_pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__current_pathERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__read_symlinkERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem15directory_entry12__do_refreshEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16_FilesystemClock3nowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16_FilesystemClock9is_steadyE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16__create_symlinkERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16__symlink_statusERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_error13__create_whatEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_errorD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_errorD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_errorD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem17__hard_link_countERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathENS_6chrono10time_pointINS1_16_FilesystemClockENS5_8durationInNS_5ratioILl1ELl1000000000EEEEEEEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__create_directoryERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__create_directoryERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__create_hard_linkERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__weakly_canonicalERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18directory_iterator11__incrementEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18directory_iteratorC1ERKNS1_4pathEPNS_10error_codeENS1_17directory_optionsE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18directory_iteratorC2ERKNS1_4pathEPNS_10error_codeENS1_17directory_optionsE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem20__create_directoriesERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem21__temp_directory_pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem26__create_directory_symlinkERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator11__incrementEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator15__try_recursionEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator5__popEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator9__advanceEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iteratorC1ERKNS1_4pathENS1_17directory_optionsEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iteratorC2ERKNS1_4pathENS1_17directory_optionsEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path17replace_extensionERKS2_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path19preferred_separatorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path8iterator11__decrementEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path8iterator11__incrementEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem6__copyERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem7__spaceERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem8__removeERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem8__renameERKNS1_4pathES4_PNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem8__statusERKNS1_4pathEPNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14cerrE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__14clogE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__14coutE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__14stodERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stodERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stofERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stofERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stoiERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stoiERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stolERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14stolERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__14wcinE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__15alignEmmRPvRm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcE13classic_tableEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcEC1EPKjbm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcEC2EPKjbm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIcED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIwE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIwED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIwED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15ctypeIwED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15mutex4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15mutex6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15mutex8try_lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15mutexD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15mutexD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15stoldERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15stoldERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15stollERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15stollERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15stoulERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15stoulERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__15wcerrE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__15wclogE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__15wcoutE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16__itoa8__u32toaEjPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__itoa8__u64toaEyPc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIccEEPcEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIddEEPdEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIeeEEPeEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIffEEPfEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIhhEEPhEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIiiEEPiEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIjjEEPjEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIllEEPlEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessImmEEPmEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIssEEPsEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIttEEPtEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIwwEEPwEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIxxEEPxEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16__sortIRNS_6__lessIyyEEPyEEvT0_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16chrono12steady_clock3nowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16chrono12steady_clock9is_steadyE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16chrono12system_clock11from_time_tEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16chrono12system_clock3nowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16chrono12system_clock9is_steadyE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16chrono12system_clock9to_time_tERKNS0_10time_pointIS1_NS0_8durationIxNS_5ratioILl1ELl1000000EEEEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16futureIvE3getEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16futureIvEC1EPNS_17__assoc_sub_stateE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16futureIvEC2EPNS_17__assoc_sub_stateE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16futureIvED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16futureIvED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16gslice6__initEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale14__install_ctorERKS0_PNS0_5facetEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale2id5__getEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale2id6__initEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale2id9__next_idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale3allE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale4noneE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale4timeE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale5ctypeE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale5facet16__on_zero_sharedEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale5facetD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale5facetD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale5facetD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale6globalERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale7classicEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale7collateE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale7numericE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale8__globalEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16locale8messagesE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16locale8monetaryE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1ERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1ERKS0_PKci', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1ERKS0_RKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1ERKS0_S2_i', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2EPKc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2ERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2ERKS0_PKci', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2ERKS0_RKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2ERKS0_S2_i', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16localeaSERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16stoullERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16stoullERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16thread20hardware_concurrencyEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16thread4joinEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16thread6detachEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16threadD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__16threadD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17__sort5IRNS_6__lessIeeEEPeEEjT0_S5_S5_S5_S5_T_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDiDu11__mbstate_tE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDiDu11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDiDu11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDiDu11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDic11__mbstate_tE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDic11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDic11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDic11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsDu11__mbstate_tE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsDu11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsDu11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsDu11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsc11__mbstate_tE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsc11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsc11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIDsc11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIcc11__mbstate_tE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIcc11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIcc11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIcc11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tEC1EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tEC1Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tEC2EPKcm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tEC2Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17codecvtIwc11__mbstate_tED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17collateIcE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17collateIcED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17collateIcED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17collateIcED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17collateIwE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17collateIwED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17collateIwED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17collateIwED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvE10get_futureEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvE13set_exceptionESt13exception_ptr', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvE24set_value_at_thread_exitEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvE28set_exception_at_thread_exitESt13exception_ptr', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvE9set_valueEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvEC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvEC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__17promiseIvED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__c_node5__addEPNS_8__i_nodeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__c_nodeD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__c_nodeD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__c_nodeD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__get_dbEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__i_nodeD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__i_nodeD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__rs_getEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__sp_mut4lockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18__sp_mut6unlockEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base10floatfieldE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base10scientificE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base11adjustfieldE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base15sync_with_stdioEb', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base16__call_callbacksENS0_5eventE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base17register_callbackEPFvNS0_5eventERS0_iEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base2inE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base33__set_badbit_and_consider_rethrowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base34__set_failbit_and_consider_rethrowEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base3appE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base3ateE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base3decE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base3hexE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base3octE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base3outE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4InitC1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4InitC2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4InitD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4InitD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4initEPv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4leftE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4moveERS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base4swapERS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5clearEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5fixedE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5imbueERKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5iwordEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5pwordEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5rightE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base5truncE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base6badbitE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base6binaryE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base6eofbitE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base6skipwsE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base6xallocEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7copyfmtERKS0_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failbitE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureC1EPKcRKNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureC2EPKcRKNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_10error_codeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7failureD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7goodbitE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7showposE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base7unitbufE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base8internalE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base8showbaseE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base9__xindex_E', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base9basefieldE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base9boolalphaE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base9showpointE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_base9uppercaseE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18ios_baseD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_baseD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18ios_baseD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18messagesIcE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18messagesIwE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIcE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIcEC1Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIcEC2Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIcED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIcED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIcED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIwE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIwEC1Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIwEC2Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIwED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIwED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18numpunctIwED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__18valarrayImE6resizeEmm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18valarrayImEC1Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18valarrayImEC2Em', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18valarrayImED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__18valarrayImED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIcE17__stage2_int_loopEciPcRS2_RjcRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSD_S2_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIcE17__stage2_int_prepERNS_8ios_baseEPcRc', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIcE19__stage2_float_loopEcRbRcPcRS4_ccRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSE_RjS4_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIcE19__stage2_float_prepERNS_8ios_baseEPcRcS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIwE17__stage2_int_loopEwiPcRS2_RjwRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSD_Pw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIwE17__stage2_int_prepERNS_8ios_baseEPwRw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIwE19__stage2_float_loopEwRbRcPcRS4_wwRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSE_RjPw', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_getIwE19__stage2_float_prepERNS_8ios_baseEPwRwS5_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_putIcE21__widen_and_group_intEPcS2_S2_S2_RS2_S3_RKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_putIcE23__widen_and_group_floatEPcS2_S2_S2_RS2_S3_RKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_putIwE21__widen_and_group_intEPcS2_S2_PwRS3_S4_RKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19__num_putIwE23__widen_and_group_floatEPcS2_S2_PwRS3_S4_RKNS_6localeE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIcNS_11char_traitsIcEEE7copyfmtERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIcNS_11char_traitsIcEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIwNS_11char_traitsIwEEE7copyfmtERKS3_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIwNS_11char_traitsIwEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIwNS_11char_traitsIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19basic_iosIwNS_11char_traitsIwEEED2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE8__do_getERS4_S4_bRKNS_6localeEjRjRbRKNS_5ctypeIcEERNS_10unique_ptrIcPFvPvEEERPcSM_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE8__do_getERS4_S4_bRKNS_6localeEjRjRbRKNS_5ctypeIwEERNS_10unique_ptrIwPFvPvEEERPwSM_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__19money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZNSt3__19strstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19strstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19strstreamD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEd', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEe', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEf', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEi', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEj', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEl', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEm', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEx', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__19to_stringEy', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__1plIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_12basic_stringIT_T0_T1_EEPKS6_RKS9_', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt8bad_castC1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt8bad_castC2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt8bad_castD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt8bad_castD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt8bad_castD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9bad_allocC1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9bad_allocC2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9bad_allocD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9bad_allocD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9bad_allocD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9exceptionD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9exceptionD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9type_infoD0Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9type_infoD1Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt9type_infoD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt10unexpectedv', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt13get_terminatev', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt13set_terminatePFvvE', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt14get_unexpectedv', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt14set_unexpectedPFvvE', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt15get_new_handlerv', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt15set_new_handlerPFvvE', 'type': 'I'} +{'is_defined': True, 'name': '__ZSt17__throw_bad_allocv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZSt17current_exceptionv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZSt17rethrow_exceptionSt13exception_ptr', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZSt18uncaught_exceptionv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZSt19uncaught_exceptionsv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZSt7nothrow', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZSt9terminatev', 'type': 'I'} +{'is_defined': True, 'name': '__ZTCNSt3__110istrstreamE0_NS_13basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__110ostrstreamE0_NS_13basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE0_NS_13basic_istreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__114basic_iostreamIcNS_11char_traitsIcEEEE0_NS_13basic_istreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__114basic_iostreamIcNS_11char_traitsIcEEEE16_NS_13basic_ostreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__114basic_ofstreamIcNS_11char_traitsIcEEEE0_NS_13basic_ostreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_13basic_istreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_14basic_iostreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE16_NS_13basic_ostreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_13basic_istreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_13basic_ostreamIcS2_EE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__19strstreamE0_NS_13basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__19strstreamE0_NS_14basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTCNSt3__19strstreamE16_NS_13basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTIDi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIDn', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIDs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTINSt12experimental15fundamentals_v112bad_any_castE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt12experimental19bad_optional_accessE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__110istrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__110moneypunctIcLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__110moneypunctIcLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__110moneypunctIwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__110moneypunctIwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__110ostrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__111regex_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112bad_weak_ptrE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112ctype_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112ctype_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112format_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112future_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112strstreambufE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__112system_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__113basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114__codecvt_utf8IDiEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114__codecvt_utf8IDsEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114__codecvt_utf8IwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114__shared_countE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114basic_ofstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114codecvt_bynameIDiDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114codecvt_bynameIDic11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114codecvt_bynameIDsDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114codecvt_bynameIDsc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114codecvt_bynameIcc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114codecvt_bynameIwc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114collate_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114collate_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__114error_categoryE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115__codecvt_utf16IDiLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115__codecvt_utf16IDiLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115__codecvt_utf16IDsLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115__codecvt_utf16IDsLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115__codecvt_utf16IwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115__codecvt_utf16IwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115basic_streambufIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115basic_streambufIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115messages_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115messages_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115numpunct_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115numpunct_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115time_get_bynameIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115time_get_bynameIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115time_put_bynameIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__115time_put_bynameIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__116__narrow_to_utf8ILm16EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__116__narrow_to_utf8ILm32EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117__assoc_sub_stateE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117__widen_from_utf8ILm16EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117__widen_from_utf8ILm32EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117moneypunct_bynameIcLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117moneypunct_bynameIcLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117moneypunct_bynameIwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__117moneypunct_bynameIwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__119__shared_weak_countE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__120__codecvt_utf8_utf16IDiEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__120__codecvt_utf8_utf16IDsEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__120__codecvt_utf8_utf16IwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__14__fs10filesystem16filesystem_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__15ctypeIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__15ctypeIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__16locale5facetE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17codecvtIDiDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17codecvtIDic11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17codecvtIDsDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17codecvtIDsc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17codecvtIcc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17codecvtIwc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17collateIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17collateIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18__c_nodeE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18ios_base7failureE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18ios_baseE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18messagesIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18messagesIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18numpunctIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18numpunctIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__18time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19basic_iosIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19basic_iosIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTINSt3__19strstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTIPDi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPDn', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPDs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKDi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKDn', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKDs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKa', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKb', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKd', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKe', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKf', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKh', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKj', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKl', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKm', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKt', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKv', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKw', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKx', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPKy', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPa', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPb', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPd', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPe', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPf', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPh', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPj', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPl', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPm', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPt', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPv', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPw', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPx', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIPy', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt10bad_typeid', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt11logic_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt11range_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt12bad_any_cast', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTISt12domain_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt12length_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt12out_of_range', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt13bad_exception', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt13runtime_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt14overflow_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt15underflow_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt16invalid_argument', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt16nested_exception', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTISt18bad_variant_access', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTISt19bad_optional_access', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTISt20bad_array_new_length', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt8bad_cast', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt9bad_alloc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt9exception', 'type': 'I'} +{'is_defined': True, 'name': '__ZTISt9type_info', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIa', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIb', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTId', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIe', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIf', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIh', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIj', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIl', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIm', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIt', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIv', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIw', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIx', 'type': 'I'} +{'is_defined': True, 'name': '__ZTIy', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSDi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSDn', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSDs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv116__enum_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv117__array_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv117__class_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv117__pbase_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv119__pointer_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv120__function_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv120__si_class_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv121__vmi_class_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv123__fundamental_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSN10__cxxabiv129__pointer_to_member_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt12experimental19bad_optional_accessE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__110istrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__110moneypunctIcLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__110moneypunctIcLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__110moneypunctIwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__110moneypunctIwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__110ostrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__111regex_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112bad_weak_ptrE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112ctype_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112ctype_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112format_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112future_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112strstreambufE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__112system_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__113basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__114basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__114basic_ofstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__114collate_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__114collate_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__114error_categoryE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115basic_streambufIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115basic_streambufIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115messages_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115messages_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115numpunct_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115numpunct_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115time_get_bynameIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115time_get_bynameIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115time_put_bynameIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__115time_put_bynameIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__117moneypunct_bynameIcLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__117moneypunct_bynameIcLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__117moneypunct_bynameIwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__117moneypunct_bynameIwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__14__fs10filesystem16filesystem_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__15ctypeIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__15ctypeIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__16locale5facetE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17codecvtIDiDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17codecvtIDic11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17codecvtIDsDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17codecvtIDsc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17codecvtIcc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17codecvtIwc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17collateIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17collateIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18__c_nodeE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18ios_base7failureE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18ios_baseE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18messagesIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18messagesIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18numpunctIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18numpunctIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__18time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19basic_iosIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19basic_iosIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSNSt3__19strstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSPDi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPDn', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPDs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKDi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKDn', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKDs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKa', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKb', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKd', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKe', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKf', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKh', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKj', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKl', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKm', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKt', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKv', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKw', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKx', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPKy', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPa', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPb', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPd', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPe', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPf', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPh', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPj', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPl', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPm', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPt', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPv', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPw', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPx', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSPy', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt10bad_typeid', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt11logic_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt11range_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt12bad_any_cast', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSSt12domain_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt12length_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt12out_of_range', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt13bad_exception', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt13runtime_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt14overflow_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt15underflow_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt16invalid_argument', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt16nested_exception', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSSt18bad_variant_access', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSSt19bad_optional_access', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTSSt20bad_array_new_length', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt8bad_cast', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt9bad_alloc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt9exception', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSSt9type_info', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSa', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSb', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSd', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSe', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSf', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSh', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSi', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSj', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSl', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSm', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSs', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSt', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSv', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSw', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSx', 'type': 'I'} +{'is_defined': True, 'name': '__ZTSy', 'type': 'I'} +{'is_defined': True, 'name': '__ZTTNSt3__110istrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__110ostrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__113basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__114basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__114basic_ofstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTTNSt3__19strstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv116__enum_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv117__array_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv117__class_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv117__pbase_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv119__pointer_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv120__function_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv120__si_class_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv121__vmi_class_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv123__fundamental_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVN10__cxxabiv129__pointer_to_member_type_infoE', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVNSt12experimental15fundamentals_v112bad_any_castE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt12experimental19bad_optional_accessE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__110istrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__110moneypunctIcLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__110moneypunctIcLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__110moneypunctIwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__110moneypunctIwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__110ostrstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__111regex_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112bad_weak_ptrE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112ctype_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112ctype_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112format_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112future_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112strstreambufE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__112system_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__113basic_filebufIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__113basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__113basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__113basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114__codecvt_utf8IDiEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114__codecvt_utf8IDsEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114__codecvt_utf8IwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114__shared_countE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114basic_ofstreamIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114codecvt_bynameIDiDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114codecvt_bynameIDic11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114codecvt_bynameIDsDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114codecvt_bynameIDsc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114codecvt_bynameIcc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114codecvt_bynameIwc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114collate_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114collate_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__114error_categoryE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115__codecvt_utf16IDiLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115__codecvt_utf16IDiLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115__codecvt_utf16IDsLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115__codecvt_utf16IDsLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115__codecvt_utf16IwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115__codecvt_utf16IwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115basic_streambufIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115basic_streambufIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115messages_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115messages_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115numpunct_bynameIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115numpunct_bynameIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115time_get_bynameIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115time_get_bynameIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115time_put_bynameIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__115time_put_bynameIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__116__narrow_to_utf8ILm16EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__116__narrow_to_utf8ILm32EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117__assoc_sub_stateE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117__widen_from_utf8ILm16EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117__widen_from_utf8ILm32EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117moneypunct_bynameIcLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117moneypunct_bynameIcLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117moneypunct_bynameIwLb0EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__117moneypunct_bynameIwLb1EEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__119__shared_weak_countE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__120__codecvt_utf8_utf16IDiEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__120__codecvt_utf8_utf16IDsEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__120__codecvt_utf8_utf16IwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__14__fs10filesystem16filesystem_errorE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__15ctypeIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__15ctypeIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__16locale5facetE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17codecvtIDiDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17codecvtIDic11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17codecvtIDsDu11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17codecvtIDsc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17codecvtIcc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17codecvtIwc11__mbstate_tEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17collateIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17collateIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__17num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18__c_nodeE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18ios_base7failureE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18ios_baseE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18messagesIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18messagesIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18numpunctIcEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18numpunctIwEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__18time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19basic_iosIcNS_11char_traitsIcEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19basic_iosIwNS_11char_traitsIwEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVNSt3__19strstreamE', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVSt10bad_typeid', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt11logic_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt11range_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt12bad_any_cast', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVSt12domain_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt12length_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt12out_of_range', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt13bad_exception', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt13runtime_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt14overflow_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt15underflow_error', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt16invalid_argument', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt16nested_exception', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVSt18bad_variant_access', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVSt19bad_optional_access', 'size': 0, 'type': 'OBJECT'} +{'is_defined': True, 'name': '__ZTVSt20bad_array_new_length', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt8bad_cast', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt9bad_alloc', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt9exception', 'type': 'I'} +{'is_defined': True, 'name': '__ZTVSt9type_info', 'type': 'I'} +{'is_defined': True, 'name': '__ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZThn16_NSt3__19strstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZThn16_NSt3__19strstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__110istrstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__110istrstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__110ostrstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__110ostrstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_istreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_istreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_istreamIwNS_11char_traitsIwEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_istreamIwNS_11char_traitsIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_ostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_ostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_ostreamIwNS_11char_traitsIwEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__113basic_ostreamIwNS_11char_traitsIwEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__19strstreamD0Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZdaPv', 'type': 'I'} +{'is_defined': True, 'name': '__ZdaPvRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdaPvSt11align_val_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdaPvSt11align_val_tRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdaPvm', 'type': 'I'} +{'is_defined': True, 'name': '__ZdaPvmSt11align_val_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdlPv', 'type': 'I'} +{'is_defined': True, 'name': '__ZdlPvRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdlPvSt11align_val_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdlPvSt11align_val_tRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZdlPvm', 'type': 'I'} +{'is_defined': True, 'name': '__ZdlPvmSt11align_val_t', 'type': 'I'} +{'is_defined': True, 'name': '__Znam', 'type': 'I'} +{'is_defined': True, 'name': '__ZnamRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZnamSt11align_val_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZnamSt11align_val_tRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__Znwm', 'type': 'I'} +{'is_defined': True, 'name': '__ZnwmRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZnwmSt11align_val_t', 'type': 'I'} +{'is_defined': True, 'name': '__ZnwmSt11align_val_tRKSt9nothrow_t', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_allocate_dependent_exception', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_allocate_exception', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_bad_cast', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_bad_typeid', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_begin_catch', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_call_unexpected', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_current_exception_type', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_deleted_virtual', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_demangle', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_end_catch', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_free_dependent_exception', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_free_exception', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_get_exception_ptr', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_get_globals', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_get_globals_fast', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_guard_abort', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_guard_acquire', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_guard_release', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_pure_virtual', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_rethrow', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_throw', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_throw_bad_array_new_length', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_uncaught_exceptions', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_cctor', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_cleanup', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_ctor', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_delete', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_delete2', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_delete3', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_dtor', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_new', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_new2', 'type': 'I'} +{'is_defined': True, 'name': '___cxa_vec_new3', 'type': 'I'} +{'is_defined': True, 'name': '___dynamic_cast', 'type': 'I'} +{'is_defined': True, 'name': '___gxx_personality_v0', 'type': 'I'} \ No newline at end of file diff --git a/libcxx/test/CMakeLists.txt b/libcxx/test/CMakeLists.txt index 0252ff42963ff..58e95b8be2a75 100644 --- a/libcxx/test/CMakeLists.txt +++ b/libcxx/test/CMakeLists.txt @@ -105,8 +105,8 @@ if (NOT LIBCXX_ENABLE_DEBUG_MODE_SUPPORT) serialize_lit_param(enable_debug_tests False) endif() -if (TARGET_TRIPLE) - serialize_lit_param(target_triple "\"${TARGET_TRIPLE}\"") +if (LIBCXX_TARGET_TRIPLE) + serialize_lit_param(target_triple "\"${LIBCXX_TARGET_TRIPLE}\"") endif() if (LLVM_USE_SANITIZER) @@ -117,6 +117,12 @@ if (LIBCXX_BUILD_32_BITS) serialize_lit_param(enable_32bit True) endif() +foreach(param IN LISTS LIBCXX_TEST_PARAMS) + string(REGEX REPLACE "(.+)=(.+)" "\\1" name "${param}") + string(REGEX REPLACE "(.+)=(.+)" "\\2" value "${param}") + serialize_lit_param("${name}" "\"${value}\"") +endforeach() + if (NOT DEFINED LIBCXX_TEST_DEPS) message(FATAL_ERROR "Expected LIBCXX_TEST_DEPS to be defined") endif() @@ -136,8 +142,7 @@ if (LIBCXX_INCLUDE_TESTS) add_lit_testsuite(check-cxx "Running libcxx tests" ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS cxx-test-depends - PARAMS "${LIBCXX_TEST_PARAMS}") + DEPENDS cxx-test-depends) endif() if (LIBCXX_GENERATE_COVERAGE) diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/adjacent_find.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/adjacent_find.module.verify.cpp new file mode 100644 index 0000000000000..e445eca753817 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/adjacent_find.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/adjacent_find.h'}} +#include <__algorithm/adjacent_find.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/all_of.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/all_of.module.verify.cpp new file mode 100644 index 0000000000000..94cbcd38d2399 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/all_of.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/all_of.h'}} +#include <__algorithm/all_of.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/any_of.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/any_of.module.verify.cpp new file mode 100644 index 0000000000000..6a7f3066657a0 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/any_of.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/any_of.h'}} +#include <__algorithm/any_of.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/binary_search.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/binary_search.module.verify.cpp new file mode 100644 index 0000000000000..c5dc84ca6cad3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/binary_search.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/binary_search.h'}} +#include <__algorithm/binary_search.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/clamp.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/clamp.module.verify.cpp new file mode 100644 index 0000000000000..85b7ba3e5c06b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/clamp.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/clamp.h'}} +#include <__algorithm/clamp.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/comp.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/comp.module.verify.cpp new file mode 100644 index 0000000000000..16127b5d37e2f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/comp.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/comp.h'}} +#include <__algorithm/comp.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/comp_ref_type.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/comp_ref_type.module.verify.cpp new file mode 100644 index 0000000000000..3bcfe37a9df4f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/comp_ref_type.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/comp_ref_type.h'}} +#include <__algorithm/comp_ref_type.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy.module.verify.cpp new file mode 100644 index 0000000000000..9dc3406388f0b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/copy.h'}} +#include <__algorithm/copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_backward.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_backward.module.verify.cpp new file mode 100644 index 0000000000000..22cd8cd653e57 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_backward.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/copy_backward.h'}} +#include <__algorithm/copy_backward.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_if.module.verify.cpp new file mode 100644 index 0000000000000..91fff8139151d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/copy_if.h'}} +#include <__algorithm/copy_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_n.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_n.module.verify.cpp new file mode 100644 index 0000000000000..88100beac424d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/copy_n.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/copy_n.h'}} +#include <__algorithm/copy_n.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/count.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/count.module.verify.cpp new file mode 100644 index 0000000000000..40583e7870bcb --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/count.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/count.h'}} +#include <__algorithm/count.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/count_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/count_if.module.verify.cpp new file mode 100644 index 0000000000000..4465c91ec41f1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/count_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/count_if.h'}} +#include <__algorithm/count_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/equal.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/equal.module.verify.cpp new file mode 100644 index 0000000000000..877b70a7ec25b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/equal.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/equal.h'}} +#include <__algorithm/equal.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/equal_range.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/equal_range.module.verify.cpp new file mode 100644 index 0000000000000..e8217712d8dc3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/equal_range.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/equal_range.h'}} +#include <__algorithm/equal_range.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/fill.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/fill.module.verify.cpp new file mode 100644 index 0000000000000..c5d95121fd740 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/fill.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/fill.h'}} +#include <__algorithm/fill.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/fill_n.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/fill_n.module.verify.cpp new file mode 100644 index 0000000000000..b0075472caba8 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/fill_n.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/fill_n.h'}} +#include <__algorithm/fill_n.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find.module.verify.cpp new file mode 100644 index 0000000000000..5e464846ffb88 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/find.h'}} +#include <__algorithm/find.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_end.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_end.module.verify.cpp new file mode 100644 index 0000000000000..0f8788ca0aac3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_end.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/find_end.h'}} +#include <__algorithm/find_end.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_first_of.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_first_of.module.verify.cpp new file mode 100644 index 0000000000000..0d92c1fc655e8 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_first_of.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/find_first_of.h'}} +#include <__algorithm/find_first_of.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_if.module.verify.cpp new file mode 100644 index 0000000000000..123ed3f24e4fd --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/find_if.h'}} +#include <__algorithm/find_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_if_not.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_if_not.module.verify.cpp new file mode 100644 index 0000000000000..af941eede4ff0 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/find_if_not.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/find_if_not.h'}} +#include <__algorithm/find_if_not.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/for_each.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/for_each.module.verify.cpp new file mode 100644 index 0000000000000..d7d37fb341755 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/for_each.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/for_each.h'}} +#include <__algorithm/for_each.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/for_each_n.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/for_each_n.module.verify.cpp new file mode 100644 index 0000000000000..bb777bb97de57 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/for_each_n.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/for_each_n.h'}} +#include <__algorithm/for_each_n.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/generate.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/generate.module.verify.cpp new file mode 100644 index 0000000000000..1d22acb51cefb --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/generate.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/generate.h'}} +#include <__algorithm/generate.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/generate_n.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/generate_n.module.verify.cpp new file mode 100644 index 0000000000000..67984f067113b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/generate_n.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/generate_n.h'}} +#include <__algorithm/generate_n.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/half_positive.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/half_positive.module.verify.cpp new file mode 100644 index 0000000000000..1e69336f7cd55 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/half_positive.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/half_positive.h'}} +#include <__algorithm/half_positive.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/includes.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/includes.module.verify.cpp new file mode 100644 index 0000000000000..16e2b911d8a88 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/includes.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/includes.h'}} +#include <__algorithm/includes.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/inplace_merge.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/inplace_merge.module.verify.cpp new file mode 100644 index 0000000000000..2e8ea0a2fbdd3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/inplace_merge.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/inplace_merge.h'}} +#include <__algorithm/inplace_merge.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_heap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_heap.module.verify.cpp new file mode 100644 index 0000000000000..3bdf3c982e0af --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_heap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/is_heap.h'}} +#include <__algorithm/is_heap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_heap_until.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_heap_until.module.verify.cpp new file mode 100644 index 0000000000000..9545b2d98166f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_heap_until.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/is_heap_until.h'}} +#include <__algorithm/is_heap_until.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_partitioned.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_partitioned.module.verify.cpp new file mode 100644 index 0000000000000..685e9c5bcb27e --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_partitioned.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/is_partitioned.h'}} +#include <__algorithm/is_partitioned.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_permutation.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_permutation.module.verify.cpp new file mode 100644 index 0000000000000..5b3d1ca92ccae --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_permutation.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/is_permutation.h'}} +#include <__algorithm/is_permutation.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_sorted.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_sorted.module.verify.cpp new file mode 100644 index 0000000000000..6bdf25d3cbbe9 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_sorted.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/is_sorted.h'}} +#include <__algorithm/is_sorted.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_sorted_until.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_sorted_until.module.verify.cpp new file mode 100644 index 0000000000000..6f4f12c6f87d8 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/is_sorted_until.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/is_sorted_until.h'}} +#include <__algorithm/is_sorted_until.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/iter_swap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/iter_swap.module.verify.cpp new file mode 100644 index 0000000000000..7db68792f9456 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/iter_swap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/iter_swap.h'}} +#include <__algorithm/iter_swap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/lexicographical_compare.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/lexicographical_compare.module.verify.cpp new file mode 100644 index 0000000000000..7c417f6123877 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/lexicographical_compare.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/lexicographical_compare.h'}} +#include <__algorithm/lexicographical_compare.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/lower_bound.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/lower_bound.module.verify.cpp new file mode 100644 index 0000000000000..5d2347b3acadf --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/lower_bound.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/lower_bound.h'}} +#include <__algorithm/lower_bound.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/make_heap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/make_heap.module.verify.cpp new file mode 100644 index 0000000000000..2ac533eac94fb --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/make_heap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/make_heap.h'}} +#include <__algorithm/make_heap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/max.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/max.module.verify.cpp new file mode 100644 index 0000000000000..51f0e90adc1f7 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/max.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/max.h'}} +#include <__algorithm/max.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/max_element.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/max_element.module.verify.cpp new file mode 100644 index 0000000000000..e25d1927efb0b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/max_element.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/max_element.h'}} +#include <__algorithm/max_element.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/merge.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/merge.module.verify.cpp new file mode 100644 index 0000000000000..5f4ca30aa2163 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/merge.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/merge.h'}} +#include <__algorithm/merge.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/min.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/min.module.verify.cpp new file mode 100644 index 0000000000000..26f265b0efc69 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/min.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/min.h'}} +#include <__algorithm/min.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/min_element.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/min_element.module.verify.cpp new file mode 100644 index 0000000000000..1e4174abd6952 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/min_element.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/min_element.h'}} +#include <__algorithm/min_element.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/minmax.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/minmax.module.verify.cpp new file mode 100644 index 0000000000000..a595d38c9a84b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/minmax.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/minmax.h'}} +#include <__algorithm/minmax.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/minmax_element.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/minmax_element.module.verify.cpp new file mode 100644 index 0000000000000..18d7f7d410134 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/minmax_element.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/minmax_element.h'}} +#include <__algorithm/minmax_element.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/mismatch.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/mismatch.module.verify.cpp new file mode 100644 index 0000000000000..b5645a27b3b6d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/mismatch.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/mismatch.h'}} +#include <__algorithm/mismatch.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/move.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/move.module.verify.cpp new file mode 100644 index 0000000000000..80030e2746d69 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/move.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/move.h'}} +#include <__algorithm/move.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/move_backward.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/move_backward.module.verify.cpp new file mode 100644 index 0000000000000..ef738d00aeee0 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/move_backward.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/move_backward.h'}} +#include <__algorithm/move_backward.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/next_permutation.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/next_permutation.module.verify.cpp new file mode 100644 index 0000000000000..08df0a706eab9 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/next_permutation.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/next_permutation.h'}} +#include <__algorithm/next_permutation.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/none_of.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/none_of.module.verify.cpp new file mode 100644 index 0000000000000..f421b9d53dd17 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/none_of.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/none_of.h'}} +#include <__algorithm/none_of.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/nth_element.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/nth_element.module.verify.cpp new file mode 100644 index 0000000000000..14e69fa16dcda --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/nth_element.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/nth_element.h'}} +#include <__algorithm/nth_element.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partial_sort.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partial_sort.module.verify.cpp new file mode 100644 index 0000000000000..9b189241eb417 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partial_sort.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/partial_sort.h'}} +#include <__algorithm/partial_sort.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partial_sort_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partial_sort_copy.module.verify.cpp new file mode 100644 index 0000000000000..42242f705a3a3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partial_sort_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/partial_sort_copy.h'}} +#include <__algorithm/partial_sort_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition.module.verify.cpp new file mode 100644 index 0000000000000..f7e213663adf1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/partition.h'}} +#include <__algorithm/partition.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition_copy.module.verify.cpp new file mode 100644 index 0000000000000..92462787e7c0d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/partition_copy.h'}} +#include <__algorithm/partition_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition_point.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition_point.module.verify.cpp new file mode 100644 index 0000000000000..e22856ee26008 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/partition_point.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/partition_point.h'}} +#include <__algorithm/partition_point.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/pop_heap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/pop_heap.module.verify.cpp new file mode 100644 index 0000000000000..f5fe44f277cf2 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/pop_heap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/pop_heap.h'}} +#include <__algorithm/pop_heap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/prev_permutation.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/prev_permutation.module.verify.cpp new file mode 100644 index 0000000000000..5d7c7dd72c035 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/prev_permutation.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/prev_permutation.h'}} +#include <__algorithm/prev_permutation.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/push_heap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/push_heap.module.verify.cpp new file mode 100644 index 0000000000000..b1a2d743aa52d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/push_heap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/push_heap.h'}} +#include <__algorithm/push_heap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove.module.verify.cpp new file mode 100644 index 0000000000000..cf78bbcaef773 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/remove.h'}} +#include <__algorithm/remove.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_copy.module.verify.cpp new file mode 100644 index 0000000000000..ff7afca29842f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/remove_copy.h'}} +#include <__algorithm/remove_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_copy_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_copy_if.module.verify.cpp new file mode 100644 index 0000000000000..55a21c529d411 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_copy_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/remove_copy_if.h'}} +#include <__algorithm/remove_copy_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_if.module.verify.cpp new file mode 100644 index 0000000000000..4309184ae51ea --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/remove_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/remove_if.h'}} +#include <__algorithm/remove_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace.module.verify.cpp new file mode 100644 index 0000000000000..ec81e421e68d1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/replace.h'}} +#include <__algorithm/replace.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_copy.module.verify.cpp new file mode 100644 index 0000000000000..cb95f4c97ad72 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/replace_copy.h'}} +#include <__algorithm/replace_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_copy_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_copy_if.module.verify.cpp new file mode 100644 index 0000000000000..b67f7fa87fea9 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_copy_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/replace_copy_if.h'}} +#include <__algorithm/replace_copy_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_if.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_if.module.verify.cpp new file mode 100644 index 0000000000000..616fe024ae11e --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/replace_if.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/replace_if.h'}} +#include <__algorithm/replace_if.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/reverse.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/reverse.module.verify.cpp new file mode 100644 index 0000000000000..6ead238517dd9 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/reverse.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/reverse.h'}} +#include <__algorithm/reverse.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/reverse_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/reverse_copy.module.verify.cpp new file mode 100644 index 0000000000000..8e174853797fb --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/reverse_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/reverse_copy.h'}} +#include <__algorithm/reverse_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/rotate.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/rotate.module.verify.cpp new file mode 100644 index 0000000000000..2cb958c868f65 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/rotate.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/rotate.h'}} +#include <__algorithm/rotate.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/rotate_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/rotate_copy.module.verify.cpp new file mode 100644 index 0000000000000..453c9477691d2 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/rotate_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/rotate_copy.h'}} +#include <__algorithm/rotate_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sample.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sample.module.verify.cpp new file mode 100644 index 0000000000000..bce9021616a79 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sample.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/sample.h'}} +#include <__algorithm/sample.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/search.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/search.module.verify.cpp new file mode 100644 index 0000000000000..965e26e368eb1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/search.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/search.h'}} +#include <__algorithm/search.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/search_n.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/search_n.module.verify.cpp new file mode 100644 index 0000000000000..1b96ca21ba815 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/search_n.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/search_n.h'}} +#include <__algorithm/search_n.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_difference.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_difference.module.verify.cpp new file mode 100644 index 0000000000000..e620e30e54234 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_difference.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/set_difference.h'}} +#include <__algorithm/set_difference.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_intersection.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_intersection.module.verify.cpp new file mode 100644 index 0000000000000..760995e23e55f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_intersection.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/set_intersection.h'}} +#include <__algorithm/set_intersection.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_symmetric_difference.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_symmetric_difference.module.verify.cpp new file mode 100644 index 0000000000000..9d9bdad0e3a00 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_symmetric_difference.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/set_symmetric_difference.h'}} +#include <__algorithm/set_symmetric_difference.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_union.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_union.module.verify.cpp new file mode 100644 index 0000000000000..b33fa8af0f101 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/set_union.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/set_union.h'}} +#include <__algorithm/set_union.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shift_left.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shift_left.module.verify.cpp new file mode 100644 index 0000000000000..14f90a22a106f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shift_left.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/shift_left.h'}} +#include <__algorithm/shift_left.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shift_right.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shift_right.module.verify.cpp new file mode 100644 index 0000000000000..3a07bbda76ac3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shift_right.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/shift_right.h'}} +#include <__algorithm/shift_right.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shuffle.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shuffle.module.verify.cpp new file mode 100644 index 0000000000000..3273d90243767 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/shuffle.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/shuffle.h'}} +#include <__algorithm/shuffle.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sift_down.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sift_down.module.verify.cpp new file mode 100644 index 0000000000000..d4ed87fcfcc6f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sift_down.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/sift_down.h'}} +#include <__algorithm/sift_down.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sort.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sort.module.verify.cpp new file mode 100644 index 0000000000000..42e369b23efb4 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sort.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/sort.h'}} +#include <__algorithm/sort.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sort_heap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sort_heap.module.verify.cpp new file mode 100644 index 0000000000000..fbb405c8f7eaa --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/sort_heap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/sort_heap.h'}} +#include <__algorithm/sort_heap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/stable_partition.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/stable_partition.module.verify.cpp new file mode 100644 index 0000000000000..74edd38515349 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/stable_partition.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/stable_partition.h'}} +#include <__algorithm/stable_partition.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/stable_sort.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/stable_sort.module.verify.cpp new file mode 100644 index 0000000000000..999a0878a7a8f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/stable_sort.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/stable_sort.h'}} +#include <__algorithm/stable_sort.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/swap_ranges.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/swap_ranges.module.verify.cpp new file mode 100644 index 0000000000000..294a06b2cda0b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/swap_ranges.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/swap_ranges.h'}} +#include <__algorithm/swap_ranges.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/transform.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/transform.module.verify.cpp new file mode 100644 index 0000000000000..b9f59dc17ad96 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/transform.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/transform.h'}} +#include <__algorithm/transform.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unique.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unique.module.verify.cpp new file mode 100644 index 0000000000000..c1ee21884b45c --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unique.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/unique.h'}} +#include <__algorithm/unique.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unique_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unique_copy.module.verify.cpp new file mode 100644 index 0000000000000..b589e88d35615 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unique_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/unique_copy.h'}} +#include <__algorithm/unique_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unwrap_iter.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unwrap_iter.module.verify.cpp new file mode 100644 index 0000000000000..f6a80e2178460 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/unwrap_iter.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/unwrap_iter.h'}} +#include <__algorithm/unwrap_iter.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/upper_bound.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/upper_bound.module.verify.cpp new file mode 100644 index 0000000000000..25b065f2e9835 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/algorithm/upper_bound.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__algorithm/upper_bound.h'}} +#include <__algorithm/upper_bound.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/availability.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/availability.module.verify.cpp new file mode 100644 index 0000000000000..4f966e736a871 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/availability.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__availability'}} +#include <__availability> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/bit_reference.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/bit_reference.module.verify.cpp new file mode 100644 index 0000000000000..3676f7ad5c50e --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/bit_reference.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__bit_reference'}} +#include <__bit_reference> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/bits.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/bits.module.verify.cpp new file mode 100644 index 0000000000000..fa9f78495f918 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/bits.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__bits'}} +#include <__bits> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/errc.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/errc.module.verify.cpp new file mode 100644 index 0000000000000..8489223bce611 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/errc.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__errc'}} +#include <__errc> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/format/format_error.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/format/format_error.module.verify.cpp new file mode 100644 index 0000000000000..f6af9432c8ead --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/format/format_error.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__format/format_error.h'}} +#include <__format/format_error.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/format/format_parse_context.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/format/format_parse_context.module.verify.cpp new file mode 100644 index 0000000000000..308f66e8c570f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/format/format_parse_context.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__format/format_parse_context.h'}} +#include <__format/format_parse_context.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/function_like.h.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/function_like.h.module.verify.cpp new file mode 100644 index 0000000000000..f7fd96ebf176f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/function_like.h.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__function_like.h'}} +#include <__function_like.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/binary_function.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binary_function.module.verify.cpp new file mode 100644 index 0000000000000..46be85ab992df --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binary_function.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/binary_function.h'}} +#include <__functional/binary_function.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/binary_negate.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binary_negate.module.verify.cpp new file mode 100644 index 0000000000000..4c9210165b664 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binary_negate.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/binary_negate.h'}} +#include <__functional/binary_negate.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/bind.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/bind.module.verify.cpp new file mode 100644 index 0000000000000..b8616081b7ea1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/bind.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/bind.h'}} +#include <__functional/bind.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/bind_front.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/bind_front.module.verify.cpp new file mode 100644 index 0000000000000..4b2f25f93b941 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/bind_front.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/bind_front.h'}} +#include <__functional/bind_front.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/binder1st.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binder1st.module.verify.cpp new file mode 100644 index 0000000000000..c639813b97859 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binder1st.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/binder1st.h'}} +#include <__functional/binder1st.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/binder2nd.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binder2nd.module.verify.cpp new file mode 100644 index 0000000000000..4f2ba80918727 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/binder2nd.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/binder2nd.h'}} +#include <__functional/binder2nd.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/default_searcher.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/default_searcher.module.verify.cpp new file mode 100644 index 0000000000000..7fe174a3f4a5d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/default_searcher.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/default_searcher.h'}} +#include <__functional/default_searcher.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/function.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/function.module.verify.cpp new file mode 100644 index 0000000000000..16bd1ddeb09c9 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/function.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/function.h'}} +#include <__functional/function.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/hash.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/hash.module.verify.cpp new file mode 100644 index 0000000000000..ecb2c0a39fa01 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/hash.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/hash.h'}} +#include <__functional/hash.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/identity.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/identity.module.verify.cpp new file mode 100644 index 0000000000000..b795b5ddc6e18 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/identity.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/identity.h'}} +#include <__functional/identity.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/invoke.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/invoke.module.verify.cpp new file mode 100644 index 0000000000000..a368dc1ce0356 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/invoke.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/invoke.h'}} +#include <__functional/invoke.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/is_transparent.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/is_transparent.module.verify.cpp new file mode 100644 index 0000000000000..3f226199bae5a --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/is_transparent.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/is_transparent.h'}} +#include <__functional/is_transparent.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/mem_fn.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/mem_fn.module.verify.cpp new file mode 100644 index 0000000000000..0d8e9c4816860 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/mem_fn.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/mem_fn.h'}} +#include <__functional/mem_fn.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/mem_fun_ref.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/mem_fun_ref.module.verify.cpp new file mode 100644 index 0000000000000..f28a1670f7ddd --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/mem_fun_ref.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/mem_fun_ref.h'}} +#include <__functional/mem_fun_ref.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/not_fn.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/not_fn.module.verify.cpp new file mode 100644 index 0000000000000..d0c50107d5128 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/not_fn.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/not_fn.h'}} +#include <__functional/not_fn.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/operations.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/operations.module.verify.cpp new file mode 100644 index 0000000000000..5f377080cb74c --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/operations.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/operations.h'}} +#include <__functional/operations.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/perfect_forward.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/perfect_forward.module.verify.cpp new file mode 100644 index 0000000000000..a08a3cf1943cc --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/perfect_forward.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/perfect_forward.h'}} +#include <__functional/perfect_forward.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/pointer_to_binary_function.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/pointer_to_binary_function.module.verify.cpp new file mode 100644 index 0000000000000..f98e81925cc69 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/pointer_to_binary_function.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/pointer_to_binary_function.h'}} +#include <__functional/pointer_to_binary_function.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/pointer_to_unary_function.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/pointer_to_unary_function.module.verify.cpp new file mode 100644 index 0000000000000..7196117d08e37 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/pointer_to_unary_function.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/pointer_to_unary_function.h'}} +#include <__functional/pointer_to_unary_function.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/ranges_operations.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/ranges_operations.module.verify.cpp new file mode 100644 index 0000000000000..17cb624fc70fb --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/ranges_operations.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/ranges_operations.h'}} +#include <__functional/ranges_operations.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/reference_wrapper.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/reference_wrapper.module.verify.cpp new file mode 100644 index 0000000000000..06b3bdd76d5ee --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/reference_wrapper.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/reference_wrapper.h'}} +#include <__functional/reference_wrapper.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/unary_function.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/unary_function.module.verify.cpp new file mode 100644 index 0000000000000..aa2b688d277aa --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/unary_function.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/unary_function.h'}} +#include <__functional/unary_function.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/unary_negate.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/unary_negate.module.verify.cpp new file mode 100644 index 0000000000000..0b1a9761f6393 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/unary_negate.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/unary_negate.h'}} +#include <__functional/unary_negate.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/unwrap_ref.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/unwrap_ref.module.verify.cpp new file mode 100644 index 0000000000000..804b2fb2221d3 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/unwrap_ref.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/unwrap_ref.h'}} +#include <__functional/unwrap_ref.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/functional/weak_result_type.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/functional/weak_result_type.module.verify.cpp new file mode 100644 index 0000000000000..8cc289342d266 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/functional/weak_result_type.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__functional/weak_result_type.h'}} +#include <__functional/weak_result_type.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/access.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/access.module.verify.cpp new file mode 100644 index 0000000000000..c0caedb4a4025 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/access.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/access.h'}} +#include <__iterator/access.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/advance.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/advance.module.verify.cpp new file mode 100644 index 0000000000000..9c2836c03c222 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/advance.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/advance.h'}} +#include <__iterator/advance.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/back_insert_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/back_insert_iterator.module.verify.cpp new file mode 100644 index 0000000000000..a1a49b9c9adbb --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/back_insert_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/back_insert_iterator.h'}} +#include <__iterator/back_insert_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/concepts.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/concepts.module.verify.cpp new file mode 100644 index 0000000000000..6e34ff0c3bd1f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/concepts.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/concepts.h'}} +#include <__iterator/concepts.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/data.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/data.module.verify.cpp new file mode 100644 index 0000000000000..eabd8e712ba26 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/data.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/data.h'}} +#include <__iterator/data.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/default_sentinel.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/default_sentinel.module.verify.cpp new file mode 100644 index 0000000000000..1f0f817c0ae19 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/default_sentinel.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/default_sentinel.h'}} +#include <__iterator/default_sentinel.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/distance.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/distance.module.verify.cpp new file mode 100644 index 0000000000000..b9df11c968667 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/distance.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/distance.h'}} +#include <__iterator/distance.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/empty.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/empty.module.verify.cpp new file mode 100644 index 0000000000000..5543561643d57 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/empty.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/empty.h'}} +#include <__iterator/empty.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/erase_if_container.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/erase_if_container.module.verify.cpp new file mode 100644 index 0000000000000..b1ac8ff129557 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/erase_if_container.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/erase_if_container.h'}} +#include <__iterator/erase_if_container.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/front_insert_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/front_insert_iterator.module.verify.cpp new file mode 100644 index 0000000000000..b18066442fd4a --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/front_insert_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/front_insert_iterator.h'}} +#include <__iterator/front_insert_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/incrementable_traits.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/incrementable_traits.module.verify.cpp new file mode 100644 index 0000000000000..c42bc62a2a693 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/incrementable_traits.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/incrementable_traits.h'}} +#include <__iterator/incrementable_traits.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/insert_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/insert_iterator.module.verify.cpp new file mode 100644 index 0000000000000..b9a307c50b332 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/insert_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/insert_iterator.h'}} +#include <__iterator/insert_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/istream_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/istream_iterator.module.verify.cpp new file mode 100644 index 0000000000000..df7989fd7b32d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/istream_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/istream_iterator.h'}} +#include <__iterator/istream_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/istreambuf_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/istreambuf_iterator.module.verify.cpp new file mode 100644 index 0000000000000..8572c81aa92d1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/istreambuf_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/istreambuf_iterator.h'}} +#include <__iterator/istreambuf_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iter_move.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iter_move.module.verify.cpp new file mode 100644 index 0000000000000..ef98fd535e0f2 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iter_move.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/iter_move.h'}} +#include <__iterator/iter_move.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iter_swap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iter_swap.module.verify.cpp new file mode 100644 index 0000000000000..110324b77b4f1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iter_swap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/iter_swap.h'}} +#include <__iterator/iter_swap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iterator.module.verify.cpp new file mode 100644 index 0000000000000..cb565d969ccda --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/iterator.h'}} +#include <__iterator/iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iterator_traits.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iterator_traits.module.verify.cpp new file mode 100644 index 0000000000000..9e4c0c42d88b0 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/iterator_traits.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/iterator_traits.h'}} +#include <__iterator/iterator_traits.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/move_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/move_iterator.module.verify.cpp new file mode 100644 index 0000000000000..a73b44a65b3c6 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/move_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/move_iterator.h'}} +#include <__iterator/move_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/next.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/next.module.verify.cpp new file mode 100644 index 0000000000000..4098301762b58 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/next.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/next.h'}} +#include <__iterator/next.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/ostream_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/ostream_iterator.module.verify.cpp new file mode 100644 index 0000000000000..9f522aa8d828a --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/ostream_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/ostream_iterator.h'}} +#include <__iterator/ostream_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/ostreambuf_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/ostreambuf_iterator.module.verify.cpp new file mode 100644 index 0000000000000..ce9c257f54756 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/ostreambuf_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/ostreambuf_iterator.h'}} +#include <__iterator/ostreambuf_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/prev.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/prev.module.verify.cpp new file mode 100644 index 0000000000000..01ef28172d419 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/prev.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/prev.h'}} +#include <__iterator/prev.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/projected.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/projected.module.verify.cpp new file mode 100644 index 0000000000000..69f445fbe6f37 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/projected.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/projected.h'}} +#include <__iterator/projected.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/readable_traits.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/readable_traits.module.verify.cpp new file mode 100644 index 0000000000000..0c4c367a45f15 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/readable_traits.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/readable_traits.h'}} +#include <__iterator/readable_traits.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/reverse_access.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/reverse_access.module.verify.cpp new file mode 100644 index 0000000000000..1dd372bf634ac --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/reverse_access.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/reverse_access.h'}} +#include <__iterator/reverse_access.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/reverse_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/reverse_iterator.module.verify.cpp new file mode 100644 index 0000000000000..eb0517abb03c1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/reverse_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/reverse_iterator.h'}} +#include <__iterator/reverse_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/size.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/size.module.verify.cpp new file mode 100644 index 0000000000000..8d7d496a5906d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/size.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/size.h'}} +#include <__iterator/size.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/iterator/wrap_iter.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/wrap_iter.module.verify.cpp new file mode 100644 index 0000000000000..d151d7264f655 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/iterator/wrap_iter.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__iterator/wrap_iter.h'}} +#include <__iterator/wrap_iter.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/locale.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/locale.module.verify.cpp new file mode 100644 index 0000000000000..b880842c0f44e --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/locale.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__locale'}} +#include <__locale> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/addressof.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/addressof.module.verify.cpp new file mode 100644 index 0000000000000..d596c76608579 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/addressof.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/addressof.h'}} +#include <__memory/addressof.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocation_guard.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocation_guard.module.verify.cpp new file mode 100644 index 0000000000000..715ebff8c04ba --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocation_guard.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/allocation_guard.h'}} +#include <__memory/allocation_guard.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator.module.verify.cpp new file mode 100644 index 0000000000000..9d20a0f61fa99 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/allocator.h'}} +#include <__memory/allocator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator_arg_t.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator_arg_t.module.verify.cpp new file mode 100644 index 0000000000000..d7d5e69938945 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator_arg_t.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/allocator_arg_t.h'}} +#include <__memory/allocator_arg_t.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator_traits.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator_traits.module.verify.cpp new file mode 100644 index 0000000000000..ab0a5758918f0 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/allocator_traits.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/allocator_traits.h'}} +#include <__memory/allocator_traits.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/auto_ptr.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/auto_ptr.module.verify.cpp new file mode 100644 index 0000000000000..b46f06db44c21 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/auto_ptr.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/auto_ptr.h'}} +#include <__memory/auto_ptr.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/compressed_pair.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/compressed_pair.module.verify.cpp new file mode 100644 index 0000000000000..0c54b9158ba8d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/compressed_pair.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/compressed_pair.h'}} +#include <__memory/compressed_pair.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/construct_at.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/construct_at.module.verify.cpp new file mode 100644 index 0000000000000..957636014204f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/construct_at.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/construct_at.h'}} +#include <__memory/construct_at.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/pointer_safety.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/pointer_safety.module.verify.cpp new file mode 100644 index 0000000000000..4edca13465918 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/pointer_safety.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/pointer_safety.h'}} +#include <__memory/pointer_safety.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/pointer_traits.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/pointer_traits.module.verify.cpp new file mode 100644 index 0000000000000..000ef0f3ebbae --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/pointer_traits.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/pointer_traits.h'}} +#include <__memory/pointer_traits.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/raw_storage_iterator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/raw_storage_iterator.module.verify.cpp new file mode 100644 index 0000000000000..6f575bc2e19cc --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/raw_storage_iterator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/raw_storage_iterator.h'}} +#include <__memory/raw_storage_iterator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/shared_ptr.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/shared_ptr.module.verify.cpp new file mode 100644 index 0000000000000..63edce9b9865b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/shared_ptr.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/shared_ptr.h'}} +#include <__memory/shared_ptr.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/temporary_buffer.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/temporary_buffer.module.verify.cpp new file mode 100644 index 0000000000000..e9d343b348662 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/temporary_buffer.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/temporary_buffer.h'}} +#include <__memory/temporary_buffer.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/uninitialized_algorithms.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/uninitialized_algorithms.module.verify.cpp new file mode 100644 index 0000000000000..a20d34e780719 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/uninitialized_algorithms.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/uninitialized_algorithms.h'}} +#include <__memory/uninitialized_algorithms.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/unique_ptr.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/unique_ptr.module.verify.cpp new file mode 100644 index 0000000000000..b9a6bf514cd69 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/unique_ptr.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/unique_ptr.h'}} +#include <__memory/unique_ptr.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/memory/uses_allocator.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/memory/uses_allocator.module.verify.cpp new file mode 100644 index 0000000000000..b7804aa026da6 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/memory/uses_allocator.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__memory/uses_allocator.h'}} +#include <__memory/uses_allocator.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/mutex_base.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/mutex_base.module.verify.cpp new file mode 100644 index 0000000000000..0dd39407f7383 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/mutex_base.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__mutex_base'}} +#include <__mutex_base> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/node_handle.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/node_handle.module.verify.cpp new file mode 100644 index 0000000000000..01b9fa5e809a1 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/node_handle.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__node_handle'}} +#include <__node_handle> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/random/uniform_int_distribution.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/random/uniform_int_distribution.module.verify.cpp new file mode 100644 index 0000000000000..df36fd28cf737 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/random/uniform_int_distribution.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__random/uniform_int_distribution.h'}} +#include <__random/uniform_int_distribution.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/access.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/access.module.verify.cpp new file mode 100644 index 0000000000000..d7ed406863891 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/access.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/access.h'}} +#include <__ranges/access.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/all.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/all.module.verify.cpp new file mode 100644 index 0000000000000..b052cec217858 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/all.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/all.h'}} +#include <__ranges/all.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/concepts.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/concepts.module.verify.cpp new file mode 100644 index 0000000000000..9e2a7eead6696 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/concepts.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/concepts.h'}} +#include <__ranges/concepts.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/copyable_box.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/copyable_box.module.verify.cpp new file mode 100644 index 0000000000000..b1749eb3921ed --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/copyable_box.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/copyable_box.h'}} +#include <__ranges/copyable_box.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/data.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/data.module.verify.cpp new file mode 100644 index 0000000000000..2ffc98b1874a4 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/data.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/data.h'}} +#include <__ranges/data.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/drop_view.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/drop_view.module.verify.cpp new file mode 100644 index 0000000000000..4ae85f5e2b30d --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/drop_view.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/drop_view.h'}} +#include <__ranges/drop_view.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/empty.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/empty.module.verify.cpp new file mode 100644 index 0000000000000..9edeb03fb2be9 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/empty.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/empty.h'}} +#include <__ranges/empty.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/empty_view.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/empty_view.module.verify.cpp new file mode 100644 index 0000000000000..c4c8fce38f727 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/empty_view.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/empty_view.h'}} +#include <__ranges/empty_view.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/enable_borrowed_range.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/enable_borrowed_range.module.verify.cpp new file mode 100644 index 0000000000000..4d83c09288224 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/enable_borrowed_range.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/enable_borrowed_range.h'}} +#include <__ranges/enable_borrowed_range.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/enable_view.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/enable_view.module.verify.cpp new file mode 100644 index 0000000000000..1e0920b7dd12c --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/enable_view.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/enable_view.h'}} +#include <__ranges/enable_view.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/ref_view.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/ref_view.module.verify.cpp new file mode 100644 index 0000000000000..5c7169bdd6890 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/ref_view.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/ref_view.h'}} +#include <__ranges/ref_view.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/size.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/size.module.verify.cpp new file mode 100644 index 0000000000000..39fab7ea0b312 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/size.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/size.h'}} +#include <__ranges/size.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/subrange.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/subrange.module.verify.cpp new file mode 100644 index 0000000000000..53bf897a34bdf --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/subrange.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/subrange.h'}} +#include <__ranges/subrange.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/transform_view.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/transform_view.module.verify.cpp new file mode 100644 index 0000000000000..d014f30e87a6a --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/transform_view.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/transform_view.h'}} +#include <__ranges/transform_view.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/ranges/view_interface.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/view_interface.module.verify.cpp new file mode 100644 index 0000000000000..92cea7c2f7e56 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/ranges/view_interface.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__ranges/view_interface.h'}} +#include <__ranges/view_interface.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/split_buffer.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/split_buffer.module.verify.cpp new file mode 100644 index 0000000000000..b0136c85c8e49 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/split_buffer.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__split_buffer'}} +#include <__split_buffer> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/std_stream.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/std_stream.module.verify.cpp new file mode 100644 index 0000000000000..fe8b52e0962ed --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/std_stream.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__std_stream'}} +#include <__std_stream> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/string.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/string.module.verify.cpp new file mode 100644 index 0000000000000..b368079cf93f8 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/string.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__string'}} +#include <__string> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/tuple.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/tuple.module.verify.cpp new file mode 100644 index 0000000000000..d20d348b04787 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/tuple.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__tuple'}} +#include <__tuple> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/__decay_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/__decay_copy.module.verify.cpp new file mode 100644 index 0000000000000..3398a0b31e4bf --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/__decay_copy.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/__decay_copy.h'}} +#include <__utility/__decay_copy.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/as_const.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/as_const.module.verify.cpp new file mode 100644 index 0000000000000..afa0a116b0886 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/as_const.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/as_const.h'}} +#include <__utility/as_const.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/cmp.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/cmp.module.verify.cpp new file mode 100644 index 0000000000000..0f491b538c223 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/cmp.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/cmp.h'}} +#include <__utility/cmp.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/declval.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/declval.module.verify.cpp new file mode 100644 index 0000000000000..8c9feed63a043 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/declval.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/declval.h'}} +#include <__utility/declval.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/exchange.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/exchange.module.verify.cpp new file mode 100644 index 0000000000000..047b8aeed12b6 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/exchange.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/exchange.h'}} +#include <__utility/exchange.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/forward.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/forward.module.verify.cpp new file mode 100644 index 0000000000000..ed4af64de985e --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/forward.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/forward.h'}} +#include <__utility/forward.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/in_place.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/in_place.module.verify.cpp new file mode 100644 index 0000000000000..ebf2019197e4f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/in_place.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/in_place.h'}} +#include <__utility/in_place.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/integer_sequence.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/integer_sequence.module.verify.cpp new file mode 100644 index 0000000000000..36208e7df162f --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/integer_sequence.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/integer_sequence.h'}} +#include <__utility/integer_sequence.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/move.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/move.module.verify.cpp new file mode 100644 index 0000000000000..e410bdb6da637 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/move.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/move.h'}} +#include <__utility/move.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/pair.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/pair.module.verify.cpp new file mode 100644 index 0000000000000..b847833a3e38c --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/pair.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/pair.h'}} +#include <__utility/pair.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/piecewise_construct.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/piecewise_construct.module.verify.cpp new file mode 100644 index 0000000000000..a804894bde901 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/piecewise_construct.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/piecewise_construct.h'}} +#include <__utility/piecewise_construct.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/rel_ops.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/rel_ops.module.verify.cpp new file mode 100644 index 0000000000000..94b198ea76b7e --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/rel_ops.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/rel_ops.h'}} +#include <__utility/rel_ops.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/swap.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/swap.module.verify.cpp new file mode 100644 index 0000000000000..0b5208f1a17f4 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/swap.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/swap.h'}} +#include <__utility/swap.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/to_underlying.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/to_underlying.module.verify.cpp new file mode 100644 index 0000000000000..553c29c582fa4 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/to_underlying.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__utility/to_underlying.h'}} +#include <__utility/to_underlying.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/variant/monostate.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/variant/monostate.module.verify.cpp new file mode 100644 index 0000000000000..bb20cbbede3e0 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/variant/monostate.module.verify.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__variant/monostate.h'}} +#include <__variant/monostate.h> diff --git a/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp b/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp index 109375b10e6e7..cbc1e26136993 100644 --- a/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp +++ b/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp @@ -14,8 +14,6 @@ // T* polymorphic_allocator::deallocate(T*, size_t size) -// XFAIL: LIBCXX-WINDOWS-FIXME - int AssertCount = 0; #define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (void)::AssertCount++) @@ -38,13 +36,8 @@ int main(int, char**) ex::resource_adaptor r(Alloc{P}); ex::memory_resource & m1 = r; -#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ - std::size_t maxSize = std::numeric_limits::max() - - __STDCPP_DEFAULT_NEW_ALIGNMENT__; -#else std::size_t maxSize = std::numeric_limits::max() - alignof(std::max_align_t); -#endif m1.deallocate(nullptr, maxSize); assert(AssertCount == 0); diff --git a/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_destruction_order.pass.cpp b/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_destruction_order.pass.cpp index 47bc940b27e24..5a8d0590a5ef7 100644 --- a/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_destruction_order.pass.cpp +++ b/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_destruction_order.pass.cpp @@ -9,15 +9,12 @@ // // Test arguments destruction order involving unique_ptr with trivial_abi. -// Note: Unlike other tests in this directory, this is the only test that -// exhibits a difference between the two modes in Microsft ABI. // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI // There were assertion failures in both parse and codegen, which are fixed in clang 11. // UNSUPPORTED: gcc, clang-4, clang-5, clang-6, clang-7, clang-8, clang-9, clang-10 -// XFAIL: LIBCXX-WINDOWS-FIXME #include #include @@ -58,7 +55,12 @@ int main(int, char**) { func(A(shared_buf, &cur_idx), std::unique_ptr(new B(shared_buf, &cur_idx)), C(shared_buf, &cur_idx)); +#if defined(_LIBCPP_ABI_MICROSOFT) + // On Microsoft ABI, the dtor order is always A,B,C (because callee-destroyed) + assert(shared_buf[0] == 'A' && shared_buf[1] == 'B' && shared_buf[2] == 'C'); +#else // With trivial_abi, the std::unique_ptr arg is always destructed first. assert(shared_buf[0] == 'B'); +#endif return 0; } diff --git a/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp b/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp index 8b9e7303b6e8c..ce5adfaa63e7d 100644 --- a/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp +++ b/libcxx/test/libcxx/memory/trivial_abi/unique_ptr_ret.pass.cpp @@ -15,8 +15,6 @@ // There were assertion failures in both parse and codegen, which are fixed in clang 11. // UNSUPPORTED: gcc, clang-4, clang-5, clang-6, clang-7, clang-8, clang-9, clang-10 -// XFAIL: LIBCXX-WINDOWS-FIXME - #include #include @@ -48,9 +46,10 @@ int main(int, char**) { // // With trivial_abi, local_addr is the address of a local variable in // make_val, and hence different from &ret. -#if !defined(__i386__) +#if !defined(__i386__) && !defined(_WIN32) // On X86, structs are never returned in registers. // Thus, unique_ptr will be passed indirectly even if it is trivial. + // On Windows, structs with a destructor are always returned indirectly. assert((void*)&ret != local_addr); #endif diff --git a/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp b/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp index 2da9dd3aea7c4..f556eaf0a0c99 100644 --- a/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp +++ b/libcxx/test/libcxx/memory/trivial_abi/weak_ptr_ret.pass.cpp @@ -15,8 +15,6 @@ // There were assertion failures in both parse and codegen, which are fixed in clang 11. // UNSUPPORTED: gcc, clang-4, clang-5, clang-6, clang-7, clang-8, clang-9, clang-10 -// XFAIL: LIBCXX-WINDOWS-FIXME - #include #include @@ -51,9 +49,10 @@ int main(int, char**) { // // With trivial_abi, local_addr is the address of a local variable in // make_val, and hence different from &ret. -#if !defined(__i386__) && !defined(__arm__) +#if !defined(__i386__) && !defined(__arm__) && !defined(_WIN32) // On X86, structs are never returned in registers. // On ARM32, structs larger than 4 bytes cannot be returned in registers. + // On Windows, structs with a destructor are always returned indirectly. // Thus, weak_ptr will be passed indirectly even if it is trivial. assert((void*)&ret != local_addr); #endif diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp index 91ea226cc40d4..cfa0857838c66 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.copy.pass.cpp @@ -14,7 +14,7 @@ // ADDITIONAL_COMPILE_FLAGS: -Wno-self-assign-overloaded -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp index 7b2e1bd111bd4..7fbb7df714079 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/assign.move.pass.cpp @@ -14,7 +14,7 @@ // ADDITIONAL_COMPILE_FLAGS: -Wno-self-move -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp index 324394f81ae69..e236d59fa8061 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.default.pass.cpp @@ -12,7 +12,7 @@ // ::() -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp index decbf0430af1b..9018e726e50b6 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/ctor.in_place.pass.cpp @@ -13,7 +13,7 @@ // template // explicit ::(in_place_t, Args&& ...args); -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp index 4582effeff0a6..261bef2255cf0 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/deref.pass.cpp @@ -13,7 +13,7 @@ // T& ::operator*() // T const& ::operator*() const -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp index e1bd6287efc93..705309d140f57 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/has_value.pass.cpp @@ -12,7 +12,7 @@ // bool ::__has_value() const -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp index 4b094a703fb63..b8b5537d058ea 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/no_unique_address.pass.cpp @@ -12,7 +12,7 @@ // This test ensures that behaves correctly when it holds an empty type. -#include <__ranges/copyable_box.h> +#include #include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp index 5e933e84d680e..3602a63834b7f 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/properties.compile.pass.cpp @@ -12,7 +12,7 @@ // Test various properties of -#include <__ranges/copyable_box.h> +#include #include diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h index 556023f505363..bcc3493679444 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.copy.wrap/types.h @@ -9,7 +9,7 @@ #ifndef TEST_LIBCXX_RANGES_RANGE_ADAPTORS_RANGE_COPY_WRAP_TYPES_H #define TEST_LIBCXX_RANGES_RANGE_ADAPTORS_RANGE_COPY_WRAP_TYPES_H -#include <__ranges/copyable_box.h> +#include #include #include #include diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp index 12d03545d85c2..25d1411834577 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp @@ -27,10 +27,11 @@ template struct TestFn { void operator()() const { typedef std::atomic A; - A t = T(); - bool b1 = std::atomic_is_lock_free(static_cast(&t)); - volatile A vt = T(); - bool b2 = std::atomic_is_lock_free(static_cast(&vt)); + T t = T(); + A a(t); + bool b1 = std::atomic_is_lock_free(static_cast(&a)); + volatile A va(t); + bool b2 = std::atomic_is_lock_free(static_cast(&va)); assert(b1 == b2); } }; diff --git a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp index 7619c8ce22178..1f0b7395c91b0 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp @@ -27,13 +27,13 @@ struct R { // clang-format off template requires std::relation -[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_relation() { +constexpr bool check_equivalence_relation_subsumes_relation() { return false; } template requires std::equivalence_relation && true -[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_relation() { +constexpr bool check_equivalence_relation_subsumes_relation() { return true; } // clang-format on @@ -48,13 +48,13 @@ static_assert(check_equivalence_relation_subsumes_relation()); // clang-format off template requires std::relation && true -[[nodiscard]] constexpr bool check_relation_subsumes_equivalence_relation() { +constexpr bool check_relation_subsumes_equivalence_relation() { return true; } template requires std::equivalence_relation -[[nodiscard]] constexpr bool check_relation_subsumes_equivalence_relation() { +constexpr bool check_relation_subsumes_equivalence_relation() { return false; } // clang-format on @@ -69,13 +69,13 @@ static_assert(check_relation_subsumes_equivalence_relation()); // clang-format off template requires std::equivalence_relation && std::equivalence_relation -[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_itself() { +constexpr bool check_equivalence_relation_subsumes_itself() { return false; } template requires std::equivalence_relation -[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_itself() { +constexpr bool check_equivalence_relation_subsumes_itself() { return true; } // clang-format on diff --git a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.pass.cpp index 0aad734fa654a..ffec212ebc60f 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.pass.cpp @@ -17,15 +17,15 @@ // clang-format off template requires std::relation -[[nodiscard]] constexpr bool check_subsumption() { return false; } +constexpr bool check_subsumption() { return false; } template requires std::equivalence_relation && true -[[nodiscard]] constexpr bool check_subsumption() { return false; } +constexpr bool check_subsumption() { return false; } template requires std::equivalence_relation && true -[[nodiscard]] constexpr bool check_subsumption() { return true; } +constexpr bool check_subsumption() { return true; } // clang-format on static_assert(check_subsumption()); @@ -46,11 +46,11 @@ static_assert(check_subsumption()); // clang-format off template requires std::relation && true -[[nodiscard]] constexpr bool check_reverse_subsumption() { return true; } +constexpr bool check_reverse_subsumption() { return true; } template requires std::equivalence_relation -[[nodiscard]] constexpr bool check_no_subsumption() { return false; } +constexpr bool check_no_subsumption() { return false; } // clang-format on static_assert(check_reverse_subsumption()); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp index ddded61520b9c..dfd21a4f31333 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.invocable/invocable.compile.pass.cpp @@ -19,7 +19,7 @@ #include template -[[nodiscard]] constexpr bool check_invocable() { +constexpr bool check_invocable() { constexpr bool result = std::invocable; static_assert(std::invocable == result); static_assert(std::invocable == result); @@ -239,7 +239,7 @@ static_assert(!std::invocable); namespace pointer_to_member_functions { // clang-format off template - [[nodiscard]] constexpr bool check_member_is_invocable() + constexpr bool check_member_is_invocable() { constexpr bool result = std::invocable; using uncv_t = std::remove_cvref_t; diff --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp index 5ad5985d8fa45..f2e86e214a353 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp @@ -45,9 +45,9 @@ static_assert(std::predicate); static_assert(!std::predicate); static_assert(!std::predicate); -[[nodiscard]] constexpr bool check_lambda(auto) { return false; } +constexpr bool check_lambda(auto) { return false; } -[[nodiscard]] constexpr bool check_lambda(std::predicate auto) { return true; } +constexpr bool check_lambda(std::predicate auto) { return true; } static_assert(check_lambda([] { return std::true_type(); })); static_assert(check_lambda([]() -> int* { return nullptr; })); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.pass.cpp index 111f89cd16147..5c5941599f0b0 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.pass.cpp @@ -45,9 +45,9 @@ static_assert(std::predicate); static_assert(!std::predicate); static_assert(!std::predicate); -[[nodiscard]] constexpr bool check_lambda(auto) { return false; } +constexpr bool check_lambda(auto) { return false; } -[[nodiscard]] constexpr bool check_lambda(std::predicate auto) { return true; } +constexpr bool check_lambda(std::predicate auto) { return true; } static_assert(check_lambda([] { return std::true_type(); })); static_assert(check_lambda([]() -> int* { return nullptr; })); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp index 3ac652626edf5..da133d58d6b54 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp @@ -14,14 +14,14 @@ #include -[[nodiscard]] constexpr bool check_subsumption(std::regular_invocable auto) { +constexpr bool check_subsumption(std::regular_invocable auto) { return false; } // clang-format off template requires std::predicate && true -[[nodiscard]] constexpr bool check_subsumption(F) +constexpr bool check_subsumption(F) { return true; } diff --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.pass.cpp index 86c79f008ad69..ca451ecd97e06 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.pass.cpp @@ -14,14 +14,14 @@ #include -[[nodiscard]] constexpr bool check_subsumption(std::regular_invocable auto) { +constexpr bool check_subsumption(std::regular_invocable auto) { return false; } // clang-format off template requires std::predicate && true -[[nodiscard]] constexpr bool check_subsumption(F) +constexpr bool check_subsumption(F) { return true; } diff --git a/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.compile.pass.cpp index 7868def3cfe5d..35973a793f4d3 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.regularinvocable/regular_invocable.compile.pass.cpp @@ -19,7 +19,7 @@ #include template -[[nodiscard]] constexpr bool check_invocable() { +constexpr bool check_invocable() { constexpr bool result = std::regular_invocable; static_assert(std::regular_invocable == result); static_assert(std::regular_invocable == result); @@ -265,7 +265,7 @@ static_assert(!std::regular_invocable namespace pointer_to_member_functions { // clang-format off template - [[nodiscard]] constexpr bool check_member_is_invocable() + constexpr bool check_member_is_invocable() { constexpr bool result = std::regular_invocable; using uncv_t = std::remove_cvref_t; diff --git a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp index f7a45f2b07518..4b64e262fd20f 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp @@ -28,13 +28,13 @@ struct R { template requires std::predicate && std::predicate && std::predicate && std::predicate -[[nodiscard]] constexpr bool check_relation_subsumes_predicate() { +constexpr bool check_relation_subsumes_predicate() { return false; } template requires std::relation && true -[[nodiscard]] constexpr bool check_relation_subsumes_predicate() { +constexpr bool check_relation_subsumes_predicate() { return true; } // clang-format on @@ -49,13 +49,13 @@ static_assert(check_relation_subsumes_predicate()); // clang-format off template requires std::relation && std::relation -[[nodiscard]] constexpr bool check_relation_subsumes_itself() { +constexpr bool check_relation_subsumes_itself() { return false; } template requires std::relation -[[nodiscard]] constexpr bool check_relation_subsumes_itself() { +constexpr bool check_relation_subsumes_itself() { return true; } // clang-format on diff --git a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.pass.cpp index 8568bd5f6ecf9..3e2a20534f0ed 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.pass.cpp @@ -18,11 +18,11 @@ template requires std::predicate && std::predicate && std::predicate && std::predicate -[[nodiscard]] constexpr bool check_subsumption() { return false; } +constexpr bool check_subsumption() { return false; } template requires std::relation && true -[[nodiscard]] constexpr bool check_subsumption() { return true; } +constexpr bool check_subsumption() { return true; } // clang-format on static_assert(check_subsumption()); diff --git a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp index 34574f649a3fe..969f25f16e160 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp @@ -27,13 +27,13 @@ struct R { // clang-format off template requires std::relation -[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_relation() { +constexpr bool check_strict_weak_order_subsumes_relation() { return false; } template requires std::strict_weak_order && true -[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_relation() { +constexpr bool check_strict_weak_order_subsumes_relation() { return true; } // clang-format on @@ -48,13 +48,13 @@ static_assert(check_strict_weak_order_subsumes_relation()); // clang-format off template requires std::relation && true -[[nodiscard]] constexpr bool check_relation_subsumes_strict_weak_order() { +constexpr bool check_relation_subsumes_strict_weak_order() { return true; } template requires std::strict_weak_order -[[nodiscard]] constexpr bool check_relation_subsumes_strict_weak_order() { +constexpr bool check_relation_subsumes_strict_weak_order() { return false; } // clang-format on @@ -69,13 +69,13 @@ static_assert(check_relation_subsumes_strict_weak_order()); // clang-format off template requires std::strict_weak_order && std::strict_weak_order -[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_itself() { +constexpr bool check_strict_weak_order_subsumes_itself() { return false; } template requires std::strict_weak_order -[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_itself() { +constexpr bool check_strict_weak_order_subsumes_itself() { return true; } // clang-format on diff --git a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.pass.cpp index 52a19f4f2d8d6..93b1de7255870 100644 --- a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.pass.cpp +++ b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.pass.cpp @@ -17,11 +17,11 @@ // clang-format off template requires std::relation -[[nodiscard]] constexpr bool check_subsumption() { return false; } +constexpr bool check_subsumption() { return false; } template requires std::strict_weak_order && true -[[nodiscard]] constexpr bool check_subsumption() { return true; } +constexpr bool check_subsumption() { return true; } // clang-format on static_assert(check_subsumption()); diff --git a/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp index e0772b51d8187..711072936fece 100644 --- a/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.lang/concept.swappable/swappable_with.compile.pass.cpp @@ -671,7 +671,7 @@ struct Proxy { constexpr Proxy proxy(A& a) { return Proxy{a}; } } // namespace N -[[nodiscard]] constexpr bool CheckRegression() { +constexpr bool CheckRegression() { int i = 1, j = 2; lv_swap(i, j); assert(i == 2 && j == 1); diff --git a/libcxx/test/std/concepts/concepts.lang/concepts.arithmetic/arithmetic.h b/libcxx/test/std/concepts/concepts.lang/concepts.arithmetic/arithmetic.h index bb7016508ccab..b2baabf0abea8 100644 --- a/libcxx/test/std/concepts/concepts.lang/concepts.arithmetic/arithmetic.h +++ b/libcxx/test/std/concepts/concepts.lang/concepts.arithmetic/arithmetic.h @@ -12,20 +12,20 @@ // This overload should never be called. It exists solely to force subsumption. template -[[nodiscard]] constexpr bool CheckSubsumption(I) { +constexpr bool CheckSubsumption(I) { return false; } // clang-format off template requires std::signed_integral && (!std::unsigned_integral) -[[nodiscard]] constexpr bool CheckSubsumption(I) { +constexpr bool CheckSubsumption(I) { return std::is_signed_v; } template requires std::unsigned_integral && (!std::signed_integral) -[[nodiscard]] constexpr bool CheckSubsumption(I) { +constexpr bool CheckSubsumption(I) { return std::is_unsigned_v; } // clang-format on diff --git a/libcxx/test/std/concepts/concepts.object/regular.compile.pass.cpp b/libcxx/test/std/concepts/concepts.object/regular.compile.pass.cpp index a70e265984eb1..e3d17f3dc41f2 100644 --- a/libcxx/test/std/concepts/concepts.object/regular.compile.pass.cpp +++ b/libcxx/test/std/concepts/concepts.object/regular.compile.pass.cpp @@ -161,7 +161,7 @@ static_assert(!std::regular); static_assert(!std::regular); struct is_equality_comparable { - [[nodiscard]] bool operator==(is_equality_comparable const&) const = default; + bool operator==(is_equality_comparable const&) const = default; }; static_assert(std::regular); diff --git a/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp index 0b3204c9d775f..b098f05e2764a 100644 --- a/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp index 9b0b9fc995ca6..9362e25faf40a 100644 --- a/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp index f95952c8bba60..417e19dc0c4dd 100644 --- a/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp index a2150558e0169..caf6ba28ff685 100644 --- a/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp @@ -28,6 +28,7 @@ static_assert(stdr::input_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::bidirectional_range); @@ -37,3 +38,4 @@ static_assert(stdr::input_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/iterator.rel_ops.compile.pass.cpp b/libcxx/test/std/containers/iterator.rel_ops.compile.pass.cpp new file mode 100644 index 0000000000000..46d46b7c3013c --- /dev/null +++ b/libcxx/test/std/containers/iterator.rel_ops.compile.pass.cpp @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcpp-has-no-filesystem-library + +// std::filesystem is unavailable prior to macOS 10.15 +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}} + +// Make sure the various containers' iterators are not broken by the use of `std::rel_ops`. + +#include // for std::rel_ops + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +#if TEST_STD_VER >= 11 +#include "filesystem_include.h" +#endif + +#if TEST_STD_VER >= 17 +#include +#endif + +#if TEST_STD_VER >= 20 +#include +#endif + +using namespace std::rel_ops; + +template +void test_eq(It it, ConstIt cit) { + (void)(it == it); + (void)(it != it); + (void)(it == cit); + (void)(it != cit); + (void)(cit == it); + (void)(cit != it); + (void)(cit == cit); + (void)(cit != cit); +} + +template +void test_lt(It it, ConstIt cit) { + (void)(it < it); + (void)(it <= it); + (void)(it > it); + (void)(it >= it); + (void)(it < cit); + (void)(it <= cit); + (void)(it > cit); + (void)(it >= cit); + (void)(cit < it); + (void)(cit <= it); + (void)(cit > it); + (void)(cit >= it); + (void)(cit < cit); + (void)(cit <= cit); + (void)(cit > cit); + (void)(cit >= cit); + + // Test subtraction too, even though std::rel_ops shouldn't affect it. + + (void)(it - it); + (void)(it - cit); + (void)(cit - it); + (void)(cit - cit); +} + +template +void test_forward() { + // There is no need to distinguish "forward" from "bidirectional." + // libc++ already can't handle `c.rbegin() >= c.rbegin()` in the + // presence of std::rel_ops, and neither can Microsoft nor libstdc++. + + Container c; + typename Container::iterator it = c.begin(); + typename Container::const_iterator cit = c.begin(); + test_eq(it, cit); +} + +template +void test_random_access() { + Container c; + typename Container::iterator it = c.begin(); + typename Container::const_iterator cit = c.begin(); + test_eq(it, cit); + test_lt(it, cit); +} + +template void test_random_access >(); +template void test_random_access >(); +template void test_forward >(); +template void test_forward >(); +template void test_forward >(); +template void test_forward >(); +template void test_forward >(); +template void test_forward >(); +template void test_random_access(); +template void test_forward >(); +template void test_forward >(); +template void test_forward >(); +template void test_forward >(); +template void test_random_access >(); + +#if TEST_STD_VER >= 11 +void test_directory_iterators() { + fs::directory_iterator it; + test_eq(it, it); + + fs::recursive_directory_iterator rdit; + test_eq(rdit, rdit); +} + +template void test_forward(); +#endif + +#if TEST_STD_VER >= 17 +template void test_random_access(); +#endif + +#if TEST_STD_VER >= 20 +void test_span() { + std::span c; + std::span::iterator it = c.begin(); // span has no const_iterator + test_eq(it, it); + test_lt(it, it); +} +#endif diff --git a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp index f70af72c9bd3d..cfe01e7f745ab 100644 --- a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(stdr::random_access_range); static_assert(stdr::contiguous_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(!stdr::view); static_assert(std::same_as, range::const_iterator>); @@ -35,3 +36,4 @@ static_assert(stdr::random_access_range); static_assert(stdr::contiguous_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp index 7b248e9846ed2..df9f6e8cae3f8 100644 --- a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp index af237700f943d..142dc96c0a949 100644 --- a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp index bbe6020603e6c..75c6d34fa7568 100644 --- a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp index 9981d65fd80d0..fb028d0b39319 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp index 117c36b6e1a65..c47413ec262e8 100644 --- a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp index 450705c3417c2..71a72212f59cf 100644 --- a/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp index c98d7b85c4e7b..e18627241df8c 100644 --- a/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp index 64332c422ba73..29789d05210de 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp index 922ca43e1242c..bd48bbab3d21a 100644 --- a/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, range::const_iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(!stdr::bidirectional_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp index 50fdc6a09119f..c850c50976e92 100644 --- a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp @@ -27,6 +27,7 @@ static_assert(stdr::contiguous_range); static_assert(stdr::view && stdr::enable_view); static_assert(stdr::sized_range); static_assert(stdr::borrowed_range); +static_assert(stdr::viewable_range); static_assert(std::same_as, range::iterator>); static_assert(stdr::common_range); @@ -35,3 +36,4 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view && !stdr::enable_view); static_assert(stdr::sized_range); static_assert(stdr::borrowed_range); +static_assert(stdr::viewable_range); diff --git a/libcxx/test/std/containers/views/span.sub/first.fail.cpp b/libcxx/test/std/containers/views/span.sub/first.fail.cpp index b51196cb02789..9f48dc48c7078 100644 --- a/libcxx/test/std/containers/views/span.sub/first.fail.cpp +++ b/libcxx/test/std/containers/views/span.sub/first.fail.cpp @@ -19,6 +19,8 @@ #include +#include + #include "test_macros.h" constexpr int carr[] = {1, 2, 3, 4}; diff --git a/libcxx/test/std/containers/views/span.sub/last.fail.cpp b/libcxx/test/std/containers/views/span.sub/last.fail.cpp index 0ab11792b3b28..0a68dd0c7cade 100644 --- a/libcxx/test/std/containers/views/span.sub/last.fail.cpp +++ b/libcxx/test/std/containers/views/span.sub/last.fail.cpp @@ -19,6 +19,8 @@ #include +#include + #include "test_macros.h" constexpr int carr[] = {1, 2, 3, 4}; diff --git a/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp b/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp index 11b7136e08185..96c403e7bf636 100644 --- a/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp +++ b/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp @@ -21,6 +21,8 @@ #include +#include + #include "test_macros.h" constexpr int carr[] = {1, 2, 3, 4}; diff --git a/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/A.h b/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/A.h index e452ec545742b..13a45ad1b75b8 100644 --- a/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/A.h +++ b/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/A.h @@ -19,6 +19,8 @@ class A A(const A& a) : id_(a.id_) {++count;} ~A() {assert(id_ >= 0); id_ = -1; --count;} + A& operator=(const A& other) { id_ = other.id_; return *this; } + int id() const {return id_;} static int count; diff --git a/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/AB.h b/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/AB.h index 75b4ab88bc18e..fd5c323e3a923 100644 --- a/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/AB.h +++ b/libcxx/test/std/depr/depr.auto.ptr/auto.ptr/AB.h @@ -19,6 +19,8 @@ class A A(const A& a) : id_(a.id_) {++count;} virtual ~A() {assert(id_ >= 0); id_ = -1; --count;} + A& operator=(const A& other) { id_ = other.id_; return *this; } + static int count; }; diff --git a/libcxx/test/std/input.output/file.streams/c.files/cstdio.pass.cpp b/libcxx/test/std/input.output/file.streams/c.files/cstdio.pass.cpp index f388386819528..008862246fcff 100644 --- a/libcxx/test/std/input.output/file.streams/c.files/cstdio.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/c.files/cstdio.pass.cpp @@ -148,7 +148,10 @@ int main(int, char**) #ifndef _LIBCPP_HAS_NO_STDIN static_assert((std::is_same::value), ""); #if TEST_STD_VER <= 11 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" // disable the warning from the C library static_assert((std::is_same::value), ""); +# pragma GCC diagnostic pop #endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp index 80445f28e25cd..ff79c8bd699ec 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp @@ -26,6 +26,7 @@ static_assert(stdr::input_range); static_assert(!stdr::view); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, fs::directory_iterator>); static_assert(stdr::common_range); @@ -33,6 +34,7 @@ static_assert(stdr::input_range); static_assert(!stdr::view); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, fs::recursive_directory_iterator>); static_assert(stdr::common_range); @@ -40,6 +42,7 @@ static_assert(stdr::input_range); static_assert(!stdr::view); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, fs::recursive_directory_iterator>); static_assert(stdr::common_range); @@ -47,3 +50,4 @@ static_assert(stdr::input_range); static_assert(!stdr::view); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp index 47cec87ffac67..b9b70d0725f70 100644 --- a/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp @@ -26,6 +26,7 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, fs::path::const_iterator>); static_assert(stdr::common_range); @@ -34,3 +35,4 @@ static_assert(!stdr::view); static_assert(!stdr::random_access_range); static_assert(!stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp index dc18146a13b83..0d4597259eec5 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.assoc.types/readable.traits/iter_value_t.pass.cpp @@ -20,7 +20,7 @@ #include template -[[nodiscard]] constexpr bool check_iter_value_t() { +constexpr bool check_iter_value_t() { constexpr bool result = std::same_as, Expected>; static_assert(std::same_as, Expected> == result); static_assert(std::same_as, Expected> == result); @@ -50,13 +50,13 @@ static_assert(check_iter_value_t()); // clang-format off template requires requires { typename std::iter_value_t; } -[[nodiscard]] constexpr bool check_no_iter_value_t() { +constexpr bool check_no_iter_value_t() { return false; } // clang-format on template -[[nodiscard]] constexpr bool check_no_iter_value_t() { +constexpr bool check_no_iter_value_t() { return true; } diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/subsumption.compile.pass.cpp index f1b7f304e40df..2fd10c5d0801b 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/subsumption.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/subsumption.compile.pass.cpp @@ -18,12 +18,12 @@ // clang-format off template -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return false; } template -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return true; } // clang-format on diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp index 985a068cef81a..c4280633e7679 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.inc/subsumption.compile.pass.cpp @@ -20,12 +20,12 @@ // clang-format off template requires std::regular -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return false; } template -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return true; } // clang-format on diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp index 608a7d006e54b..92aa5c887d8dc 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp @@ -20,12 +20,12 @@ // clang-format off template requires std::indirectly_readable -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return false; } template -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return true; } // clang-format on diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp index c138fc58b6418..2a2196745c3a8 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/subsumption.compile.pass.cpp @@ -17,12 +17,12 @@ // clang-format off template -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return false; } template -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return true; } // clang-format on diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp index 1734c26878e78..50c18e49a6632 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp @@ -20,7 +20,7 @@ #include "read_write.h" template -[[nodiscard]] constexpr bool check_indirectly_readable() { +constexpr bool check_indirectly_readable() { constexpr bool result = std::indirectly_readable; static_assert(std::indirectly_readable == result); static_assert(std::indirectly_readable == result); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp index bb95595453bc6..32d7b563b14ec 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp @@ -20,12 +20,12 @@ // clang-format off template -[[nodiscard]] constexpr bool check_sentinel_subsumption() { +constexpr bool check_sentinel_subsumption() { return false; } template > -[[nodiscard]] constexpr bool check_subsumption() { +constexpr bool check_subsumption() { return true; } // clang-format on diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp index 8f46ae06878d3..71b1bd274c5b7 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.writable/indirectly_writable.compile.pass.cpp @@ -22,7 +22,7 @@ #include "read_write.h" template -[[nodiscard]] constexpr bool check_indirectly_writable() { +constexpr bool check_indirectly_writable() { constexpr bool result = std::indirectly_writable; static_assert(std::indirectly_writable == result); return result; diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp index cf80bdeb205ba..a4c2bfb43173e 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp @@ -32,10 +32,10 @@ class iterator_wrapper { constexpr explicit iterator_wrapper(I i) noexcept : base_(std::move(i)) {} // `noexcept(false)` is used to check that this operator is called. - [[nodiscard]] constexpr decltype(auto) operator*() const& noexcept(false) { return *base_; } + constexpr decltype(auto) operator*() const& noexcept(false) { return *base_; } // `noexcept` is used to check that this operator is called. - [[nodiscard]] constexpr auto&& operator*() && noexcept { return std::move(*base_); } + constexpr auto&& operator*() && noexcept { return std::move(*base_); } constexpr iterator_wrapper& operator++() noexcept { ++base_; @@ -44,7 +44,7 @@ class iterator_wrapper { constexpr void operator++(int) noexcept { ++base_; } - [[nodiscard]] constexpr bool operator==(iterator_wrapper const& other) const noexcept { return base_ == other.base_; } + constexpr bool operator==(iterator_wrapper const& other) const noexcept { return base_ == other.base_; } private: I base_ = I{}; diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h index 51f35c3234ec1..7c3719aa519e3 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h @@ -20,7 +20,7 @@ class unqualified_lookup_wrapper { constexpr explicit unqualified_lookup_wrapper(I i) noexcept : base_(std::move(i)) {} - [[nodiscard]] constexpr decltype(auto) operator*() const noexcept { return *base_; } + constexpr decltype(auto) operator*() const noexcept { return *base_; } constexpr unqualified_lookup_wrapper& operator++() noexcept { ++base_; @@ -29,13 +29,13 @@ class unqualified_lookup_wrapper { constexpr void operator++(int) noexcept { ++base_; } - [[nodiscard]] constexpr bool operator==(unqualified_lookup_wrapper const& other) const noexcept { + constexpr bool operator==(unqualified_lookup_wrapper const& other) const noexcept { return base_ == other.base_; } // Delegates `std::ranges::iter_move` for the underlying iterator. `noexcept(false)` will be used // to ensure that the unqualified-lookup overload is chosen. - [[nodiscard]] friend constexpr decltype(auto) iter_move(unqualified_lookup_wrapper& i) noexcept(false) { + friend constexpr decltype(auto) iter_move(unqualified_lookup_wrapper& i) noexcept(false) { return std::ranges::iter_move(i.base_); } diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp index 875e20c7fdb0f..00f2b444fc095 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp @@ -18,12 +18,6 @@ // However, support for that was broken prior to Clang 8 and AppleClang 11. // UNSUPPORTED: apple-clang-9, apple-clang-10 // UNSUPPORTED: clang-5, clang-6, clang-7 -// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13}} - -// On Windows libc++ doesn't provide its own definitions for new/delete -// but instead depends on the ones in VCRuntime. However VCRuntime does not -// yet provide aligned new/delete definitions so this test fails to compile/link. -// XFAIL: LIBCXX-WINDOWS-FIXME // Libcxx when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. @@ -48,22 +42,29 @@ void reset() { aligned_delete_called = 0; } -void operator delete(void* p) TEST_NOEXCEPT +alignas(OverAligned) char DummyData[OverAligned * 4]; + +void* operator new [] (std::size_t s, std::align_val_t) +{ + assert(s <= sizeof(DummyData)); + return DummyData; +} + +void operator delete [] (void* p) noexcept { ++unsized_delete_called; std::free(p); } -void operator delete(void* p, const std::nothrow_t&) TEST_NOEXCEPT +void operator delete [] (void* p, const std::nothrow_t&) noexcept { ++unsized_delete_nothrow_called; std::free(p); } -void operator delete [] (void* p, std::align_val_t) TEST_NOEXCEPT +void operator delete [] (void*, std::align_val_t) noexcept { ++aligned_delete_called; - std::free(p); } struct alignas(OverAligned) A {}; diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp index 740ba21a430ff..3be61283094b7 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp @@ -18,12 +18,6 @@ // However, support for that was broken prior to Clang 8 and AppleClang 11. // UNSUPPORTED: apple-clang-9, apple-clang-10 // UNSUPPORTED: clang-5, clang-6, clang-7 -// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13}} - -// On Windows libc++ doesn't provide its own definitions for new/delete -// but instead depends on the ones in VCRuntime. However VCRuntime does not -// yet provide aligned new/delete definitions so this test fails to compile/link. -// XFAIL: LIBCXX-WINDOWS-FIXME // Libcxx when built for z/OS doesn't contain the aligned allocation functions, // nor does the dynamic library shipped with z/OS. @@ -48,22 +42,29 @@ void reset() { aligned_delete_called = 0; } -void operator delete(void* p) TEST_NOEXCEPT +alignas(OverAligned) char DummyData[OverAligned * 4]; + +void* operator new (std::size_t s, std::align_val_t) +{ + assert(s <= sizeof(DummyData)); + return DummyData; +} + +void operator delete(void* p) noexcept { ++unsized_delete_called; std::free(p); } -void operator delete(void* p, const std::nothrow_t&) TEST_NOEXCEPT +void operator delete(void* p, const std::nothrow_t&) noexcept { ++unsized_delete_nothrow_called; std::free(p); } -void operator delete(void* p, std::align_val_t) TEST_NOEXCEPT +void operator delete(void*, std::align_val_t) noexcept { ++aligned_delete_called; - std::free(p); } struct alignas(OverAligned) A {}; diff --git a/libcxx/test/std/ranges/range.adaptors/range.all.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp similarity index 100% rename from libcxx/test/std/ranges/range.adaptors/range.all.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.all/all.pass.cpp diff --git a/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp new file mode 100644 index 0000000000000..5aaf03c5a2b4a --- /dev/null +++ b/libcxx/test/std/ranges/range.adaptors/range.all/all_t.compile.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// using all_t = decltype(views::all(declval())); + +#include + +#include "test_iterators.h" +#include "test_range.h" + +struct View : test_range, std::ranges::view_base { }; +struct Range : test_range { }; +struct BorrowableRange : test_range { }; +template<> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +// When T is a view, returns decay-copy(T) +ASSERT_SAME_TYPE(std::views::all_t, View); +ASSERT_SAME_TYPE(std::views::all_t, View); +ASSERT_SAME_TYPE(std::views::all_t, View); +ASSERT_SAME_TYPE(std::views::all_t, View); + +// Otherwise, when T is a reference to a range, returns ref_view +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::ref_view); +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::ref_view); +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::ref_view); +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::ref_view); + +// Otherwise, returns subrange, sentinel_t> +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::subrange, sentinel>); +ASSERT_SAME_TYPE(std::views::all_t, std::ranges::subrange, sentinel>); diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/dangling.cache.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/dangling.cache.pass.cpp index f5ca14d2e15b2..99e7d6154acb8 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.drop/dangling.cache.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/dangling.cache.pass.cpp @@ -16,6 +16,9 @@ #include +#include +#include + #include "test_macros.h" #include "types.h" diff --git a/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp index 5baf128e8800c..9278bd086093e 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.ref.view.pass.cpp @@ -10,7 +10,9 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// std::ranges::ref_view +// template +// requires is_object_v +// class ref_view; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/bidirectional_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/bidirectional_range.compile.pass.cpp index 56245c9f7dbf9..6c6bb508d395d 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/bidirectional_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/bidirectional_range.compile.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// template +// template // concept bidirectional_range; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/common_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/common_range.compile.pass.cpp index 4c94e212795ed..59ce71e23b8bb 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/common_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/common_range.compile.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: libcpp-no-concepts -// template +// template // concept common_range; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp index 37b1cca464454..d4f024746532e 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// template +// template // concept contiguous_range; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/forward_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/forward_range.compile.pass.cpp index 1a58f1fac4088..d19531cbc63cb 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/forward_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/forward_range.compile.pass.cpp @@ -10,7 +10,8 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// std::ranges::forward_range; +// template +// concept forward_range; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/input_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/input_range.compile.pass.cpp index bdfa24f8c9272..dc9b9bc168023 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/input_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/input_range.compile.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// template +// template // concept input_range; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/random_access_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/random_access_range.compile.pass.cpp index 5a2820734dd9e..f73c750e46c81 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/random_access_range.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/random_access_range.compile.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: gcc-10 -// template +// template // concept random_access_range; #include diff --git a/libcxx/test/std/ranges/range.req/range.refinements/subsumption.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/subsumption.compile.pass.cpp index 0d0b9de44c682..d2f3f3987daf5 100644 --- a/libcxx/test/std/ranges/range.req/range.refinements/subsumption.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.req/range.refinements/subsumption.compile.pass.cpp @@ -26,13 +26,13 @@ struct range { template requires std::input_iterator> -[[nodiscard]] constexpr bool check_input_range_subsumption() { +constexpr bool check_input_range_subsumption() { return false; } template requires true -[[nodiscard]] constexpr bool check_input_range_subsumption() { +constexpr bool check_input_range_subsumption() { return true; } @@ -40,13 +40,13 @@ static_assert(check_input_range_subsumption()); template requires std::forward_iterator> -[[nodiscard]] constexpr bool check_forward_range_subsumption() { +constexpr bool check_forward_range_subsumption() { return false; } template requires true -[[nodiscard]] constexpr bool check_forward_range_subsumption() { +constexpr bool check_forward_range_subsumption() { return true; } @@ -54,13 +54,13 @@ static_assert(check_forward_range_subsumption()); template requires std::bidirectional_iterator> -[[nodiscard]] constexpr bool check_bidirectional_range_subsumption() { +constexpr bool check_bidirectional_range_subsumption() { return false; } template requires true -[[nodiscard]] constexpr bool check_bidirectional_range_subsumption() { +constexpr bool check_bidirectional_range_subsumption() { return true; } diff --git a/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp new file mode 100644 index 0000000000000..3cef347a98c21 --- /dev/null +++ b/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// concept viewable_range; + +#include +#include + +#include "test_iterators.h" +#include "test_range.h" + +// The constraints we have in viewable_range are: +// range +// view> +// constructible_from, T> +// borrowed_range +// +// We test all the relevant combinations of satisfying/not satisfying those constraints. + +// viewable_range is not satisfied for (range=false, view=*, constructible_from=*, borrowed_range=*) +struct T1 { }; +static_assert(!std::ranges::range); + +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); + +// viewable_range is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=true) +struct T2 : test_range, std::ranges::view_base { + T2(T2 const&) = default; +}; +template<> constexpr bool std::ranges::enable_borrowed_range = true; +static_assert(std::ranges::range); +static_assert(std::ranges::view); +static_assert(std::constructible_from); +static_assert(std::ranges::borrowed_range); + +static_assert(std::ranges::viewable_range); +static_assert(std::ranges::viewable_range); +static_assert(std::ranges::viewable_range); +static_assert(std::ranges::viewable_range); + +// viewable_range is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=false) +struct T3 : test_range, std::ranges::view_base { + T3(T3 const&) = default; +}; +template<> constexpr bool std::ranges::enable_borrowed_range = false; +static_assert(std::ranges::range); +static_assert(std::ranges::view); +static_assert(std::constructible_from); +static_assert(!std::ranges::borrowed_range); + +static_assert(std::ranges::viewable_range); +static_assert(std::ranges::viewable_range); +static_assert(std::ranges::viewable_range); +static_assert(std::ranges::viewable_range); + +// viewable_range is not satisfied for (range=true, view=true, constructible_from=false, borrowed_range=true) +struct T4 : test_range, std::ranges::view_base { + T4(T4 const&) = delete; + T4(T4&&) = default; // necessary to model view + T4& operator=(T4&&) = default; // necessary to model view +}; +static_assert(std::ranges::range); +static_assert(std::ranges::view>); +static_assert(!std::constructible_from, T4 const&>); +static_assert(std::ranges::borrowed_range); + +static_assert(!std::ranges::viewable_range); + +// A type that satisfies (range=true, view=true, constructible_from=false, borrowed_range=false) can't be formed + +// viewable_range is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true) +struct T5 : test_range { }; +template<> constexpr bool std::ranges::enable_borrowed_range = true; +static_assert(std::ranges::range); +static_assert(!std::ranges::view); +static_assert(std::constructible_from); +static_assert(std::ranges::borrowed_range); + +static_assert(std::ranges::viewable_range); + +// viewable_range is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false) +struct T6 : test_range { }; +template<> constexpr bool std::ranges::enable_borrowed_range = false; +static_assert(std::ranges::range); +static_assert(!std::ranges::view); +static_assert(std::constructible_from); +static_assert(!std::ranges::borrowed_range); + +static_assert(!std::ranges::viewable_range); + +// viewable_range is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true) +struct T7 : test_range { + T7(T7 const&) = delete; +}; +static_assert(std::ranges::range); +static_assert(!std::ranges::view>); +static_assert(!std::constructible_from, T7&>); +static_assert(std::ranges::borrowed_range); + +static_assert(std::ranges::viewable_range); + +// A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed +struct T8 : test_range { + T8(T8 const&) = delete; +}; +static_assert(std::ranges::range); +static_assert(!std::ranges::view); +static_assert(!std::constructible_from); +static_assert(!std::ranges::borrowed_range); + +static_assert(!std::ranges::viewable_range); + +// Test with a few degenerate types +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); +static_assert(!std::ranges::viewable_range); // unbounded array is not a range +static_assert( std::ranges::viewable_range); diff --git a/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp b/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp new file mode 100644 index 0000000000000..1c7f6e4cf2f27 --- /dev/null +++ b/libcxx/test/std/ranges/range.utility/range.subrange/enable_borrowed_range.compile.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// class std::ranges::subrange; + +#include + +#include "test_iterators.h" + +namespace ranges = std::ranges; + +static_assert(ranges::borrowed_range>); +static_assert(ranges::borrowed_range>); +static_assert(ranges::borrowed_range, ranges::subrange_kind::unsized>>); diff --git a/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp index de92ca20a71c5..741b1ad0bcbb0 100644 --- a/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp @@ -26,6 +26,7 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, std::cmatch::const_iterator>); static_assert(stdr::common_range); @@ -34,3 +35,4 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp index 398549696f532..fb1e6765c900c 100644 --- a/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp @@ -26,6 +26,7 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); static_assert(std::same_as, std::string::const_iterator>); static_assert(stdr::common_range); @@ -34,3 +35,4 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view); static_assert(stdr::sized_range); static_assert(!stdr::borrowed_range); +static_assert(!stdr::viewable_range); diff --git a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp index 78a803e14f59b..860de80eb9811 100644 --- a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp @@ -26,6 +26,7 @@ static_assert(stdr::contiguous_range); static_assert(stdr::view && stdr::enable_view); static_assert(stdr::sized_range); static_assert(stdr::borrowed_range); +static_assert(stdr::viewable_range); static_assert(std::same_as, std::string_view::const_iterator>); static_assert(stdr::common_range); @@ -34,3 +35,4 @@ static_assert(stdr::contiguous_range); static_assert(!stdr::view && !stdr::enable_view); static_assert(stdr::sized_range); static_assert(stdr::borrowed_range); +static_assert(stdr::viewable_range); diff --git a/libcxx/test/std/strings/string.view/string.view.ops/copy.pass.cpp b/libcxx/test/std/strings/string.view/string.view.ops/copy.pass.cpp index a68b016a3f6f8..914bc62b82fe2 100644 --- a/libcxx/test/std/strings/string.view/string.view.ops/copy.pass.cpp +++ b/libcxx/test/std/strings/string.view/string.view.ops/copy.pass.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -// XFAIL: gcc-10, gcc-11 -// GCC's __builtin_strlen isn't constexpr yet +// GCC's __builtin_strlen isn't constexpr yet +// XFAIL: (gcc-10 || gcc-11) && !(c++11 || c++14 || c++17) // UNSUPPORTED: LIBCXX-DEBUG-FIXME // diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp index 4e1ffd5d3e556..b4ee76cf2660c 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_adopt_lock.pass.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "nasty_containers.h" #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp index fac91220eafc9..4e868298337f2 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.cons/mutex_defer_lock.pass.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "nasty_containers.h" #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp index 43a4a633f01aa..57148253a4341 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock.pass.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp index 0327b51d664d3..bb62472a64a5b 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_for.pass.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp index 9f8456199e04f..1a93163658891 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/try_lock_until.pass.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/unlock.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/unlock.pass.cpp index d03fa42ea0eb4..838baab8ddf39 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/unlock.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.locking/unlock.pass.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.obs/op_bool.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.obs/op_bool.pass.cpp index ecc47b888247b..8f15135d81c1c 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.obs/op_bool.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/thread.lock.shared.obs/op_bool.pass.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/types.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/types.pass.cpp index 63f29e83a2100..495360d622ced 100644 --- a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/types.pass.cpp +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/types.pass.cpp @@ -21,6 +21,7 @@ // }; #include +#include #include #include "test_macros.h" diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp index 184b931dff84d..2286f74eda72f 100644 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.member/join.pass.cpp @@ -19,10 +19,13 @@ #include #include #include +#include #include "make_test_thread.h" #include "test_macros.h" +std::atomic_bool done(false); + class G { int alive_; @@ -45,7 +48,7 @@ class G int G::n_alive = 0; bool G::op_run = false; -void foo() {} +void foo() { done = true; } int main(int, char**) { @@ -72,6 +75,11 @@ int main(int, char**) assert(false); } catch (std::system_error const&) { } + // Wait to make sure that the detached thread has started up. + // Without this, we could exit main and start destructing global + // resources that are needed when the thread starts up, while the + // detached thread would start up only later. + while (!done) {} } #endif diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp index a591b5f62e69b..708370a47b616 100644 --- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp @@ -48,7 +48,7 @@ class X int i_; public: constexpr explicit X(int i) : i_(i) {} - constexpr X(X&& x) : i_(std::exchange(x.i_, 0)) {} + constexpr X(X&& x) : i_(x.i_) { x.i_ = 0; } TEST_CONSTEXPR_CXX20 ~X() {i_ = 0;} friend constexpr bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} }; diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/auto_pointer.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/auto_pointer.pass.cpp index a2e3c4eab3652..4d13ba9c52018 100644 --- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/auto_pointer.pass.cpp +++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/auto_pointer.pass.cpp @@ -36,7 +36,7 @@ int A::count = 0; struct B : public A { static int count; B() { ++count; } - B(const B&) { ++count; } + B(const B& b) : A(b) { ++count; } virtual ~B() { --count; } }; diff --git a/libcxx/test/support/atomic_helpers.h b/libcxx/test/support/atomic_helpers.h index a5c17035d0d90..3a71c09e48e0d 100644 --- a/libcxx/test/support/atomic_helpers.h +++ b/libcxx/test/support/atomic_helpers.h @@ -77,7 +77,7 @@ struct TestEachIntegralType { TestFunctor()(); TestFunctor()(); TestFunctor()(); - TestFunctor(); + TestFunctor()(); #if TEST_STD_VER > 17 && defined(__cpp_char8_t) TestFunctor()(); #endif diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h index 1d448da5407e1..581adb4f86946 100644 --- a/libcxx/test/support/compare_types.h +++ b/libcxx/test/support/compare_types.h @@ -261,62 +261,62 @@ struct totally_ordered_with_others { }; struct no_lt_not_totally_ordered_with { - [[nodiscard]] bool operator==(no_lt_not_totally_ordered_with const&) const = default; - [[nodiscard]] auto operator<=>(no_lt_not_totally_ordered_with const&) const = default; + bool operator==(no_lt_not_totally_ordered_with const&) const = default; + auto operator<=>(no_lt_not_totally_ordered_with const&) const = default; operator totally_ordered_with_others() const noexcept; - [[nodiscard]] bool operator==(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator<=>(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator<(totally_ordered_with_others const&) const; + bool operator==(totally_ordered_with_others const&) const; + auto operator<=>(totally_ordered_with_others const&) const; + auto operator<(totally_ordered_with_others const&) const; }; struct no_gt_not_totally_ordered_with { - [[nodiscard]] bool operator==(no_gt_not_totally_ordered_with const&) const = default; - [[nodiscard]] auto operator<=>(no_gt_not_totally_ordered_with const&) const = default; + bool operator==(no_gt_not_totally_ordered_with const&) const = default; + auto operator<=>(no_gt_not_totally_ordered_with const&) const = default; operator totally_ordered_with_others() const noexcept; - [[nodiscard]] bool operator==(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator<=>(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator>(totally_ordered_with_others const&) const; + bool operator==(totally_ordered_with_others const&) const; + auto operator<=>(totally_ordered_with_others const&) const; + auto operator>(totally_ordered_with_others const&) const; }; struct no_le_not_totally_ordered_with { - [[nodiscard]] bool operator==(no_le_not_totally_ordered_with const&) const = default; - [[nodiscard]] auto operator<=>(no_le_not_totally_ordered_with const&) const = default; + bool operator==(no_le_not_totally_ordered_with const&) const = default; + auto operator<=>(no_le_not_totally_ordered_with const&) const = default; operator totally_ordered_with_others() const noexcept; - [[nodiscard]] bool operator==(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator<=>(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator<=(totally_ordered_with_others const&) const; + bool operator==(totally_ordered_with_others const&) const; + auto operator<=>(totally_ordered_with_others const&) const; + auto operator<=(totally_ordered_with_others const&) const; }; struct no_ge_not_totally_ordered_with { - [[nodiscard]] bool operator==(no_ge_not_totally_ordered_with const&) const = default; - [[nodiscard]] auto operator<=>(no_ge_not_totally_ordered_with const&) const = default; + bool operator==(no_ge_not_totally_ordered_with const&) const = default; + auto operator<=>(no_ge_not_totally_ordered_with const&) const = default; operator totally_ordered_with_others() const noexcept; - [[nodiscard]] bool operator==(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator<=>(totally_ordered_with_others const&) const; - [[nodiscard]] auto operator>=(totally_ordered_with_others const&) const; + bool operator==(totally_ordered_with_others const&) const; + auto operator<=>(totally_ordered_with_others const&) const; + auto operator>=(totally_ordered_with_others const&) const; }; struct partial_ordering_totally_ordered_with { - [[nodiscard]] auto operator<=>(partial_ordering_totally_ordered_with const&) const noexcept = default; - [[nodiscard]] std::partial_ordering operator<=>(totally_ordered_with_others const&) const noexcept; + auto operator<=>(partial_ordering_totally_ordered_with const&) const noexcept = default; + std::partial_ordering operator<=>(totally_ordered_with_others const&) const noexcept; operator totally_ordered_with_others() const; }; struct weak_ordering_totally_ordered_with { - [[nodiscard]] auto operator<=>(weak_ordering_totally_ordered_with const&) const noexcept = default; - [[nodiscard]] std::weak_ordering operator<=>(totally_ordered_with_others const&) const noexcept; + auto operator<=>(weak_ordering_totally_ordered_with const&) const noexcept = default; + std::weak_ordering operator<=>(totally_ordered_with_others const&) const noexcept; operator totally_ordered_with_others() const; }; struct strong_ordering_totally_ordered_with { - [[nodiscard]] auto operator<=>(strong_ordering_totally_ordered_with const&) const noexcept = default; - [[nodiscard]] std::strong_ordering operator<=>(totally_ordered_with_others const&) const noexcept; + auto operator<=>(strong_ordering_totally_ordered_with const&) const noexcept = default; + std::strong_ordering operator<=>(totally_ordered_with_others const&) const noexcept; operator totally_ordered_with_others() const; }; diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h index 2ce548279ada7..bb1671b909352 100644 --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -730,9 +730,9 @@ class stride_counting_iterator { constexpr explicit stride_counting_iterator(I current) : base_(std::move(current)) {} - [[nodiscard]] constexpr I const& base() const& { return base_; } + constexpr I const& base() const& { return base_; } - [[nodiscard]] constexpr I base() && { return std::move(base_); } + constexpr I base() && { return std::move(base_); } constexpr difference_type stride_count() const { return stride_count_; } diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h index 3d8f933ee8b6f..96c6965ec65d4 100644 --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -139,7 +139,7 @@ # define TEST_NOEXCEPT_COND(...) #endif -#if TEST_STD_VER >= 17 +#if TEST_STD_VER >= 11 # define TEST_THROW_SPEC(...) #else # define TEST_THROW_SPEC(...) throw(__VA_ARGS__) diff --git a/libcxx/utils/CMakeLists.txt b/libcxx/utils/CMakeLists.txt new file mode 100644 index 0000000000000..638ea7aa12924 --- /dev/null +++ b/libcxx/utils/CMakeLists.txt @@ -0,0 +1,23 @@ + +add_custom_target(libcxx-generate-public-header-transitive-inclusion-tests + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_header_inclusion_tests.py" + COMMENT "Generate tests checking for mandated transitive includes in public headers.") + +add_custom_target(libcxx-generate-public-header-tests + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_header_tests.py" + COMMENT "Generate tests for including public headers.") + +add_custom_target(libcxx-generate-feature-test-macros + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_feature_test_macro_components.py" + COMMENT "Generate the header and tests for feature test macros.") + +add_custom_target(libcxx-generate-private-header-tests + COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_private_header_tests.py" + COMMENT "Generates tests for ensuring detail headers are private") + +add_custom_target(libcxx-generate-files + DEPENDS libcxx-generate-public-header-transitive-inclusion-tests + libcxx-generate-public-header-tests + libcxx-generate-feature-test-macros + libcxx-generate-private-header-tests + COMMENT "Create all the auto-generated files in libc++ and its tests.") diff --git a/libcxx/utils/ci/Dockerfile b/libcxx/utils/ci/Dockerfile index aeb1d2f24952e..276e5a5cf275d 100644 --- a/libcxx/utils/ci/Dockerfile +++ b/libcxx/utils/ci/Dockerfile @@ -47,15 +47,9 @@ RUN bash /tmp/llvm.sh $(($LLVM_LATEST_VERSION - 1)) # previous release RUN bash /tmp/llvm.sh $LLVM_LATEST_VERSION # latest release RUN bash /tmp/llvm.sh $(($LLVM_LATEST_VERSION + 1)) # current ToT -# Make the latest Clang the "default" compiler on the system -RUN ln -fs /usr/bin/clang++-$LLVM_LATEST_VERSION /usr/bin/c++ && [ -e $(readlink /usr/bin/c++) ] -RUN ln -fs /usr/bin/clang-$LLVM_LATEST_VERSION /usr/bin/cc && [ -e $(readlink /usr/bin/cc) ] - -# Temporarily keep the clang++ and clang++-tot symlinks around for backwards compatibility with builders -RUN ln -s /usr/bin/clang++-$LLVM_LATEST_VERSION /usr/bin/clang++ && [ -e $(readlink /usr/bin/clang++) ] -RUN ln -s /usr/bin/clang-$LLVM_LATEST_VERSION /usr/bin/clang && [ -e $(readlink /usr/bin/clang) ] -RUN ln -s /usr/bin/clang++-$(($LLVM_LATEST_VERSION + 1)) /usr/bin/clang++-tot && [ -e $(readlink /usr/bin/clang++-tot) ] -RUN ln -s /usr/bin/clang-$(($LLVM_LATEST_VERSION + 1)) /usr/bin/clang-tot && [ -e $(readlink /usr/bin/clang-tot) ] +# Make the ToT Clang the "default" compiler on the system +RUN ln -fs /usr/bin/clang++-$(($LLVM_LATEST_VERSION + 1)) /usr/bin/c++ && [ -e $(readlink /usr/bin/c++) ] +RUN ln -fs /usr/bin/clang-$(($LLVM_LATEST_VERSION + 1)) /usr/bin/cc && [ -e $(readlink /usr/bin/cc) ] # Install clang-format RUN apt-get install -y clang-format-$LLVM_LATEST_VERSION @@ -67,9 +61,6 @@ ENV GCC_LATEST_VERSION=11 RUN add-apt-repository ppa:ubuntu-toolchain-r/test RUN apt-get update && apt install -y gcc-$GCC_LATEST_VERSION g++-$GCC_LATEST_VERSION -# Temporarily keep installing GCC 10 for backwards compatibility with build bots -RUN apt-get update && apt install -y gcc-10 g++-10 - # Install a recent CMake RUN wget https://github.com/Kitware/CMake/releases/download/v3.18.2/cmake-3.18.2-Linux-x86_64.sh -O /tmp/install-cmake.sh RUN bash /tmp/install-cmake.sh --prefix=/usr --exclude-subdir --skip-license @@ -87,6 +78,7 @@ WORKDIR /home/libcxx-builder # for the Buildkite agent to be installed in a path where we can find it. RUN bash -c "$(curl -sL https://raw.githubusercontent.com/buildkite/agent/master/install.sh)" ENV PATH="${PATH}:/home/libcxx-builder/.buildkite-agent/bin" +RUN echo "tags=\"queue=libcxx-builders,arch=$(uname -m),os=linux\"" >> "/home/libcxx-builder/.buildkite-agent/buildkite-agent.cfg" # By default, start the Buildkite agent (this requires a token). -CMD buildkite-agent start --tags "queue=libcxx-builders" +CMD buildkite-agent start diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml index 095bfaa72bae6..b1ac2007f0c7e 100644 --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -28,6 +28,7 @@ steps: - "**/clang-format.patch" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -41,6 +42,7 @@ steps: - "**/generated_output.patch" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -60,6 +62,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -72,6 +75,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -84,6 +88,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -96,6 +101,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -107,6 +113,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -119,17 +126,19 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost limit: 2 - - label: "GCC 11" + - label: "GCC 11 / C++latest" command: "libcxx/utils/ci/run-buildbot generic-gcc" artifact_paths: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -140,12 +149,25 @@ steps: # - wait + - label: "GCC 11 / C++11" + command: "libcxx/utils/ci/run-buildbot generic-gcc-cxx11" + artifact_paths: + - "**/test-results.xml" + agents: + queue: "libcxx-builders" + os: "linux" + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + - label: "Clang 11" command: "libcxx/utils/ci/run-buildbot generic-clang-11" artifact_paths: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -157,6 +179,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -168,6 +191,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -179,6 +203,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -190,6 +215,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -202,6 +228,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -214,6 +241,7 @@ steps: - "**/*.abilist" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -225,6 +253,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -236,6 +265,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -247,6 +277,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -258,6 +289,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -269,6 +301,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -280,6 +313,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -291,6 +325,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -302,6 +337,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -313,6 +349,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -324,6 +361,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -335,6 +373,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -346,6 +385,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -357,6 +397,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -368,6 +409,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -379,6 +421,7 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost @@ -412,18 +455,35 @@ steps: - "**/test-results.xml" agents: queue: "libcxx-builders" + os: "linux" retry: automatic: - exit_status: -1 # Agent was lost limit: 2 - - label: "MacOS C++20" + - label: "MacOS x86_64" command: "libcxx/utils/ci/run-buildbot generic-cxx20" artifact_paths: - "**/test-results.xml" - "**/*.abilist" agents: - queue: "libcxx-builders-macos" + queue: "libcxx-builders" + os: "macos" + arch: "x86_64" + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + + - label: "MacOS arm64" + command: "libcxx/utils/ci/run-buildbot generic-cxx20" + artifact_paths: + - "**/test-results.xml" + - "**/*.abilist" + agents: + queue: "libcxx-builders" + os: "macos" + arch: "arm64" retry: automatic: - exit_status: -1 # Agent was lost @@ -435,7 +495,8 @@ steps: artifact_paths: - "**/test-results.xml" agents: - queue: "libcxx-builders-macos" + queue: "libcxx-builders" + os: "macos" retry: automatic: - exit_status: -1 # Agent was lost @@ -446,7 +507,8 @@ steps: artifact_paths: - "**/test-results.xml" agents: - queue: "libcxx-builders-macos" + queue: "libcxx-builders" + os: "macos" retry: automatic: - exit_status: -1 # Agent was lost @@ -458,7 +520,9 @@ steps: artifact_paths: - "**/test-results.xml" agents: - queue: "libcxx-builders-macos10.15" # TODO: For now, we're running the back-deployment tests for 10.9 on 10.15, because we don't have proper 10.9 machines + queue: "libcxx-builders" + os: "macos10.15" # TODO: For now, we're running the back-deployment tests for 10.9 on 10.15, because we don't have proper 10.9 machines + arch: "x86_64" retry: automatic: - exit_status: -1 # Agent was lost @@ -469,7 +533,9 @@ steps: artifact_paths: - "**/test-results.xml" agents: - queue: "libcxx-builders-macos10.15" + queue: "libcxx-builders" + os: "macos10.15" + arch: "x86_64" retry: automatic: - exit_status: -1 # Agent was lost diff --git a/libcxx/utils/ci/macos-ci-setup b/libcxx/utils/ci/macos-ci-setup index f9bf4888e2d15..eb16c47573bf2 100755 --- a/libcxx/utils/ci/macos-ci-setup +++ b/libcxx/utils/ci/macos-ci-setup @@ -3,24 +3,98 @@ # This simple script can be used to set up a CI node running MacOS. # An additional requirement that is *not* handled by this script is the # installation of Xcode, which requires manual intervention. +# +# This script should first be run from an administrator account to install +# the dependencies necessary for running CI. It can be run without having +# to clone the LLVM repository with: +# +# $ /bin/bash -c "$(curl -fsSl https://raw.githubusercontent.com/llvm/llvm-project/main/libcxx/utils/ci/macos-ci-setup)" +# +# Once the necessary dependencies have been installed, you can switch +# to a non-administrator account and run the script again, passing the +# --setup-launchd argument. That will install a Launchd agent to run the +# BuildKite agent whenever the current user is logged in. You should enable +# automatic login for that user, so that if the CI node goes down, the user +# is logged back in automatically when the node goes up again, and the +# BuildKite agent starts automatically. +# +# Alternatively, you can simply run the BuildKite agent by hand using: +# +# $ caffeinate -s buildkite-agent start --build-path /tmp/buildkite-builds -if [[ -z "${BUILDKITE_AGENT_TOKEN}" ]]; then - echo "The BUILDKITE_AGENT_TOKEN environment variable must be set to a BuildKite Agent token when calling this script." - exit 1 -fi +set -e + +# Install a Launchd agent that will automatically start the BuildKite agent at login +if [[ ${1} == "--setup-launchd" ]]; then + HOMEBREW_PREFIX="$(brew --prefix)" + mkdir -p ~/Library/LaunchAgents + cat < ~/Library/LaunchAgents/libcxx.buildkite-agent.plist + + + + + Label + libcxx.buildkite-agent + + ProgramArguments + + ${HOMEBREW_PREFIX}/bin/buildkite-agent + start + --build-path + ${HOME}/libcxx.buildkite-agent/builds + + + EnvironmentVariables + + PATH + ${HOMEBREW_PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin + + + RunAtLoad + + + KeepAlive + + SuccessfulExit + + -# Install Homebrew -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + ProcessType + Interactive -# Install the required tools to run CI -brew install sphinx-doc python3 ninja cmake clang-format buildkite/buildkite/buildkite-agent + ThrottleInterval + 30 -CFG_DIR="$(brew --prefix)/etc/buildkite-agent" + StandardOutPath + ${HOME}/libcxx.buildkite-agent/stdout.log -version="$(sw_vers -productVersion | sed -E 's/([0-9]+).([0-9]+).[0-9]+/\1.\2/')" + StandardErrorPath + ${HOME}/libcxx.buildkite-agent/stderr.log + + +EOF -# Setup the tags of the agent -echo "tags=\"queue=libcxx-builders-macos,queue=libcxx-builders-macos${version}\"" >> "${CFG_DIR}/buildkite-agent.cfg" + echo "Starting BuildKite agent" + launchctl load ~/Library/LaunchAgents/libcxx.buildkite-agent.plist -# Setup the BuildKite Agent token -sed -i '' "s/xxx/${BUILDKITE_AGENT_TOKEN}/g" "${CFG_DIR}/buildkite-agent.cfg" +else + echo "Installing CI dependencies for macOS" + + if [[ -z "${BUILDKITE_AGENT_TOKEN}" ]]; then + echo "The BUILDKITE_AGENT_TOKEN environment variable must be set to a BuildKite Agent token when calling this script." + exit 1 + fi + + # Install Homebrew + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + HOMEBREW_PREFIX="$(brew --prefix)" + + # Install the required tools to run CI + brew install sphinx-doc python3 ninja cmake clang-format buildkite/buildkite/buildkite-agent + + # Setup BuildKite Agent config + version="$(sw_vers -productVersion | sed -E 's/([0-9]+).([0-9]+).[0-9]+/\1.\2/')" + arch="$(uname -m)" + sed -i '' "s/token=xxx/token=${BUILDKITE_AGENT_TOKEN}/g" "${HOMEBREW_PREFIX}/etc/buildkite-agent/buildkite-agent.cfg" + echo "tags=\"queue=libcxx-builders,arch=${arch},os=macos,os=macos${version}\"" >> "${HOMEBREW_PREFIX}/etc/buildkite-agent/buildkite-agent.cfg" +fi diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot index 15488e942527c..e37f604c4d8b7 100755 --- a/libcxx/utils/ci/run-buildbot +++ b/libcxx/utils/ci/run-buildbot @@ -164,19 +164,19 @@ check-generated-output) # `! foo` doesn't work properly with `set -e`, use `! foo || false` instead. # https://stackoverflow.com/questions/57681955/set-e-does-not-respect-logical-not clean - echo "+++ Checking the output of the generator scripts" - mkdir -p ${BUILD_DIR} - # Reject patches that don't update the generated output correctly. - python3 libcxx/utils/generate_feature_test_macro_components.py - python3 libcxx/utils/generate_header_inclusion_tests.py - python3 libcxx/utils/generate_header_tests.py + generate-cmake + + # Reject patches that forgot to re-run the generator scripts. + echo "+++ Making sure the generator scripts were run" + ${NINJA} -vC "${BUILD_DIR}" libcxx-generate-files git diff | tee ${BUILD_DIR}/generated_output.patch - # Check if the diffs are empty, fail otherwise. ! grep -q '^--- a' ${BUILD_DIR}/generated_output.patch || false + # Reject patches that introduce non-ASCII characters or hard tabs. # Depends on LC_COLLATE set at the top of this script. ! grep -rn '[^ -~]' libcxx/include/ || false - # Check that no dependency cycles have been introduced. + + # Reject patches that introduce dependency cycles in the headers. python3 libcxx/utils/graph_header_deps.py >/dev/null ;; generic-cxx03) @@ -278,6 +278,13 @@ generic-gcc) generate-cmake check-cxx-cxxabi ;; +generic-gcc-cxx11) + export CC=gcc-11 + export CXX=g++-11 + clean + generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx11.cmake" + check-cxx-cxxabi +;; generic-asan) clean generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-asan.cmake" @@ -480,8 +487,8 @@ aarch64-noexceptions) export CXX=/usr/local/bin/c++ clean generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/AArch64.cmake" \ - -DLIBCXX_ENABLE_EXCEPTIONS=OFF \ - -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF + -DLIBCXX_ENABLE_EXCEPTIONS=OFF \ + -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF check-cxx-cxxabi ;; # Aka Armv8 32 bit diff --git a/libcxx/utils/generate_private_header_tests.py b/libcxx/utils/generate_private_header_tests.py new file mode 100755 index 0000000000000..10acb9214961c --- /dev/null +++ b/libcxx/utils/generate_private_header_tests.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +import os +import re +import shutil +from pathlib import Path + + +def get_libcxx_paths(): + utils_path = os.path.dirname(os.path.abspath(__file__)) + script_name = os.path.basename(__file__) + assert os.path.exists(utils_path) + src_root = os.path.dirname(utils_path) + include_path = os.path.join(src_root, 'include') + assert os.path.exists(include_path) + docs_path = os.path.join(src_root, 'docs') + assert os.path.exists(docs_path) + detail_header_test_root = os.path.join(src_root, 'test', 'libcxx', + 'diagnostics', 'detail.headers') + assert os.path.exists(detail_header_test_root) + shutil.rmtree(detail_header_test_root) + Path(f'{detail_header_test_root}').mkdir() + assert os.path.exists(detail_header_test_root) + return script_name, src_root, include_path, docs_path, detail_header_test_root + + +script_name, source_root, include_path, docs_path, detail_header_test_root = get_libcxx_paths( +) + + +def generate_test(header): + return f'''// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by '{script_name}' +// and should not be edited manually. + +// expected-error@*:* {{{{use of private header from outside its module: '{header}'}}}} +#include <{header}> +''' + + +def relative_path(path): + return path.as_posix()[len(include_path + '/'):] + + +def is_still_public(path): + rp = relative_path(path) + return not rp.startswith('__support') and rp not in [ + "__bsd_locale_defaults.h", "__bsd_locale_fallbacks.h", "__config", + "__config_site.in", "__debug", "__hash_table", "__functional_base", + "__libcpp_version", "__nullptr", "__threading_support", "__tree", + "__undef_macros" + ] + + +def main(): + paths = [ + relative_path(p) for p in Path(include_path).rglob('*') + if relative_path(p).startswith('__') and not p.is_dir() + and is_still_public(p) + ] + for path in paths: + path_with_subdir = re.search(r'__(\w+)/(\w+)', path) + directory = path_with_subdir.group(1) + '/' if path_with_subdir else "" + file = path_with_subdir.group(2) if path_with_subdir else path[2:] + path_to_write = f'{detail_header_test_root}/{directory}{file}.module.verify.cpp' + Path(f'{detail_header_test_root}/{directory}').mkdir(exist_ok=True) + assert os.path.exists(f'{detail_header_test_root}/{directory}') + with open(path_to_write, 'w') as f: + f.write(generate_test(path)) + + +if __name__ == '__main__': + main() diff --git a/libcxx/utils/google-benchmark/.clang-format b/libcxx/utils/google-benchmark/.clang-format index 06ea346a1067b..e7d00feaa08a9 100644 --- a/libcxx/utils/google-benchmark/.clang-format +++ b/libcxx/utils/google-benchmark/.clang-format @@ -1,4 +1,5 @@ --- Language: Cpp BasedOnStyle: Google +PointerAlignment: Left ... diff --git a/libcxx/utils/google-benchmark/.github/.libcxx-setup.sh b/libcxx/utils/google-benchmark/.github/.libcxx-setup.sh new file mode 100755 index 0000000000000..56008403ae921 --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/.libcxx-setup.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Checkout LLVM sources +git clone --depth=1 https://github.com/llvm/llvm-project.git llvm-project + +# Setup libc++ options +if [ -z "$BUILD_32_BITS" ]; then + export BUILD_32_BITS=OFF && echo disabling 32 bit build +fi + +# Build and install libc++ (Use unstable ABI for better sanitizer coverage) +cd ./llvm-project +cmake -DCMAKE_C_COMPILER=${C_COMPILER} \ + -DCMAKE_CXX_COMPILER=${COMPILER} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DLIBCXX_ABI_UNSTABLE=OFF \ + -DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \ + -DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \ + -DLLVM_ENABLE_PROJECTS='libcxx;libcxxabi' \ + -S llvm -B llvm-build -G "Unix Makefiles" +make -C llvm-build -j3 cxx cxxabi +sudo make -C llvm-build install-cxx install-cxxabi +cd .. diff --git a/libcxx/utils/google-benchmark/.github/ISSUE_TEMPLATE/bug_report.md b/libcxx/utils/google-benchmark/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..6c2ced9b2ec5b --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**System** +Which OS, compiler, and compiler version are you using: + - OS: + - Compiler and version: + +**To reproduce** +Steps to reproduce the behavior: +1. sync to commit ... +2. cmake/bazel... +3. make ... +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. diff --git a/libcxx/utils/google-benchmark/.github/ISSUE_TEMPLATE/feature_request.md b/libcxx/utils/google-benchmark/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..9e8ab6a673f6b --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[FR]" +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/libcxx/utils/google-benchmark/.github/workflows/bazel.yml b/libcxx/utils/google-benchmark/.github/workflows/bazel.yml new file mode 100644 index 0000000000000..a53661b2f9b11 --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/workflows/bazel.yml @@ -0,0 +1,30 @@ +name: bazel + +on: + push: {} + pull_request: {} + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + + - name: mount bazel cache + uses: actions/cache@v2.0.0 + env: + cache-name: bazel-cache + with: + path: "~/.cache/bazel" + key: ${{ env.cache-name }}-${{ runner.os }}-${{ github.ref }} + restore-keys: | + ${{ env.cache-name }}-${{ runner.os }}-main + + - name: build + run: | + bazel build //:benchmark //:benchmark_main //test/... + + - name: test + run: | + bazel test --test_output=all //test/... diff --git a/libcxx/utils/google-benchmark/.github/workflows/build-and-test-perfcounters.yml b/libcxx/utils/google-benchmark/.github/workflows/build-and-test-perfcounters.yml new file mode 100644 index 0000000000000..b2b541919766f --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/workflows/build-and-test-perfcounters.yml @@ -0,0 +1,44 @@ +name: build-and-test-perfcounters + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + job: + # TODO(dominic): Extend this to include compiler and set through env: CC/CXX. + name: ${{ matrix.os }}.${{ matrix.build_type }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, ubuntu-16.04, ubuntu-20.04] + build_type: ['Release', 'Debug'] + steps: + - uses: actions/checkout@v2 + + - name: install libpfm + run: sudo apt install libpfm4-dev + + - name: create build environment + run: cmake -E make_directory ${{ runner.workspace }}/_build + + - name: configure cmake + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: cmake -DBENCHMARK_ENABLE_LIBPFM=1 -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + + - name: build + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: cmake --build . --config ${{ matrix.build_type }} + + # Skip testing, for now. It seems perf_event_open does not succeed on the + # hosting machine, very likely a permissions issue. + # TODO(mtrofin): Enable test. + # - name: test + # shell: bash + # working-directory: ${{ runner.workspace }}/_build + # run: sudo ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure diff --git a/libcxx/utils/google-benchmark/.github/workflows/build-and-test.yml b/libcxx/utils/google-benchmark/.github/workflows/build-and-test.yml new file mode 100644 index 0000000000000..9e5be3b1dc172 --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/workflows/build-and-test.yml @@ -0,0 +1,110 @@ +name: build-and-test + +on: + push: {} + pull_request: {} + +jobs: + # TODO: add 32-bit builds (g++ and clang++) for ubuntu + # (requires g++-multilib and libc6:i386) + # TODO: add coverage build (requires lcov) + # TODO: add clang + libc++ builds for ubuntu + # TODO: add clang + ubsan/asan/msan + libc++ builds for ubuntu + job: + name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.compiler }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, ubuntu-16.04, ubuntu-20.04, macos-latest] + build_type: ['Release', 'Debug'] + compiler: [g++, clang++] + include: + - displayTargetName: windows-latest-release + os: windows-latest + build_type: 'Release' + - displayTargetName: windows-latest-debug + os: windows-latest + build_type: 'Debug' + steps: + - uses: actions/checkout@v2 + + - name: create build environment + run: cmake -E make_directory ${{ runner.workspace }}/_build + + - name: configure cmake + env: + CXX: ${{ matrix.compiler }} + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: > + cmake $GITHUB_WORKSPACE + -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + + - name: build + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: cmake --build . --config ${{ matrix.build_type }} + + - name: test + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: ctest -C ${{ matrix.build_type }} -VV + + ubuntu-14_04: + name: ubuntu-14.04.${{ matrix.build_type }}.${{ matrix.compiler }} + runs-on: [ubuntu-latest] + strategy: + fail-fast: false + matrix: + build_type: ['Release', 'Debug'] + compiler: [g++-4.8, clang++-3.6] + include: + - compiler: g++-6 + build_type: 'Debug' + run_tests: true + - compiler: g++-6 + build_type: 'Release' + run_tests: true + container: ubuntu:14.04 + steps: + - uses: actions/checkout@v2 + + - name: install required bits + run: | + sudo apt update + sudo apt -y install clang-3.6 cmake3 g++-4.8 git + + - name: install other bits + if: ${{ matrix.compiler }} == g++-6 + run: | + sudo apt -y install software-properties-common + sudo add-apt-repository -y "ppa:ubuntu-toolchain-r/test" + sudo apt update + sudo apt -y install g++-6 + + - name: create build environment + run: cmake -E make_directory $GITHUB_WORKSPACE/_build + + - name: configure cmake + env: + CXX: ${{ matrix.compiler }} + shell: bash + working-directory: ${{ github.workspace }}/_build + run: > + cmake $GITHUB_WORKSPACE + -DBENCHMARK_ENABLE_TESTING=${{ matrix.run_tests }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -DBENCHMARK_DOWNLOAD_DEPENDENCIES=${{ matrix.run_tests }} + + - name: build + shell: bash + working-directory: ${{ github.workspace }}/_build + run: cmake --build . --config ${{ matrix.build_type }} + + - name: test + if: ${{ matrix.run_tests }} + shell: bash + working-directory: ${{ github.workspace }}/_build + run: ctest -C ${{ matrix.build_type }} -VV diff --git a/libcxx/utils/google-benchmark/.github/workflows/pylint.yml b/libcxx/utils/google-benchmark/.github/workflows/pylint.yml new file mode 100644 index 0000000000000..0f73a5823206e --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/workflows/pylint.yml @@ -0,0 +1,26 @@ +name: pylint + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + pylint: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint pylint-exit conan + - name: Run pylint + run: | + pylint `find . -name '*.py'|xargs` || pylint-exit $? diff --git a/libcxx/utils/google-benchmark/.github/workflows/sanitizer.yml b/libcxx/utils/google-benchmark/.github/workflows/sanitizer.yml new file mode 100644 index 0000000000000..fbc984492df68 --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/workflows/sanitizer.yml @@ -0,0 +1,78 @@ +name: sanitizer + +on: + push: {} + pull_request: {} + +env: + CC: clang + CXX: clang++ + EXTRA_CXX_FLAGS: "-stdlib=libc++" + UBSAN_OPTIONS: "print_stacktrace=1" + +jobs: + job: + name: ${{ matrix.sanitizer }}.${{ matrix.build_type }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + build_type: ['Debug', 'RelWithDebInfo'] + sanitizer: ['asan', 'ubsan', 'tsan'] + # TODO: add 'msan' above. currently failing and needs investigation. + steps: + - uses: actions/checkout@v2 + + - name: configure msan env + if: matrix.sanitizer == 'msan' + run: | + echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins" >> $GITHUB_ENV + echo "LIBCXX_SANITIZER=MemoryWithOrigins" >> $GITHUB_ENV + + - name: configure ubsan env + if: matrix.sanitizer == 'ubsan' + run: | + echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize-recover=all" >> $GITHUB_ENV + echo "LIBCXX_SANITIZER=Undefined" >> $GITHUB_ENV + + - name: configure asan env + if: matrix.sanitizer == 'asan' + run: | + echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=address -fno-sanitize-recover=all" >> $GITHUB_ENV + echo "LIBCXX_SANITIZER=Address" >> $GITHUB_ENV + + - name: configure tsan env + if: matrix.sanitizer == 'tsan' + run: | + echo "EXTRA_FLAGS=-g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" >> $GITHUB_ENV + echo "LIBCXX_SANITIZER=Thread" >> $GITHUB_ENV + + - name: install llvm stuff + run: "${GITHUB_WORKSPACE}/.github/.libcxx-setup.sh" + + - name: create build environment + run: cmake -E make_directory ${{ runner.workspace }}/_build + + - name: configure cmake + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: > + cmake $GITHUB_WORKSPACE + -DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF + -DBENCHMARK_ENABLE_LIBPFM=OFF + -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON + -DCMAKE_C_COMPILER=${{ env.CC }} + -DCMAKE_CXX_COMPILER=${{ env.CXX }} + -DCMAKE_C_FLAGS="${{ env.EXTRA_FLAGS }}" + -DCMAKE_CXX_FLAGS="${{ env.EXTRA_FLAGS }} ${{ env.EXTRA_CXX_FLAGS }}" + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + + - name: build + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: cmake --build . --config ${{ matrix.build_type }} + + - name: test + shell: bash + working-directory: ${{ runner.workspace }}/_build + run: ctest -C ${{ matrix.build_type }} -VV diff --git a/libcxx/utils/google-benchmark/.github/workflows/test_bindings.yml b/libcxx/utils/google-benchmark/.github/workflows/test_bindings.yml new file mode 100644 index 0000000000000..4a580ebe047a4 --- /dev/null +++ b/libcxx/utils/google-benchmark/.github/workflows/test_bindings.yml @@ -0,0 +1,24 @@ +name: test-bindings + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + python_bindings: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.8 + - name: Install benchmark + run: + python setup.py install + - name: Run example bindings + run: + python bindings/python/google_benchmark/example.py diff --git a/libcxx/utils/google-benchmark/.gitignore b/libcxx/utils/google-benchmark/.gitignore index 8c30e28f53a06..be55d774e21bd 100644 --- a/libcxx/utils/google-benchmark/.gitignore +++ b/libcxx/utils/google-benchmark/.gitignore @@ -8,6 +8,7 @@ !/cmake/*.cmake !/test/AssemblyTests.cmake *~ +*.swp *.pyc __pycache__ @@ -56,3 +57,10 @@ build*/ # Visual Studio 2015/2017 cache/options directory .vs/ CMakeSettings.json + +# Visual Studio Code cache/options directory +.vscode/ + +# Python build stuff +dist/ +*.egg-info* diff --git a/libcxx/utils/google-benchmark/.travis-libcxx-setup.sh b/libcxx/utils/google-benchmark/.travis-libcxx-setup.sh deleted file mode 100644 index a591743c6a6ba..0000000000000 --- a/libcxx/utils/google-benchmark/.travis-libcxx-setup.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -# Install a newer CMake version -curl -sSL https://cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.sh -o install-cmake.sh -chmod +x install-cmake.sh -sudo ./install-cmake.sh --prefix=/usr/local --skip-license - -# Checkout LLVM sources -git clone --depth=1 https://github.com/llvm-mirror/llvm.git llvm-source -git clone --depth=1 https://github.com/llvm-mirror/libcxx.git llvm-source/projects/libcxx -git clone --depth=1 https://github.com/llvm-mirror/libcxxabi.git llvm-source/projects/libcxxabi - -# Setup libc++ options -if [ -z "$BUILD_32_BITS" ]; then - export BUILD_32_BITS=OFF && echo disabling 32 bit build -fi - -# Build and install libc++ (Use unstable ABI for better sanitizer coverage) -mkdir llvm-build && cd llvm-build -cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr \ - -DLIBCXX_ABI_UNSTABLE=ON \ - -DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \ - -DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \ - ../llvm-source -make cxx -j2 -sudo make install-cxxabi install-cxx -cd ../ diff --git a/libcxx/utils/google-benchmark/.travis.yml b/libcxx/utils/google-benchmark/.travis.yml index 4625dfb0878ff..8cfed3d10dab5 100644 --- a/libcxx/utils/google-benchmark/.travis.yml +++ b/libcxx/utils/google-benchmark/.travis.yml @@ -2,10 +2,6 @@ sudo: required dist: trusty language: cpp -env: - global: - - /usr/local/bin:$PATH - matrix: include: - compiler: gcc @@ -14,133 +10,146 @@ matrix: packages: - lcov env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Coverage - - compiler: gcc - env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug - - compiler: gcc - env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release - compiler: gcc addons: apt: packages: - g++-multilib - env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug BUILD_32_BITS=ON + - libc6:i386 + env: + - COMPILER=g++ + - C_COMPILER=gcc + - BUILD_TYPE=Debug + - BUILD_32_BITS=ON + - EXTRA_FLAGS="-m32" - compiler: gcc addons: apt: packages: - g++-multilib - env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release BUILD_32_BITS=ON + - libc6:i386 + env: + - COMPILER=g++ + - C_COMPILER=gcc + - BUILD_TYPE=Release + - BUILD_32_BITS=ON + - EXTRA_FLAGS="-m32" - compiler: gcc env: - INSTALL_GCC6_FROM_PPA=1 - COMPILER=g++-6 C_COMPILER=gcc-6 BUILD_TYPE=Debug - ENABLE_SANITIZER=1 - EXTRA_FLAGS="-fno-omit-frame-pointer -g -O2 -fsanitize=undefined,address -fuse-ld=gold" - - compiler: clang - env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Debug - - compiler: clang - env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Release # Clang w/ libc++ - compiler: clang + dist: xenial addons: apt: packages: clang-3.8 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug - LIBCXX_BUILD=1 - - EXTRA_FLAGS="-stdlib=libc++" + - EXTRA_CXX_FLAGS="-stdlib=libc++" - compiler: clang + dist: xenial addons: apt: packages: clang-3.8 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release - LIBCXX_BUILD=1 - - EXTRA_FLAGS="-stdlib=libc++" + - EXTRA_CXX_FLAGS="-stdlib=libc++" # Clang w/ 32bit libc++ - compiler: clang + dist: xenial addons: apt: packages: - clang-3.8 - g++-multilib + - libc6:i386 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug - LIBCXX_BUILD=1 - BUILD_32_BITS=ON - - EXTRA_FLAGS="-stdlib=libc++ -m32" + - EXTRA_FLAGS="-m32" + - EXTRA_CXX_FLAGS="-stdlib=libc++" # Clang w/ 32bit libc++ - compiler: clang + dist: xenial addons: apt: packages: - clang-3.8 - g++-multilib + - libc6:i386 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release - LIBCXX_BUILD=1 - BUILD_32_BITS=ON - - EXTRA_FLAGS="-stdlib=libc++ -m32" + - EXTRA_FLAGS="-m32" + - EXTRA_CXX_FLAGS="-stdlib=libc++" # Clang w/ libc++, ASAN, UBSAN - compiler: clang + dist: xenial addons: apt: packages: clang-3.8 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug - LIBCXX_BUILD=1 LIBCXX_SANITIZER="Undefined;Address" - ENABLE_SANITIZER=1 - - EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=undefined,address -fno-sanitize-recover=all" + - EXTRA_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=undefined,address -fno-sanitize-recover=all" + - EXTRA_CXX_FLAGS="-stdlib=libc++" - UBSAN_OPTIONS=print_stacktrace=1 # Clang w/ libc++ and MSAN - compiler: clang + dist: xenial addons: apt: packages: clang-3.8 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug - LIBCXX_BUILD=1 LIBCXX_SANITIZER=MemoryWithOrigins - ENABLE_SANITIZER=1 - - EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins" + - EXTRA_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins" + - EXTRA_CXX_FLAGS="-stdlib=libc++" # Clang w/ libc++ and MSAN - compiler: clang + dist: xenial addons: apt: packages: clang-3.8 env: + - INSTALL_GCC6_FROM_PPA=1 - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=RelWithDebInfo - LIBCXX_BUILD=1 LIBCXX_SANITIZER=Thread - ENABLE_SANITIZER=1 - - EXTRA_FLAGS="-stdlib=libc++ -g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" - - os: osx - osx_image: xcode8.3 - compiler: clang - env: - - COMPILER=clang++ BUILD_TYPE=Debug - - os: osx - osx_image: xcode8.3 - compiler: clang - env: - - COMPILER=clang++ BUILD_TYPE=Release + - EXTRA_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all" + - EXTRA_CXX_FLAGS="-stdlib=libc++" - os: osx osx_image: xcode8.3 compiler: clang env: - - COMPILER=clang++ BUILD_TYPE=Release BUILD_32_BITS=ON - - os: osx - osx_image: xcode8.3 - compiler: gcc - env: - - COMPILER=g++-7 C_COMPILER=gcc-7 BUILD_TYPE=Debug + - COMPILER=clang++ + - BUILD_TYPE=Release + - BUILD_32_BITS=ON + - EXTRA_FLAGS="-m32" before_script: - if [ -n "${LIBCXX_BUILD}" ]; then - source .travis-libcxx-setup.sh; + source .libcxx-setup.sh; fi - if [ -n "${ENABLE_SANITIZER}" ]; then export EXTRA_OPTIONS="-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF"; @@ -178,17 +187,17 @@ install: fi - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then sudo apt-get update -qq; - sudo apt-get install -qq unzip; - wget https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-linux-x86_64.sh --output-document bazel-installer.sh; + sudo apt-get install -qq unzip cmake3; + wget https://github.com/bazelbuild/bazel/releases/download/3.2.0/bazel-3.2.0-installer-linux-x86_64.sh --output-document bazel-installer.sh; travis_wait sudo bash bazel-installer.sh; fi - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then - curl -L -o bazel-installer.sh https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-darwin-x86_64.sh; + curl -L -o bazel-installer.sh https://github.com/bazelbuild/bazel/releases/download/3.2.0/bazel-3.2.0-installer-darwin-x86_64.sh; travis_wait sudo bash bazel-installer.sh; fi script: - - cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS}" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON -DBENCHMARK_BUILD_32_BITS=${BUILD_32_BITS} ${EXTRA_OPTIONS} .. + - cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_C_FLAGS="${EXTRA_FLAGS}" -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} ${EXTRA_CXX_FLAGS}" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON -DBENCHMARK_BUILD_32_BITS=${BUILD_32_BITS} ${EXTRA_OPTIONS} .. - make - ctest -C ${BUILD_TYPE} --output-on-failure - bazel test -c dbg --define google_benchmark.have_regex=posix --announce_rc --verbose_failures --test_output=errors --keep_going //test/... diff --git a/libcxx/utils/google-benchmark/AUTHORS b/libcxx/utils/google-benchmark/AUTHORS index 3593870661ec4..838dd4f5bd5e7 100644 --- a/libcxx/utils/google-benchmark/AUTHORS +++ b/libcxx/utils/google-benchmark/AUTHORS @@ -9,24 +9,32 @@ # Please keep the list sorted. Albert Pretorius +Alex Steele +Andriy Berestovskyy Arne Beer Carto +Christian Wassermann Christopher Seymour +Colin Braley +Daniel Harvey David Coeurjolly Deniz Evrenci Dirac Research Dominik Czarnota +Eric Backus Eric Fiselier Eugene Zhuk Evgeny Safronov Federico Ficarelli Felix Homann +Gergő Szitár Google Inc. International Business Machines Corporation Ismael Jimenez Martinez Jern-Kuan Leong JianXiong Zhou Joao Paulo Magalhaes +Jordan Williams Jussi Knuuttila Kaito Udagawa Kishan Kumar @@ -35,14 +43,17 @@ Matt Clarkson Maxim Vafin MongoDB Inc. Nick Hutchinson +Norman Heino Oleksandr Sochka Ori Livneh Paul Redmond Radoslav Yovchev Roman Lebedev +Sayan Bhattacharjee Shuo Chen Steinar H. Gunderson Stripe, Inc. +Tobias Schmidt Yixuan Qiu Yusuke Suzuki Zbigniew Skowron diff --git a/libcxx/utils/google-benchmark/BUILD.bazel b/libcxx/utils/google-benchmark/BUILD.bazel new file mode 100644 index 0000000000000..eb35b62730c67 --- /dev/null +++ b/libcxx/utils/google-benchmark/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +licenses(["notice"]) + +config_setting( + name = "windows", + values = { + "cpu": "x64_windows", + }, + visibility = [":__subpackages__"], +) + +cc_library( + name = "benchmark", + srcs = glob( + [ + "src/*.cc", + "src/*.h", + ], + exclude = ["src/benchmark_main.cc"], + ), + hdrs = ["include/benchmark/benchmark.h"], + linkopts = select({ + ":windows": ["-DEFAULTLIB:shlwapi.lib"], + "//conditions:default": ["-pthread"], + }), + strip_include_prefix = "include", + visibility = ["//visibility:public"], +) + +cc_library( + name = "benchmark_main", + srcs = ["src/benchmark_main.cc"], + hdrs = ["include/benchmark/benchmark.h"], + strip_include_prefix = "include", + visibility = ["//visibility:public"], + deps = [":benchmark"], +) + +cc_library( + name = "benchmark_internal_headers", + hdrs = glob(["src/*.h"]), + visibility = ["//test:__pkg__"], +) diff --git a/libcxx/utils/google-benchmark/CMakeLists.txt b/libcxx/utils/google-benchmark/CMakeLists.txt index 310c7ee9f6b2b..ef8dcdc68cfb8 100644 --- a/libcxx/utils/google-benchmark/CMakeLists.txt +++ b/libcxx/utils/google-benchmark/CMakeLists.txt @@ -1,17 +1,20 @@ -cmake_minimum_required (VERSION 2.8.12) - -project (benchmark) +cmake_minimum_required (VERSION 3.5.1) foreach(p + CMP0048 # OK to clear PROJECT_VERSION on project() CMP0054 # CMake 3.1 CMP0056 # export EXE_LINKER_FLAGS to try_run CMP0057 # Support no if() IN_LIST operator + CMP0063 # Honor visibility properties for all targets + CMP0077 # Allow option() overrides in importing projects ) if(POLICY ${p}) cmake_policy(SET ${p} NEW) endif() endforeach() +project (benchmark VERSION 1.5.4 LANGUAGES CXX) + option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON) option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON) option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF) @@ -31,6 +34,20 @@ option(BENCHMARK_DOWNLOAD_DEPENDENCIES "Allow the downloading and in-tree buildi # in cases where it is not possible to build or find a valid version of gtest. option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend on gtest" ON) +option(BENCHMARK_ENABLE_LIBPFM "Enable performance counters provided by libpfm" OFF) + +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +if(MSVC) + # As of CMake 3.18, CMAKE_SYSTEM_PROCESSOR is not set properly for MSVC and + # cross-compilation (e.g. Host=x86_64, target=aarch64) requires using the + # undocumented, but working variable. + # See https://gitlab.kitware.com/cmake/cmake/-/issues/15170 + set(CMAKE_SYSTEM_PROCESSOR ${MSVC_CXX_ARCHITECTURE_ID}) + if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM") + set(CMAKE_CROSSCOMPILING TRUE) + endif() +endif() + set(ENABLE_ASSEMBLY_TESTS_DEFAULT OFF) function(should_enable_assembly_tests) if(CMAKE_BUILD_TYPE) @@ -77,8 +94,14 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(GetGitVersion) get_git_version(GIT_VERSION) +# If no git version can be determined, use the version +# from the project() command +if ("${GIT_VERSION}" STREQUAL "0.0.0") + set(VERSION "${benchmark_VERSION}") +else() + set(VERSION "${GIT_VERSION}") +endif() # Tell the user what versions we are using -string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" VERSION ${GIT_VERSION}) message(STATUS "Version: ${VERSION}") # The version of the libraries @@ -140,6 +163,10 @@ else() add_cxx_compiler_flag(-Werror RELEASE) add_cxx_compiler_flag(-Werror RELWITHDEBINFO) add_cxx_compiler_flag(-Werror MINSIZEREL) + if (NOT BENCHMARK_ENABLE_TESTING) + # Disable warning when compiling tests as gtest does not use 'override'. + add_cxx_compiler_flag(-Wsuggest-override) + endif() add_cxx_compiler_flag(-pedantic) add_cxx_compiler_flag(-pedantic-errors) add_cxx_compiler_flag(-Wshorten-64-to-32) @@ -182,10 +209,15 @@ else() add_definitions(-D_GNU_SOURCE=1) endif() + if (QNXNTO) + add_definitions(-D_QNX_SOURCE) + endif() + # Link time optimisation if (BENCHMARK_ENABLE_LTO) add_cxx_compiler_flag(-flto) - if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + add_cxx_compiler_flag(-Wno-lto-type-mismatch) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") find_program(GCC_AR gcc-ar) if (GCC_AR) set(CMAKE_AR ${GCC_AR}) @@ -194,7 +226,7 @@ else() if (GCC_RANLIB) set(CMAKE_RANLIB ${GCC_RANLIB}) endif() - elseif("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") + elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") include(llvm-toolchain) endif() endif() @@ -236,11 +268,17 @@ if (BENCHMARK_USE_LIBCXX) endif() endif(BENCHMARK_USE_LIBCXX) +set(EXTRA_CXX_FLAGS "") +if (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + # Clang on Windows fails to compile the regex feature check under C++11 + set(EXTRA_CXX_FLAGS "-DCMAKE_CXX_STANDARD=14") +endif() + # C++ feature checks # Determine the correct regular expression engine to use -cxx_feature_check(STD_REGEX) -cxx_feature_check(GNU_POSIX_REGEX) -cxx_feature_check(POSIX_REGEX) +cxx_feature_check(STD_REGEX ${EXTRA_CXX_FLAGS}) +cxx_feature_check(GNU_POSIX_REGEX ${EXTRA_CXX_FLAGS}) +cxx_feature_check(POSIX_REGEX ${EXTRA_CXX_FLAGS}) if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX) message(FATAL_ERROR "Failed to determine the source files for the regular expression backend") endif() @@ -248,10 +286,16 @@ if (NOT BENCHMARK_ENABLE_EXCEPTIONS AND HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX) message(WARNING "Using std::regex with exceptions disabled is not fully supported") endif() + cxx_feature_check(STEADY_CLOCK) # Ensure we have pthreads +set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) +if (BENCHMARK_ENABLE_LIBPFM) + find_package(PFM) +endif() + # Set up directories include_directories(${PROJECT_SOURCE_DIR}/include) @@ -260,8 +304,10 @@ add_subdirectory(src) if (BENCHMARK_ENABLE_TESTING) enable_testing() - if (BENCHMARK_ENABLE_GTEST_TESTS) - include(HandleGTest) + if (BENCHMARK_ENABLE_GTEST_TESTS AND + NOT (TARGET gtest AND TARGET gtest_main AND + TARGET gmock AND TARGET gmock_main)) + include(GoogleTest) endif() add_subdirectory(test) endif() diff --git a/libcxx/utils/google-benchmark/CONTRIBUTORS b/libcxx/utils/google-benchmark/CONTRIBUTORS index f684c7d4b2d4c..7489731de5a82 100644 --- a/libcxx/utils/google-benchmark/CONTRIBUTORS +++ b/libcxx/utils/google-benchmark/CONTRIBUTORS @@ -22,34 +22,47 @@ # # Please keep the list sorted. +Abhina Sreeskantharajan Albert Pretorius +Alex Steele +Andriy Berestovskyy Arne Beer Billy Robert O'Neal III Chris Kennelly +Christian Wassermann Christopher Seymour +Colin Braley Cyrille Faucheux +Daniel Harvey David Coeurjolly Deniz Evrenci Dominic Hamon Dominik Czarnota +Eric Backus Eric Fiselier Eugene Zhuk Evgeny Safronov +Fanbo Meng Federico Ficarelli Felix Homann +Geoffrey Martin-Noble +Gergő Szitár +Hannes Hauswedell Ismael Jimenez Martinez Jern-Kuan Leong JianXiong Zhou Joao Paulo Magalhaes John Millikin +Jordan Williams Jussi Knuuttila Kai Wolf -Kishan Kumar Kaito Udagawa +Kishan Kumar Lei Xu Matt Clarkson Maxim Vafin Nick Hutchinson +Norman Heino Oleksandr Sochka Ori Livneh Pascal Leroy @@ -60,8 +73,10 @@ Raul Marin Ray Glover Robert Guo Roman Lebedev +Sayan Bhattacharjee Shuo Chen Steven Wan +Tobias Schmidt Tobias Ulvgård Tom Madams Yixuan Qiu diff --git a/libcxx/utils/google-benchmark/README.LLVM b/libcxx/utils/google-benchmark/README.LLVM deleted file mode 100644 index 34afcc02b2947..0000000000000 --- a/libcxx/utils/google-benchmark/README.LLVM +++ /dev/null @@ -1,28 +0,0 @@ -LLVM notes ----------- - -This directory contains the Google Benchmark source code with some unnecessary -files removed. Note that this directory is under a different license than -libc++. - -Changes: -* https://github.com/google/benchmark/commit/4abdfbb802d1b514703223f5f852ce4a507d32d2 - is applied on top of - https://github.com/google/benchmark/commit/4528c76b718acc9b57956f63069c699ae21edcab - to add RISC-V timer support. -* https://github.com/google/benchmark/commit/8e48105d465c586068dd8e248fe75a8971c6ba3a - is applied on top of - https://github.com/google/benchmark/commit/4528c76b718acc9b57956f63069c699ae21edcab - to fix cross-build from linux to windows via MinGW. -* https://github.com/google/benchmark/commit/a77d5f70efaebe2b7e8c10134526a23a7ce7ef35 - and - https://github.com/google/benchmark/commit/ecc1685340f58f7fe6b707036bc0bb1fccabb0c1 - are applied on top of - https://github.com/google/benchmark/commit/8e48105d465c586068dd8e248fe75a8971c6ba3a - to fix timestamp-related inline asm issues and 32-bit RISC-V build failures. - The second cherrypicked commit fixes formatting issues introduced by the - preceding change. -* https://github.com/google/benchmark/commit/ffe1342eb2faa7d2e7c35b4db2ccf99fab81ec20 - is applied to add the CycleTimer implementation for M68k -* https://github.com/google/benchmark/commit/d9abf017632be4a00b92cf4289539b353fcea5d2 - is applied to rename 'mftbl' to 'mftb'. diff --git a/libcxx/utils/google-benchmark/README.md b/libcxx/utils/google-benchmark/README.md index 858ea2334ef50..aa61cef1b162f 100644 --- a/libcxx/utils/google-benchmark/README.md +++ b/libcxx/utils/google-benchmark/README.md @@ -1,32 +1,111 @@ -# benchmark +# Benchmark + +[![build-and-test](https://github.com/google/benchmark/workflows/build-and-test/badge.svg)](https://github.com/google/benchmark/actions?query=workflow%3Abuild-and-test) +[![bazel](https://github.com/google/benchmark/actions/workflows/bazel.yml/badge.svg)](https://github.com/google/benchmark/actions/workflows/bazel.yml) +[![pylint](https://github.com/google/benchmark/workflows/pylint/badge.svg)](https://github.com/google/benchmark/actions?query=workflow%3Apylint) +[![test-bindings](https://github.com/google/benchmark/workflows/test-bindings/badge.svg)](https://github.com/google/benchmark/actions?query=workflow%3Atest-bindings) + [![Build Status](https://travis-ci.org/google/benchmark.svg?branch=master)](https://travis-ci.org/google/benchmark) -[![Build status](https://ci.appveyor.com/api/projects/status/u0qsyp7t1tk7cpxs/branch/master?svg=true)](https://ci.appveyor.com/project/google/benchmark/branch/master) [![Coverage Status](https://coveralls.io/repos/google/benchmark/badge.svg)](https://coveralls.io/r/google/benchmark) -[![slackin](https://slackin-iqtfqnpzxd.now.sh/badge.svg)](https://slackin-iqtfqnpzxd.now.sh/) -A library to support the benchmarking of functions, similar to unit-tests. + +A library to benchmark code snippets, similar to unit tests. Example: + +```c++ +#include + +static void BM_SomeFunction(benchmark::State& state) { + // Perform setup here + for (auto _ : state) { + // This code gets timed + SomeFunction(); + } +} +// Register the function as a benchmark +BENCHMARK(BM_SomeFunction); +// Run the benchmark +BENCHMARK_MAIN(); +``` + +To get started, see [Requirements](#requirements) and +[Installation](#installation). See [Usage](#usage) for a full example and the +[User Guide](#user-guide) for a more comprehensive feature overview. + +It may also help to read the [Google Test documentation](https://github.com/google/googletest/blob/master/docs/primer.md) +as some of the structural aspects of the APIs are similar. + +### Resources [Discussion group](https://groups.google.com/d/forum/benchmark-discuss) -IRC channel: [freenode](https://freenode.net) #googlebenchmark +IRC channels: +* [libera](https://libera.chat) #benchmark [Additional Tooling Documentation](docs/tools.md) [Assembly Testing Documentation](docs/AssemblyTests.md) +## Requirements + +The library can be used with C++03. However, it requires C++11 to build, +including compiler and standard library support. + +The following minimum versions are required to build the library: + +* GCC 4.8 +* Clang 3.4 +* Visual Studio 14 2015 +* Intel 2015 Update 1 + +See [Platform-Specific Build Instructions](#platform-specific-build-instructions). -## Building +## Installation -The basic steps for configuring and building the library look like this: +This describes the installation process using cmake. As pre-requisites, you'll +need git and cmake installed. + +_See [dependencies.md](dependencies.md) for more details regarding supported +versions of build tools._ ```bash +# Check out the library. $ git clone https://github.com/google/benchmark.git # Benchmark requires Google Test as a dependency. Add the source tree as a subdirectory. $ git clone https://github.com/google/googletest.git benchmark/googletest -$ mkdir build && cd build -$ cmake -G [options] ../benchmark -# Assuming a makefile generator was used -$ make +# Go to the library root directory +$ cd benchmark +# Make a build directory to place the build output. +$ cmake -E make_directory "build" +# Generate build system files with cmake. +$ cmake -E chdir "build" cmake -DCMAKE_BUILD_TYPE=Release ../ +# or, starting with CMake 3.13, use a simpler form: +# cmake -DCMAKE_BUILD_TYPE=Release -S . -B "build" +# Build the library. +$ cmake --build "build" --config Release +``` +This builds the `benchmark` and `benchmark_main` libraries and tests. +On a unix system, the build directory should now look something like this: + +``` +/benchmark + /build + /src + /libbenchmark.a + /libbenchmark_main.a + /test + ... +``` + +Next, you can run the tests to check the build. + +```bash +$ cmake -E chdir "build" ctest --build-config Release +``` + +If you want to install the library globally, also run: + +``` +sudo cmake --build "build" --config Release --target install ``` Note that Google Benchmark requires Google Test to build and run the tests. This @@ -40,37 +119,25 @@ dependency can be provided two ways: If you do not wish to build and run the tests, add `-DBENCHMARK_ENABLE_GTEST_TESTS=OFF` to `CMAKE_ARGS`. +### Debug vs Release -## Installation Guide - -For Ubuntu and Debian Based System - -First make sure you have git and cmake installed (If not please install them) - -``` -sudo apt-get install git cmake -``` - -Now, let's clone the repository and build it +By default, benchmark builds as a debug library. You will see a warning in the +output when this is the case. To build it as a release library instead, add +`-DCMAKE_BUILD_TYPE=Release` when generating the build system files, as shown +above. The use of `--config Release` in build commands is needed to properly +support multi-configuration tools (like Visual Studio for example) and can be +skipped for other build systems (like Makefile). -``` -git clone https://github.com/google/benchmark.git -cd benchmark -# If you want to build tests and don't use BENCHMARK_DOWNLOAD_DEPENDENCIES, then -# git clone https://github.com/google/googletest.git -mkdir build -cd build -cmake .. -DCMAKE_BUILD_TYPE=RELEASE -make -``` +To enable link-time optimisation, also add `-DBENCHMARK_ENABLE_LTO=true` when +generating the build system files. -If you need to install the library globally +If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake +cache variables, if autodetection fails. -``` -sudo make install -``` +If you are using clang, you may need to set `LLVMAR_EXECUTABLE`, +`LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables. -## Stable and Experimental Library Versions +### Stable and Experimental Library Versions The main branch contains the latest stable version of the benchmarking library; the API of which can be considered largely stable, with source breaking changes @@ -82,16 +149,13 @@ to use, test, and provide feedback on the new features are encouraged to try this branch. However, this branch provides no stability guarantees and reserves the right to change and break the API at any time. -## Further knowledge - -It may help to read the [Google Test documentation](https://github.com/google/googletest/blob/master/googletest/docs/primer.md) -as some of the structural aspects of the APIs are similar. +## Usage -## Example usage ### Basic usage -Define a function that executes the code to be measured, register it as a -benchmark function using the `BENCHMARK` macro, and ensure an appropriate `main` -function is available: + +Define a function that executes the code to measure, register it as a benchmark +function using the `BENCHMARK` macro, and ensure an appropriate `main` function +is available: ```c++ #include @@ -114,15 +178,47 @@ BENCHMARK(BM_StringCopy); BENCHMARK_MAIN(); ``` -Don't forget to inform your linker to add benchmark library e.g. through -`-lbenchmark` compilation flag. Alternatively, you may leave out the -`BENCHMARK_MAIN();` at the end of the source file and link against -`-lbenchmark_main` to get the same default behavior. +To run the benchmark, compile and link against the `benchmark` library +(libbenchmark.a/.so). If you followed the build steps above, this library will +be under the build directory you created. + +```bash +# Example on linux after running the build steps above. Assumes the +# `benchmark` and `build` directories are under the current directory. +$ g++ mybenchmark.cc -std=c++11 -isystem benchmark/include \ + -Lbenchmark/build/src -lbenchmark -lpthread -o mybenchmark +``` + +Alternatively, link against the `benchmark_main` library and remove +`BENCHMARK_MAIN();` above to get the same behavior. + +The compiled executable will run all benchmarks by default. Pass the `--help` +flag for option information or see the guide below. + +### Usage with CMake + +If using CMake, it is recommended to link against the project-provided +`benchmark::benchmark` and `benchmark::benchmark_main` targets using +`target_link_libraries`. +It is possible to use ```find_package``` to import an installed version of the +library. +```cmake +find_package(benchmark REQUIRED) +``` +Alternatively, ```add_subdirectory``` will incorporate the library directly in +to one's CMake project. +```cmake +add_subdirectory(benchmark) +``` +Either way, link to the library as follows. +```cmake +target_link_libraries(MyTarget benchmark::benchmark) +``` + +## Platform Specific Build Instructions -The benchmark library will measure and report the timing for code within the -`for(...)` loop. +### Building with GCC -#### Platform-specific libraries When the library is built using GCC it is necessary to link with the pthread library due to how GCC implements `std::thread`. Failing to link to pthread will lead to runtime exceptions (unless you're using libc++), not linker errors. See @@ -131,13 +227,282 @@ can link to pthread by adding `-pthread` to your linker command. Note, you can also use `-lpthread`, but there are potential issues with ordering of command line parameters if you use that. -If you're running benchmarks on Windows, the shlwapi library (`-lshlwapi`) is -also required. +### Building with Visual Studio 2015 or 2017 + +The `shlwapi` library (`-lshlwapi`) is required to support a call to `CPUInfo` which reads the registry. Either add `shlwapi.lib` under `[ Configuration Properties > Linker > Input ]`, or use the following: + +``` +// Alternatively, can add libraries using linker options. +#ifdef _WIN32 +#pragma comment ( lib, "Shlwapi.lib" ) +#ifdef _DEBUG +#pragma comment ( lib, "benchmarkd.lib" ) +#else +#pragma comment ( lib, "benchmark.lib" ) +#endif +#endif +``` + +Can also use the graphical version of CMake: +* Open `CMake GUI`. +* Under `Where to build the binaries`, same path as source plus `build`. +* Under `CMAKE_INSTALL_PREFIX`, same path as source plus `install`. +* Click `Configure`, `Generate`, `Open Project`. +* If build fails, try deleting entire directory and starting again, or unticking options to build less. + +### Building with Intel 2015 Update 1 or Intel System Studio Update 4 + +See instructions for building with Visual Studio. Once built, right click on the solution and change the build to Intel. + +### Building on Solaris If you're running benchmarks on solaris, you'll want the kstat library linked in too (`-lkstat`). -### Passing arguments +## User Guide + +### Command Line + +[Output Formats](#output-formats) + +[Output Files](#output-files) + +[Running Benchmarks](#running-benchmarks) + +[Running a Subset of Benchmarks](#running-a-subset-of-benchmarks) + +[Result Comparison](#result-comparison) + +[Extra Context](#extra-context) + +### Library + +[Runtime and Reporting Considerations](#runtime-and-reporting-considerations) + +[Passing Arguments](#passing-arguments) + +[Custom Benchmark Name](#custom-benchmark-name) + +[Calculating Asymptotic Complexity](#asymptotic-complexity) + +[Templated Benchmarks](#templated-benchmarks) + +[Fixtures](#fixtures) + +[Custom Counters](#custom-counters) + +[Multithreaded Benchmarks](#multithreaded-benchmarks) + +[CPU Timers](#cpu-timers) + +[Manual Timing](#manual-timing) + +[Setting the Time Unit](#setting-the-time-unit) + +[Random Interleaving](docs/random_interleaving.md) + +[User-Requested Performance Counters](docs/perf_counters.md) + +[Preventing Optimization](#preventing-optimization) + +[Reporting Statistics](#reporting-statistics) + +[Custom Statistics](#custom-statistics) + +[Using RegisterBenchmark](#using-register-benchmark) + +[Exiting with an Error](#exiting-with-an-error) + +[A Faster KeepRunning Loop](#a-faster-keep-running-loop) + +[Disabling CPU Frequency Scaling](#disabling-cpu-frequency-scaling) + + + + +### Output Formats + +The library supports multiple output formats. Use the +`--benchmark_format=` flag (or set the +`BENCHMARK_FORMAT=` environment variable) to set +the format type. `console` is the default format. + +The Console format is intended to be a human readable format. By default +the format generates color output. Context is output on stderr and the +tabular data on stdout. Example tabular output looks like: + +``` +Benchmark Time(ns) CPU(ns) Iterations +---------------------------------------------------------------------- +BM_SetInsert/1024/1 28928 29349 23853 133.097kB/s 33.2742k items/s +BM_SetInsert/1024/8 32065 32913 21375 949.487kB/s 237.372k items/s +BM_SetInsert/1024/10 33157 33648 21431 1.13369MB/s 290.225k items/s +``` + +The JSON format outputs human readable json split into two top level attributes. +The `context` attribute contains information about the run in general, including +information about the CPU and the date. +The `benchmarks` attribute contains a list of every benchmark run. Example json +output looks like: + +```json +{ + "context": { + "date": "2015/03/17-18:40:25", + "num_cpus": 40, + "mhz_per_cpu": 2801, + "cpu_scaling_enabled": false, + "build_type": "debug" + }, + "benchmarks": [ + { + "name": "BM_SetInsert/1024/1", + "iterations": 94877, + "real_time": 29275, + "cpu_time": 29836, + "bytes_per_second": 134066, + "items_per_second": 33516 + }, + { + "name": "BM_SetInsert/1024/8", + "iterations": 21609, + "real_time": 32317, + "cpu_time": 32429, + "bytes_per_second": 986770, + "items_per_second": 246693 + }, + { + "name": "BM_SetInsert/1024/10", + "iterations": 21393, + "real_time": 32724, + "cpu_time": 33355, + "bytes_per_second": 1199226, + "items_per_second": 299807 + } + ] +} +``` + +The CSV format outputs comma-separated values. The `context` is output on stderr +and the CSV itself on stdout. Example CSV output looks like: + +``` +name,iterations,real_time,cpu_time,bytes_per_second,items_per_second,label +"BM_SetInsert/1024/1",65465,17890.7,8407.45,475768,118942, +"BM_SetInsert/1024/8",116606,18810.1,9766.64,3.27646e+06,819115, +"BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06, +``` + + + +### Output Files + +Write benchmark results to a file with the `--benchmark_out=` option +(or set `BENCHMARK_OUT`). Specify the output format with +`--benchmark_out_format={json|console|csv}` (or set +`BENCHMARK_OUT_FORMAT={json|console|csv}`). Note that the 'csv' reporter is +deprecated and the saved `.csv` file +[is not parsable](https://github.com/google/benchmark/issues/794) by csv +parsers. + +Specifying `--benchmark_out` does not suppress the console output. + + + +### Running Benchmarks + +Benchmarks are executed by running the produced binaries. Benchmarks binaries, +by default, accept options that may be specified either through their command +line interface or by setting environment variables before execution. For every +`--option_flag=` CLI switch, a corresponding environment variable +`OPTION_FLAG=` exist and is used as default if set (CLI switches always + prevails). A complete list of CLI options is available running benchmarks + with the `--help` switch. + + + +### Running a Subset of Benchmarks + +The `--benchmark_filter=` option (or `BENCHMARK_FILTER=` +environment variable) can be used to only run the benchmarks that match +the specified ``. For example: + +```bash +$ ./run_benchmarks.x --benchmark_filter=BM_memcpy/32 +Run on (1 X 2300 MHz CPU ) +2016-06-25 19:34:24 +Benchmark Time CPU Iterations +---------------------------------------------------- +BM_memcpy/32 11 ns 11 ns 79545455 +BM_memcpy/32k 2181 ns 2185 ns 324074 +BM_memcpy/32 12 ns 12 ns 54687500 +BM_memcpy/32k 1834 ns 1837 ns 357143 +``` + + + +### Result comparison + +It is possible to compare the benchmarking results. +See [Additional Tooling Documentation](docs/tools.md) + + + +### Extra Context + +Sometimes it's useful to add extra context to the content printed before the +results. By default this section includes information about the CPU on which +the benchmarks are running. If you do want to add more context, you can use +the `benchmark_context` command line flag: + +```bash +$ ./run_benchmarks --benchmark_context=pwd=`pwd` +Run on (1 x 2300 MHz CPU) +pwd: /home/user/benchmark/ +Benchmark Time CPU Iterations +---------------------------------------------------- +BM_memcpy/32 11 ns 11 ns 79545455 +BM_memcpy/32k 2181 ns 2185 ns 324074 +``` + +You can get the same effect with the API: + +```c++ + benchmark::AddCustomContext("foo", "bar"); +``` + +Note that attempts to add a second value with the same key will fail with an +error message. + + + +### Runtime and Reporting Considerations + +When the benchmark binary is executed, each benchmark function is run serially. +The number of iterations to run is determined dynamically by running the +benchmark a few times and measuring the time taken and ensuring that the +ultimate result will be statistically stable. As such, faster benchmark +functions will be run for more iterations than slower benchmark functions, and +the number of iterations is thus reported. + +In all cases, the number of iterations for which the benchmark is run is +governed by the amount of time the benchmark takes. Concretely, the number of +iterations is at least one, not more than 1e9, until CPU time is greater than +the minimum time, or the wallclock time is 5x minimum time. The minimum time is +set per benchmark by calling `MinTime` on the registered benchmark object. + +Average timings are then reported over the iterations run. If multiple +repetitions are requested using the `--benchmark_repetitions` command-line +option, or at registration time, the benchmark function will be run several +times and statistical results across these repetitions will also be reported. + +As well as the per-benchmark entries, a preamble in the report will include +information about the machine on which the benchmarks are run. + + + +### Passing Arguments + Sometimes a family of benchmarks can be implemented with just one routine that takes an extra argument to specify which one of the family of benchmarks to run. For example, the following code defines a family of benchmarks for @@ -173,8 +538,26 @@ range multiplier is changed to multiples of two. ```c++ BENCHMARK(BM_memcpy)->RangeMultiplier(2)->Range(8, 8<<10); ``` + Now arguments generated are [ 8, 16, 32, 64, 128, 256, 512, 1024, 2k, 4k, 8k ]. +The preceding code shows a method of defining a sparse range. The following +example shows a method of defining a dense range. It is then used to benchmark +the performance of `std::vector` initialization for uniformly increasing sizes. + +```c++ +static void BM_DenseRange(benchmark::State& state) { + for(auto _ : state) { + std::vector v(state.range(0), state.range(0)); + benchmark::DoNotOptimize(v.data()); + benchmark::ClobberMemory(); + } +} +BENCHMARK(BM_DenseRange)->DenseRange(0, 1024, 128); +``` + +Now arguments generated are [ 0, 128, 256, 384, 512, 640, 768, 896, 1024 ]. + You might have a benchmark that depends on two or more inputs. For example, the following code defines a family of benchmarks for measuring the speed of set insertion. @@ -210,6 +593,29 @@ pair. BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}}); ``` +Some benchmarks may require specific argument values that cannot be expressed +with `Ranges`. In this case, `ArgsProduct` offers the ability to generate a +benchmark input for each combination in the product of the supplied vectors. + +```c++ +BENCHMARK(BM_SetInsert) + ->ArgsProduct({{1<<10, 3<<10, 8<<10}, {20, 40, 60, 80}}) +// would generate the same benchmark arguments as +BENCHMARK(BM_SetInsert) + ->Args({1<<10, 20}) + ->Args({3<<10, 20}) + ->Args({8<<10, 20}) + ->Args({3<<10, 40}) + ->Args({8<<10, 40}) + ->Args({1<<10, 40}) + ->Args({1<<10, 60}) + ->Args({3<<10, 60}) + ->Args({8<<10, 60}) + ->Args({1<<10, 80}) + ->Args({3<<10, 80}) + ->Args({8<<10, 80}); +``` + For more complex patterns of inputs, passing a custom function to `Apply` allows programmatic specification of an arbitrary set of arguments on which to run the benchmark. The following example enumerates a dense range on one parameter, @@ -224,7 +630,32 @@ static void CustomArguments(benchmark::internal::Benchmark* b) { BENCHMARK(BM_SetInsert)->Apply(CustomArguments); ``` -### Calculate asymptotic complexity (Big O) +#### Passing Arbitrary Arguments to a Benchmark + +In C++11 it is possible to define a benchmark that takes an arbitrary number +of extra arguments. The `BENCHMARK_CAPTURE(func, test_case_name, ...args)` +macro creates a benchmark that invokes `func` with the `benchmark::State` as +the first argument followed by the specified `args...`. +The `test_case_name` is appended to the name of the benchmark and +should describe the values passed. + +```c++ +template +void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) { + [...] +} +// Registers a benchmark named "BM_takes_args/int_string_test" that passes +// the specified values to `extra_args`. +BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc")); +``` + +Note that elements of `...args` may refer to global variables. Users should +avoid modifying global state inside of a benchmark. + + + +### Calculating Asymptotic Complexity (Big O) + Asymptotic complexity might be calculated for a family of benchmarks. The following code will calculate the coefficient for the high-order term in the running time and the normalized root-mean square error of string comparison. @@ -255,13 +686,28 @@ that might be used to customize high-order term calculation. ```c++ BENCHMARK(BM_StringCompare)->RangeMultiplier(2) - ->Range(1<<10, 1<<18)->Complexity([](int64_t n)->double{return n; }); + ->Range(1<<10, 1<<18)->Complexity([](benchmark::IterationCount n)->double{return n; }); +``` + + + +### Custom Benchmark Name + +You can change the benchmark's name as follows: + +```c++ +BENCHMARK(BM_memcpy)->Name("memcpy")->RangeMultiplier(2)->Range(8, 8<<10); ``` -### Templated benchmarks -Templated benchmarks work the same way: This example produces and consumes -messages of size `sizeof(v)` `range_x` times. It also outputs throughput in the -absence of multiprogramming. +The invocation will execute the benchmark as before using `BM_memcpy` but changes +the prefix in the report to `memcpy`. + + + +### Templated Benchmarks + +This example produces and consumes messages of size `sizeof(v)` `range_x` +times. It also outputs throughput in the absence of multiprogramming. ```c++ template void BM_Sequential(benchmark::State& state) { @@ -292,219 +738,392 @@ Three macros are provided for adding benchmark templates. #define BENCHMARK_TEMPLATE2(func, arg1, arg2) ``` -### A Faster KeepRunning loop + -In C++11 mode, a ranged-based for loop should be used in preference to -the `KeepRunning` loop for running the benchmarks. For example: - -```c++ -static void BM_Fast(benchmark::State &state) { - for (auto _ : state) { - FastOperation(); - } -} -BENCHMARK(BM_Fast); -``` - -The reason the ranged-for loop is faster than using `KeepRunning`, is -because `KeepRunning` requires a memory load and store of the iteration count -ever iteration, whereas the ranged-for variant is able to keep the iteration count -in a register. +### Fixtures -For example, an empty inner loop of using the ranged-based for method looks like: +Fixture tests are created by first defining a type that derives from +`::benchmark::Fixture` and then creating/registering the tests using the +following macros: -```asm -# Loop Init - mov rbx, qword ptr [r14 + 104] - call benchmark::State::StartKeepRunning() - test rbx, rbx - je .LoopEnd -.LoopHeader: # =>This Inner Loop Header: Depth=1 - add rbx, -1 - jne .LoopHeader -.LoopEnd: -``` +* `BENCHMARK_F(ClassName, Method)` +* `BENCHMARK_DEFINE_F(ClassName, Method)` +* `BENCHMARK_REGISTER_F(ClassName, Method)` -Compared to an empty `KeepRunning` loop, which looks like: +For Example: -```asm -.LoopHeader: # in Loop: Header=BB0_3 Depth=1 - cmp byte ptr [rbx], 1 - jne .LoopInit -.LoopBody: # =>This Inner Loop Header: Depth=1 - mov rax, qword ptr [rbx + 8] - lea rcx, [rax + 1] - mov qword ptr [rbx + 8], rcx - cmp rax, qword ptr [rbx + 104] - jb .LoopHeader - jmp .LoopEnd -.LoopInit: - mov rdi, rbx - call benchmark::State::StartKeepRunning() - jmp .LoopBody -.LoopEnd: -``` +```c++ +class MyFixture : public benchmark::Fixture { +public: + void SetUp(const ::benchmark::State& state) { + } -Unless C++03 compatibility is required, the ranged-for variant of writing -the benchmark loop should be preferred. + void TearDown(const ::benchmark::State& state) { + } +}; -## Passing arbitrary arguments to a benchmark -In C++11 it is possible to define a benchmark that takes an arbitrary number -of extra arguments. The `BENCHMARK_CAPTURE(func, test_case_name, ...args)` -macro creates a benchmark that invokes `func` with the `benchmark::State` as -the first argument followed by the specified `args...`. -The `test_case_name` is appended to the name of the benchmark and -should describe the values passed. +BENCHMARK_F(MyFixture, FooTest)(benchmark::State& st) { + for (auto _ : st) { + ... + } +} -```c++ -template -void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) { - [...] +BENCHMARK_DEFINE_F(MyFixture, BarTest)(benchmark::State& st) { + for (auto _ : st) { + ... + } } -// Registers a benchmark named "BM_takes_args/int_string_test" that passes -// the specified values to `extra_args`. -BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc")); +/* BarTest is NOT registered */ +BENCHMARK_REGISTER_F(MyFixture, BarTest)->Threads(2); +/* BarTest is now registered */ ``` -Note that elements of `...args` may refer to global variables. Users should -avoid modifying global state inside of a benchmark. -## Using RegisterBenchmark(name, fn, args...) +#### Templated Fixtures -The `RegisterBenchmark(name, func, args...)` function provides an alternative -way to create and register benchmarks. -`RegisterBenchmark(name, func, args...)` creates, registers, and returns a -pointer to a new benchmark with the specified `name` that invokes -`func(st, args...)` where `st` is a `benchmark::State` object. +Also you can create templated fixture by using the following macros: -Unlike the `BENCHMARK` registration macros, which can only be used at the global -scope, the `RegisterBenchmark` can be called anywhere. This allows for -benchmark tests to be registered programmatically. +* `BENCHMARK_TEMPLATE_F(ClassName, Method, ...)` +* `BENCHMARK_TEMPLATE_DEFINE_F(ClassName, Method, ...)` -Additionally `RegisterBenchmark` allows any callable object to be registered -as a benchmark. Including capturing lambdas and function objects. +For example: -For Example: ```c++ -auto BM_test = [](benchmark::State& st, auto Inputs) { /* ... */ }; +template +class MyFixture : public benchmark::Fixture {}; -int main(int argc, char** argv) { - for (auto& test_input : { /* ... */ }) - benchmark::RegisterBenchmark(test_input.name(), BM_test, test_input); - benchmark::Initialize(&argc, argv); - benchmark::RunSpecifiedBenchmarks(); +BENCHMARK_TEMPLATE_F(MyFixture, IntTest, int)(benchmark::State& st) { + for (auto _ : st) { + ... + } } -``` - -### Multithreaded benchmarks -In a multithreaded test (benchmark invoked by multiple threads simultaneously), -it is guaranteed that none of the threads will start until all have reached -the start of the benchmark loop, and all will have finished before any thread -exits the benchmark loop. (This behavior is also provided by the `KeepRunning()` -API) As such, any global setup or teardown can be wrapped in a check against the thread -index: -```c++ -static void BM_MultiThreaded(benchmark::State& state) { - if (state.thread_index == 0) { - // Setup code here. - } - for (auto _ : state) { - // Run the test as normal. - } - if (state.thread_index == 0) { - // Teardown code here. +BENCHMARK_TEMPLATE_DEFINE_F(MyFixture, DoubleTest, double)(benchmark::State& st) { + for (auto _ : st) { + ... } } -BENCHMARK(BM_MultiThreaded)->Threads(2); -``` - -If the benchmarked code itself uses threads and you want to compare it to -single-threaded code, you may want to use real-time ("wallclock") measurements -for latency comparisons: -```c++ -BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime(); +BENCHMARK_REGISTER_F(MyFixture, DoubleTest)->Threads(2); ``` -Without `UseRealTime`, CPU time is used by default. + -## Controlling timers -Normally, the entire duration of the work loop (`for (auto _ : state) {}`) -is measured. But sometimes, it is nessesary to do some work inside of -that loop, every iteration, but without counting that time to the benchmark time. -That is possible, althought it is not recommended, since it has high overhead. +### Custom Counters + +You can add your own counters with user-defined names. The example below +will add columns "Foo", "Bar" and "Baz" in its output: ```c++ -static void BM_SetInsert_With_Timer_Control(benchmark::State& state) { - std::set data; +static void UserCountersExample1(benchmark::State& state) { + double numFoos = 0, numBars = 0, numBazs = 0; for (auto _ : state) { - state.PauseTiming(); // Stop timers. They will not count until they are resumed. - data = ConstructRandomSet(state.range(0)); // Do something that should not be measured - state.ResumeTiming(); // And resume timers. They are now counting again. - // The rest will be measured. - for (int j = 0; j < state.range(1); ++j) - data.insert(RandomNumber()); + // ... count Foo,Bar,Baz events } + state.counters["Foo"] = numFoos; + state.counters["Bar"] = numBars; + state.counters["Baz"] = numBazs; } -BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}}); ``` -## Manual timing -For benchmarking something for which neither CPU time nor real-time are -correct or accurate enough, completely manual timing is supported using -the `UseManualTime` function. +The `state.counters` object is a `std::map` with `std::string` keys +and `Counter` values. The latter is a `double`-like class, via an implicit +conversion to `double&`. Thus you can use all of the standard arithmetic +assignment operators (`=,+=,-=,*=,/=`) to change the value of each counter. -When `UseManualTime` is used, the benchmarked code must call -`SetIterationTime` once per iteration of the benchmark loop to -report the manually measured time. +In multithreaded benchmarks, each counter is set on the calling thread only. +When the benchmark finishes, the counters from each thread will be summed; +the resulting sum is the value which will be shown for the benchmark. -An example use case for this is benchmarking GPU execution (e.g. OpenCL -or CUDA kernels, OpenGL or Vulkan or Direct3D draw calls), which cannot -be accurately measured using CPU time or real-time. Instead, they can be -measured accurately using a dedicated API, and these measurement results -can be reported back with `SetIterationTime`. +The `Counter` constructor accepts three parameters: the value as a `double` +; a bit flag which allows you to show counters as rates, and/or as per-thread +iteration, and/or as per-thread averages, and/or iteration invariants, +and/or finally inverting the result; and a flag specifying the 'unit' - i.e. +is 1k a 1000 (default, `benchmark::Counter::OneK::kIs1000`), or 1024 +(`benchmark::Counter::OneK::kIs1024`)? ```c++ -static void BM_ManualTiming(benchmark::State& state) { - int microseconds = state.range(0); - std::chrono::duration sleep_duration { - static_cast(microseconds) - }; + // sets a simple counter + state.counters["Foo"] = numFoos; - for (auto _ : state) { - auto start = std::chrono::high_resolution_clock::now(); - // Simulate some useful workload with a sleep - std::this_thread::sleep_for(sleep_duration); - auto end = std::chrono::high_resolution_clock::now(); + // Set the counter as a rate. It will be presented divided + // by the duration of the benchmark. + // Meaning: per one second, how many 'foo's are processed? + state.counters["FooRate"] = Counter(numFoos, benchmark::Counter::kIsRate); - auto elapsed_seconds = - std::chrono::duration_cast>( - end - start); + // Set the counter as a rate. It will be presented divided + // by the duration of the benchmark, and the result inverted. + // Meaning: how many seconds it takes to process one 'foo'? + state.counters["FooInvRate"] = Counter(numFoos, benchmark::Counter::kIsRate | benchmark::Counter::kInvert); - state.SetIterationTime(elapsed_seconds.count()); - } -} -BENCHMARK(BM_ManualTiming)->Range(1, 1<<17)->UseManualTime(); -``` + // Set the counter as a thread-average quantity. It will + // be presented divided by the number of threads. + state.counters["FooAvg"] = Counter(numFoos, benchmark::Counter::kAvgThreads); -### Preventing optimisation -To prevent a value or expression from being optimized away by the compiler -the `benchmark::DoNotOptimize(...)` and `benchmark::ClobberMemory()` -functions can be used. + // There's also a combined flag: + state.counters["FooAvgRate"] = Counter(numFoos,benchmark::Counter::kAvgThreadsRate); -```c++ -static void BM_test(benchmark::State& state) { - for (auto _ : state) { - int x = 0; - for (int i=0; i < 64; ++i) { - benchmark::DoNotOptimize(x += i); - } - } -} + // This says that we process with the rate of state.range(0) bytes every iteration: + state.counters["BytesProcessed"] = Counter(state.range(0), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::OneK::kIs1024); ``` -`DoNotOptimize()` forces the *result* of `` to be stored in either -memory or a register. For GNU based compilers it acts as read/write barrier +When you're compiling in C++11 mode or later you can use `insert()` with +`std::initializer_list`: + +```c++ + // With C++11, this can be done: + state.counters.insert({{"Foo", numFoos}, {"Bar", numBars}, {"Baz", numBazs}}); + // ... instead of: + state.counters["Foo"] = numFoos; + state.counters["Bar"] = numBars; + state.counters["Baz"] = numBazs; +``` + +#### Counter Reporting + +When using the console reporter, by default, user counters are printed at +the end after the table, the same way as ``bytes_processed`` and +``items_processed``. This is best for cases in which there are few counters, +or where there are only a couple of lines per benchmark. Here's an example of +the default output: + +``` +------------------------------------------------------------------------------ +Benchmark Time CPU Iterations UserCounters... +------------------------------------------------------------------------------ +BM_UserCounter/threads:8 2248 ns 10277 ns 68808 Bar=16 Bat=40 Baz=24 Foo=8 +BM_UserCounter/threads:1 9797 ns 9788 ns 71523 Bar=2 Bat=5 Baz=3 Foo=1024m +BM_UserCounter/threads:2 4924 ns 9842 ns 71036 Bar=4 Bat=10 Baz=6 Foo=2 +BM_UserCounter/threads:4 2589 ns 10284 ns 68012 Bar=8 Bat=20 Baz=12 Foo=4 +BM_UserCounter/threads:8 2212 ns 10287 ns 68040 Bar=16 Bat=40 Baz=24 Foo=8 +BM_UserCounter/threads:16 1782 ns 10278 ns 68144 Bar=32 Bat=80 Baz=48 Foo=16 +BM_UserCounter/threads:32 1291 ns 10296 ns 68256 Bar=64 Bat=160 Baz=96 Foo=32 +BM_UserCounter/threads:4 2615 ns 10307 ns 68040 Bar=8 Bat=20 Baz=12 Foo=4 +BM_Factorial 26 ns 26 ns 26608979 40320 +BM_Factorial/real_time 26 ns 26 ns 26587936 40320 +BM_CalculatePiRange/1 16 ns 16 ns 45704255 0 +BM_CalculatePiRange/8 73 ns 73 ns 9520927 3.28374 +BM_CalculatePiRange/64 609 ns 609 ns 1140647 3.15746 +BM_CalculatePiRange/512 4900 ns 4901 ns 142696 3.14355 +``` + +If this doesn't suit you, you can print each counter as a table column by +passing the flag `--benchmark_counters_tabular=true` to the benchmark +application. This is best for cases in which there are a lot of counters, or +a lot of lines per individual benchmark. Note that this will trigger a +reprinting of the table header any time the counter set changes between +individual benchmarks. Here's an example of corresponding output when +`--benchmark_counters_tabular=true` is passed: + +``` +--------------------------------------------------------------------------------------- +Benchmark Time CPU Iterations Bar Bat Baz Foo +--------------------------------------------------------------------------------------- +BM_UserCounter/threads:8 2198 ns 9953 ns 70688 16 40 24 8 +BM_UserCounter/threads:1 9504 ns 9504 ns 73787 2 5 3 1 +BM_UserCounter/threads:2 4775 ns 9550 ns 72606 4 10 6 2 +BM_UserCounter/threads:4 2508 ns 9951 ns 70332 8 20 12 4 +BM_UserCounter/threads:8 2055 ns 9933 ns 70344 16 40 24 8 +BM_UserCounter/threads:16 1610 ns 9946 ns 70720 32 80 48 16 +BM_UserCounter/threads:32 1192 ns 9948 ns 70496 64 160 96 32 +BM_UserCounter/threads:4 2506 ns 9949 ns 70332 8 20 12 4 +-------------------------------------------------------------- +Benchmark Time CPU Iterations +-------------------------------------------------------------- +BM_Factorial 26 ns 26 ns 26392245 40320 +BM_Factorial/real_time 26 ns 26 ns 26494107 40320 +BM_CalculatePiRange/1 15 ns 15 ns 45571597 0 +BM_CalculatePiRange/8 74 ns 74 ns 9450212 3.28374 +BM_CalculatePiRange/64 595 ns 595 ns 1173901 3.15746 +BM_CalculatePiRange/512 4752 ns 4752 ns 147380 3.14355 +BM_CalculatePiRange/4k 37970 ns 37972 ns 18453 3.14184 +BM_CalculatePiRange/32k 303733 ns 303744 ns 2305 3.14162 +BM_CalculatePiRange/256k 2434095 ns 2434186 ns 288 3.1416 +BM_CalculatePiRange/1024k 9721140 ns 9721413 ns 71 3.14159 +BM_CalculatePi/threads:8 2255 ns 9943 ns 70936 +``` + +Note above the additional header printed when the benchmark changes from +``BM_UserCounter`` to ``BM_Factorial``. This is because ``BM_Factorial`` does +not have the same counter set as ``BM_UserCounter``. + + + +### Multithreaded Benchmarks + +In a multithreaded test (benchmark invoked by multiple threads simultaneously), +it is guaranteed that none of the threads will start until all have reached +the start of the benchmark loop, and all will have finished before any thread +exits the benchmark loop. (This behavior is also provided by the `KeepRunning()` +API) As such, any global setup or teardown can be wrapped in a check against the thread +index: + +```c++ +static void BM_MultiThreaded(benchmark::State& state) { + if (state.thread_index == 0) { + // Setup code here. + } + for (auto _ : state) { + // Run the test as normal. + } + if (state.thread_index == 0) { + // Teardown code here. + } +} +BENCHMARK(BM_MultiThreaded)->Threads(2); +``` + +If the benchmarked code itself uses threads and you want to compare it to +single-threaded code, you may want to use real-time ("wallclock") measurements +for latency comparisons: + +```c++ +BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime(); +``` + +Without `UseRealTime`, CPU time is used by default. + + + +### CPU Timers + +By default, the CPU timer only measures the time spent by the main thread. +If the benchmark itself uses threads internally, this measurement may not +be what you are looking for. Instead, there is a way to measure the total +CPU usage of the process, by all the threads. + +```c++ +void callee(int i); + +static void MyMain(int size) { +#pragma omp parallel for + for(int i = 0; i < size; i++) + callee(i); +} + +static void BM_OpenMP(benchmark::State& state) { + for (auto _ : state) + MyMain(state.range(0)); +} + +// Measure the time spent by the main thread, use it to decide for how long to +// run the benchmark loop. Depending on the internal implementation detail may +// measure to anywhere from near-zero (the overhead spent before/after work +// handoff to worker thread[s]) to the whole single-thread time. +BENCHMARK(BM_OpenMP)->Range(8, 8<<10); + +// Measure the user-visible time, the wall clock (literally, the time that +// has passed on the clock on the wall), use it to decide for how long to +// run the benchmark loop. This will always be meaningful, an will match the +// time spent by the main thread in single-threaded case, in general decreasing +// with the number of internal threads doing the work. +BENCHMARK(BM_OpenMP)->Range(8, 8<<10)->UseRealTime(); + +// Measure the total CPU consumption, use it to decide for how long to +// run the benchmark loop. This will always measure to no less than the +// time spent by the main thread in single-threaded case. +BENCHMARK(BM_OpenMP)->Range(8, 8<<10)->MeasureProcessCPUTime(); + +// A mixture of the last two. Measure the total CPU consumption, but use the +// wall clock to decide for how long to run the benchmark loop. +BENCHMARK(BM_OpenMP)->Range(8, 8<<10)->MeasureProcessCPUTime()->UseRealTime(); +``` + +#### Controlling Timers + +Normally, the entire duration of the work loop (`for (auto _ : state) {}`) +is measured. But sometimes, it is necessary to do some work inside of +that loop, every iteration, but without counting that time to the benchmark time. +That is possible, although it is not recommended, since it has high overhead. + +```c++ +static void BM_SetInsert_With_Timer_Control(benchmark::State& state) { + std::set data; + for (auto _ : state) { + state.PauseTiming(); // Stop timers. They will not count until they are resumed. + data = ConstructRandomSet(state.range(0)); // Do something that should not be measured + state.ResumeTiming(); // And resume timers. They are now counting again. + // The rest will be measured. + for (int j = 0; j < state.range(1); ++j) + data.insert(RandomNumber()); + } +} +BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}}); +``` + + + +### Manual Timing + +For benchmarking something for which neither CPU time nor real-time are +correct or accurate enough, completely manual timing is supported using +the `UseManualTime` function. + +When `UseManualTime` is used, the benchmarked code must call +`SetIterationTime` once per iteration of the benchmark loop to +report the manually measured time. + +An example use case for this is benchmarking GPU execution (e.g. OpenCL +or CUDA kernels, OpenGL or Vulkan or Direct3D draw calls), which cannot +be accurately measured using CPU time or real-time. Instead, they can be +measured accurately using a dedicated API, and these measurement results +can be reported back with `SetIterationTime`. + +```c++ +static void BM_ManualTiming(benchmark::State& state) { + int microseconds = state.range(0); + std::chrono::duration sleep_duration { + static_cast(microseconds) + }; + + for (auto _ : state) { + auto start = std::chrono::high_resolution_clock::now(); + // Simulate some useful workload with a sleep + std::this_thread::sleep_for(sleep_duration); + auto end = std::chrono::high_resolution_clock::now(); + + auto elapsed_seconds = + std::chrono::duration_cast>( + end - start); + + state.SetIterationTime(elapsed_seconds.count()); + } +} +BENCHMARK(BM_ManualTiming)->Range(1, 1<<17)->UseManualTime(); +``` + + + +### Setting the Time Unit + +If a benchmark runs a few milliseconds it may be hard to visually compare the +measured times, since the output data is given in nanoseconds per default. In +order to manually set the time unit, you can specify it manually: + +```c++ +BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); +``` + + + +### Preventing Optimization + +To prevent a value or expression from being optimized away by the compiler +the `benchmark::DoNotOptimize(...)` and `benchmark::ClobberMemory()` +functions can be used. + +```c++ +static void BM_test(benchmark::State& state) { + for (auto _ : state) { + int x = 0; + for (int i=0; i < 64; ++i) { + benchmark::DoNotOptimize(x += i); + } + } +} +``` + +`DoNotOptimize()` forces the *result* of `` to be stored in either +memory or a register. For GNU based compilers it acts as read/write barrier for global memory. More specifically it forces the compiler to flush pending writes to memory and reload any other values as necessary. @@ -545,16 +1164,10 @@ static void BM_vector_push_back(benchmark::State& state) { Note that `ClobberMemory()` is only available for GNU or MSVC based compilers. -### Set time unit manually -If a benchmark runs a few milliseconds it may be hard to visually compare the -measured times, since the output data is given in nanoseconds per default. In -order to manually set the time unit, you can specify it manually: + -```c++ -BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); -``` +### Statistics: Reporting the Mean, Median and Standard Deviation of Repeated Benchmarks -### Reporting the mean, median and standard deviation by repeated benchmarks By default each benchmark is run once and that single result is reported. However benchmarks are often noisy and a single result may not be representative of the overall behavior. For this reason it's possible to repeatedly rerun the @@ -580,10 +1193,13 @@ Calling `ReportAggregatesOnly(bool)` / `DisplayAggregatesOnly(bool)` on a registered benchmark object overrides the value of the appropriate flag for that benchmark. -## User-defined statistics for repeated benchmarks + + +### Custom Statistics + While having mean, median and standard deviation is nice, this may not be -enough for everyone. For example you may want to know what is the largest -observation, e.g. because you have some real-time constraints. This is easy. +enough for everyone. For example you may want to know what the largest +observation is, e.g. because you have some real-time constraints. This is easy. The following code will specify a custom statistic to be calculated, defined by a lambda function. @@ -603,194 +1219,39 @@ BENCHMARK(BM_spin_empty) ->Arg(512); ``` -## Fixtures -Fixture tests are created by -first defining a type that derives from `::benchmark::Fixture` and then -creating/registering the tests using the following macros: + -* `BENCHMARK_F(ClassName, Method)` -* `BENCHMARK_DEFINE_F(ClassName, Method)` -* `BENCHMARK_REGISTER_F(ClassName, Method)` +### Using RegisterBenchmark(name, fn, args...) -For Example: +The `RegisterBenchmark(name, func, args...)` function provides an alternative +way to create and register benchmarks. +`RegisterBenchmark(name, func, args...)` creates, registers, and returns a +pointer to a new benchmark with the specified `name` that invokes +`func(st, args...)` where `st` is a `benchmark::State` object. -```c++ -class MyFixture : public benchmark::Fixture {}; +Unlike the `BENCHMARK` registration macros, which can only be used at the global +scope, the `RegisterBenchmark` can be called anywhere. This allows for +benchmark tests to be registered programmatically. -BENCHMARK_F(MyFixture, FooTest)(benchmark::State& st) { - for (auto _ : st) { - ... - } -} +Additionally `RegisterBenchmark` allows any callable object to be registered +as a benchmark. Including capturing lambdas and function objects. -BENCHMARK_DEFINE_F(MyFixture, BarTest)(benchmark::State& st) { - for (auto _ : st) { - ... - } +For Example: +```c++ +auto BM_test = [](benchmark::State& st, auto Inputs) { /* ... */ }; + +int main(int argc, char** argv) { + for (auto& test_input : { /* ... */ }) + benchmark::RegisterBenchmark(test_input.name(), BM_test, test_input); + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); } -/* BarTest is NOT registered */ -BENCHMARK_REGISTER_F(MyFixture, BarTest)->Threads(2); -/* BarTest is now registered */ ``` -### Templated fixtures -Also you can create templated fixture by using the following macros: + -* `BENCHMARK_TEMPLATE_F(ClassName, Method, ...)` -* `BENCHMARK_TEMPLATE_DEFINE_F(ClassName, Method, ...)` - -For example: -```c++ -template -class MyFixture : public benchmark::Fixture {}; - -BENCHMARK_TEMPLATE_F(MyFixture, IntTest, int)(benchmark::State& st) { - for (auto _ : st) { - ... - } -} - -BENCHMARK_TEMPLATE_DEFINE_F(MyFixture, DoubleTest, double)(benchmark::State& st) { - for (auto _ : st) { - ... - } -} - -BENCHMARK_REGISTER_F(MyFixture, DoubleTest)->Threads(2); -``` - -## User-defined counters - -You can add your own counters with user-defined names. The example below -will add columns "Foo", "Bar" and "Baz" in its output: - -```c++ -static void UserCountersExample1(benchmark::State& state) { - double numFoos = 0, numBars = 0, numBazs = 0; - for (auto _ : state) { - // ... count Foo,Bar,Baz events - } - state.counters["Foo"] = numFoos; - state.counters["Bar"] = numBars; - state.counters["Baz"] = numBazs; -} -``` - -The `state.counters` object is a `std::map` with `std::string` keys -and `Counter` values. The latter is a `double`-like class, via an implicit -conversion to `double&`. Thus you can use all of the standard arithmetic -assignment operators (`=,+=,-=,*=,/=`) to change the value of each counter. - -In multithreaded benchmarks, each counter is set on the calling thread only. -When the benchmark finishes, the counters from each thread will be summed; -the resulting sum is the value which will be shown for the benchmark. - -The `Counter` constructor accepts three parameters: the value as a `double` -; a bit flag which allows you to show counters as rates, and/or as per-thread -iteration, and/or as per-thread averages, and/or iteration invariants; -and a flag specifying the 'unit' - i.e. is 1k a 1000 (default, -`benchmark::Counter::OneK::kIs1000`), or 1024 -(`benchmark::Counter::OneK::kIs1024`)? - -```c++ - // sets a simple counter - state.counters["Foo"] = numFoos; - - // Set the counter as a rate. It will be presented divided - // by the duration of the benchmark. - state.counters["FooRate"] = Counter(numFoos, benchmark::Counter::kIsRate); - - // Set the counter as a thread-average quantity. It will - // be presented divided by the number of threads. - state.counters["FooAvg"] = Counter(numFoos, benchmark::Counter::kAvgThreads); - - // There's also a combined flag: - state.counters["FooAvgRate"] = Counter(numFoos,benchmark::Counter::kAvgThreadsRate); - - // This says that we process with the rate of state.range(0) bytes every iteration: - state.counters["BytesProcessed"] = Counter(state.range(0), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::OneK::kIs1024); -``` - -When you're compiling in C++11 mode or later you can use `insert()` with -`std::initializer_list`: - -```c++ - // With C++11, this can be done: - state.counters.insert({{"Foo", numFoos}, {"Bar", numBars}, {"Baz", numBazs}}); - // ... instead of: - state.counters["Foo"] = numFoos; - state.counters["Bar"] = numBars; - state.counters["Baz"] = numBazs; -``` - -### Counter reporting - -When using the console reporter, by default, user counters are are printed at -the end after the table, the same way as ``bytes_processed`` and -``items_processed``. This is best for cases in which there are few counters, -or where there are only a couple of lines per benchmark. Here's an example of -the default output: - -``` ------------------------------------------------------------------------------- -Benchmark Time CPU Iterations UserCounters... ------------------------------------------------------------------------------- -BM_UserCounter/threads:8 2248 ns 10277 ns 68808 Bar=16 Bat=40 Baz=24 Foo=8 -BM_UserCounter/threads:1 9797 ns 9788 ns 71523 Bar=2 Bat=5 Baz=3 Foo=1024m -BM_UserCounter/threads:2 4924 ns 9842 ns 71036 Bar=4 Bat=10 Baz=6 Foo=2 -BM_UserCounter/threads:4 2589 ns 10284 ns 68012 Bar=8 Bat=20 Baz=12 Foo=4 -BM_UserCounter/threads:8 2212 ns 10287 ns 68040 Bar=16 Bat=40 Baz=24 Foo=8 -BM_UserCounter/threads:16 1782 ns 10278 ns 68144 Bar=32 Bat=80 Baz=48 Foo=16 -BM_UserCounter/threads:32 1291 ns 10296 ns 68256 Bar=64 Bat=160 Baz=96 Foo=32 -BM_UserCounter/threads:4 2615 ns 10307 ns 68040 Bar=8 Bat=20 Baz=12 Foo=4 -BM_Factorial 26 ns 26 ns 26608979 40320 -BM_Factorial/real_time 26 ns 26 ns 26587936 40320 -BM_CalculatePiRange/1 16 ns 16 ns 45704255 0 -BM_CalculatePiRange/8 73 ns 73 ns 9520927 3.28374 -BM_CalculatePiRange/64 609 ns 609 ns 1140647 3.15746 -BM_CalculatePiRange/512 4900 ns 4901 ns 142696 3.14355 -``` - -If this doesn't suit you, you can print each counter as a table column by -passing the flag `--benchmark_counters_tabular=true` to the benchmark -application. This is best for cases in which there are a lot of counters, or -a lot of lines per individual benchmark. Note that this will trigger a -reprinting of the table header any time the counter set changes between -individual benchmarks. Here's an example of corresponding output when -`--benchmark_counters_tabular=true` is passed: - -``` ---------------------------------------------------------------------------------------- -Benchmark Time CPU Iterations Bar Bat Baz Foo ---------------------------------------------------------------------------------------- -BM_UserCounter/threads:8 2198 ns 9953 ns 70688 16 40 24 8 -BM_UserCounter/threads:1 9504 ns 9504 ns 73787 2 5 3 1 -BM_UserCounter/threads:2 4775 ns 9550 ns 72606 4 10 6 2 -BM_UserCounter/threads:4 2508 ns 9951 ns 70332 8 20 12 4 -BM_UserCounter/threads:8 2055 ns 9933 ns 70344 16 40 24 8 -BM_UserCounter/threads:16 1610 ns 9946 ns 70720 32 80 48 16 -BM_UserCounter/threads:32 1192 ns 9948 ns 70496 64 160 96 32 -BM_UserCounter/threads:4 2506 ns 9949 ns 70332 8 20 12 4 --------------------------------------------------------------- -Benchmark Time CPU Iterations --------------------------------------------------------------- -BM_Factorial 26 ns 26 ns 26392245 40320 -BM_Factorial/real_time 26 ns 26 ns 26494107 40320 -BM_CalculatePiRange/1 15 ns 15 ns 45571597 0 -BM_CalculatePiRange/8 74 ns 74 ns 9450212 3.28374 -BM_CalculatePiRange/64 595 ns 595 ns 1173901 3.15746 -BM_CalculatePiRange/512 4752 ns 4752 ns 147380 3.14355 -BM_CalculatePiRange/4k 37970 ns 37972 ns 18453 3.14184 -BM_CalculatePiRange/32k 303733 ns 303744 ns 2305 3.14162 -BM_CalculatePiRange/256k 2434095 ns 2434186 ns 288 3.1416 -BM_CalculatePiRange/1024k 9721140 ns 9721413 ns 71 3.14159 -BM_CalculatePi/threads:8 2255 ns 9943 ns 70936 -``` -Note above the additional header printed when the benchmark changes from -``BM_UserCounter`` to ``BM_Factorial``. This is because ``BM_Factorial`` does -not have the same counter set as ``BM_UserCounter``. - -## Exiting Benchmarks in Error +### Exiting with an Error When errors caused by external influences, such as file I/O and network communication, occur within a benchmark the @@ -801,7 +1262,9 @@ Users must explicitly exit the loop, otherwise all iterations will be performed. Users may explicitly return to exit the benchmark immediately. The `SkipWithError(...)` function may be used at any point within the benchmark, -including before and after the benchmark loop. +including before and after the benchmark loop. Moreover, if `SkipWithError(...)` +has been used, it is not required to reach the benchmark loop and one may return +from the benchmark function early. For example: @@ -809,188 +1272,105 @@ For example: static void BM_test(benchmark::State& state) { auto resource = GetResource(); if (!resource.good()) { - state.SkipWithError("Resource is not good!"); - // KeepRunning() loop will not be entered. + state.SkipWithError("Resource is not good!"); + // KeepRunning() loop will not be entered. } - for (state.KeepRunning()) { - auto data = resource.read_data(); - if (!resource.good()) { - state.SkipWithError("Failed to read data!"); - break; // Needed to skip the rest of the iteration. - } - do_stuff(data); + while (state.KeepRunning()) { + auto data = resource.read_data(); + if (!resource.good()) { + state.SkipWithError("Failed to read data!"); + break; // Needed to skip the rest of the iteration. + } + do_stuff(data); } } static void BM_test_ranged_fo(benchmark::State & state) { - state.SkipWithError("test will not be entered"); + auto resource = GetResource(); + if (!resource.good()) { + state.SkipWithError("Resource is not good!"); + return; // Early return is allowed when SkipWithError() has been used. + } for (auto _ : state) { - state.SkipWithError("Failed!"); - break; // REQUIRED to prevent all further iterations. + auto data = resource.read_data(); + if (!resource.good()) { + state.SkipWithError("Failed to read data!"); + break; // REQUIRED to prevent all further iterations. + } + do_stuff(data); } } ``` + -## Running a subset of the benchmarks - -The `--benchmark_filter=` option can be used to only run the benchmarks -which match the specified ``. For example: +### A Faster KeepRunning Loop -```bash -$ ./run_benchmarks.x --benchmark_filter=BM_memcpy/32 -Run on (1 X 2300 MHz CPU ) -2016-06-25 19:34:24 -Benchmark Time CPU Iterations ----------------------------------------------------- -BM_memcpy/32 11 ns 11 ns 79545455 -BM_memcpy/32k 2181 ns 2185 ns 324074 -BM_memcpy/32 12 ns 12 ns 54687500 -BM_memcpy/32k 1834 ns 1837 ns 357143 -``` - -## Runtime and reporting considerations -When the benchmark binary is executed, each benchmark function is run serially. -The number of iterations to run is determined dynamically by running the -benchmark a few times and measuring the time taken and ensuring that the -ultimate result will be statistically stable. As such, faster benchmark -functions will be run for more iterations than slower benchmark functions, and -the number of iterations is thus reported. - -In all cases, the number of iterations for which the benchmark is run is -governed by the amount of time the benchmark takes. Concretely, the number of -iterations is at least one, not more than 1e9, until CPU time is greater than -the minimum time, or the wallclock time is 5x minimum time. The minimum time is -set per benchmark by calling `MinTime` on the registered benchmark object. - -Average timings are then reported over the iterations run. If multiple -repetitions are requested using the `--benchmark_repetitions` command-line -option, or at registration time, the benchmark function will be run several -times and statistical results across these repetitions will also be reported. - -As well as the per-benchmark entries, a preamble in the report will include -information about the machine on which the benchmarks are run. - -### Output Formats -The library supports multiple output formats. Use the -`--benchmark_format=` flag to set the format type. `console` -is the default format. - -The Console format is intended to be a human readable format. By default -the format generates color output. Context is output on stderr and the -tabular data on stdout. Example tabular output looks like: -``` -Benchmark Time(ns) CPU(ns) Iterations ----------------------------------------------------------------------- -BM_SetInsert/1024/1 28928 29349 23853 133.097kB/s 33.2742k items/s -BM_SetInsert/1024/8 32065 32913 21375 949.487kB/s 237.372k items/s -BM_SetInsert/1024/10 33157 33648 21431 1.13369MB/s 290.225k items/s -``` +In C++11 mode, a ranged-based for loop should be used in preference to +the `KeepRunning` loop for running the benchmarks. For example: -The JSON format outputs human readable json split into two top level attributes. -The `context` attribute contains information about the run in general, including -information about the CPU and the date. -The `benchmarks` attribute contains a list of every benchmark run. Example json -output looks like: -```json -{ - "context": { - "date": "2015/03/17-18:40:25", - "num_cpus": 40, - "mhz_per_cpu": 2801, - "cpu_scaling_enabled": false, - "build_type": "debug" - }, - "benchmarks": [ - { - "name": "BM_SetInsert/1024/1", - "iterations": 94877, - "real_time": 29275, - "cpu_time": 29836, - "bytes_per_second": 134066, - "items_per_second": 33516 - }, - { - "name": "BM_SetInsert/1024/8", - "iterations": 21609, - "real_time": 32317, - "cpu_time": 32429, - "bytes_per_second": 986770, - "items_per_second": 246693 - }, - { - "name": "BM_SetInsert/1024/10", - "iterations": 21393, - "real_time": 32724, - "cpu_time": 33355, - "bytes_per_second": 1199226, - "items_per_second": 299807 - } - ] +```c++ +static void BM_Fast(benchmark::State &state) { + for (auto _ : state) { + FastOperation(); + } } +BENCHMARK(BM_Fast); ``` -The CSV format outputs comma-separated values. The `context` is output on stderr -and the CSV itself on stdout. Example CSV output looks like: -``` -name,iterations,real_time,cpu_time,bytes_per_second,items_per_second,label -"BM_SetInsert/1024/1",65465,17890.7,8407.45,475768,118942, -"BM_SetInsert/1024/8",116606,18810.1,9766.64,3.27646e+06,819115, -"BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06, -``` - -### Output Files -The library supports writing the output of the benchmark to a file specified -by `--benchmark_out=`. The format of the output can be specified -using `--benchmark_out_format={json|console|csv}`. Specifying -`--benchmark_out` does not suppress the console output. - -## Result comparison - -It is possible to compare the benchmarking results. See [Additional Tooling Documentation](docs/tools.md) +The reason the ranged-for loop is faster than using `KeepRunning`, is +because `KeepRunning` requires a memory load and store of the iteration count +ever iteration, whereas the ranged-for variant is able to keep the iteration count +in a register. -## Debug vs Release -By default, benchmark builds as a debug library. You will see a warning in the -output when this is the case. To build it as a release library instead, use: +For example, an empty inner loop of using the ranged-based for method looks like: -``` -cmake -DCMAKE_BUILD_TYPE=Release +```asm +# Loop Init + mov rbx, qword ptr [r14 + 104] + call benchmark::State::StartKeepRunning() + test rbx, rbx + je .LoopEnd +.LoopHeader: # =>This Inner Loop Header: Depth=1 + add rbx, -1 + jne .LoopHeader +.LoopEnd: ``` -To enable link-time optimisation, use +Compared to an empty `KeepRunning` loop, which looks like: +```asm +.LoopHeader: # in Loop: Header=BB0_3 Depth=1 + cmp byte ptr [rbx], 1 + jne .LoopInit +.LoopBody: # =>This Inner Loop Header: Depth=1 + mov rax, qword ptr [rbx + 8] + lea rcx, [rax + 1] + mov qword ptr [rbx + 8], rcx + cmp rax, qword ptr [rbx + 104] + jb .LoopHeader + jmp .LoopEnd +.LoopInit: + mov rdi, rbx + call benchmark::State::StartKeepRunning() + jmp .LoopBody +.LoopEnd: ``` -cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_LTO=true -``` - -If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake -cache variables, if autodetection fails. - -If you are using clang, you may need to set `LLVMAR_EXECUTABLE`, -`LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables. - -## Compiler Support -Google Benchmark uses C++11 when building the library. As such we require -a modern C++ toolchain, both compiler and standard library. - -The following minimum versions are strongly recommended build the library: - -* GCC 4.8 -* Clang 3.4 -* Visual Studio 2013 -* Intel 2015 Update 1 +Unless C++03 compatibility is required, the ranged-for variant of writing +the benchmark loop should be preferred. -Anything older *may* work. + -Note: Using the library and its headers in C++03 is supported. C++11 is only -required to build the library. +### Disabling CPU Frequency Scaling -## Disable CPU frequency scaling If you see this error: + ``` ***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead. ``` + you might want to disable the CPU frequency scaling while running the benchmark: + ```bash sudo cpupower frequency-set --governor performance ./mybench diff --git a/libcxx/utils/google-benchmark/WORKSPACE b/libcxx/utils/google-benchmark/WORKSPACE index 54734f1ea55e7..631f3ba05de53 100644 --- a/libcxx/utils/google-benchmark/WORKSPACE +++ b/libcxx/utils/google-benchmark/WORKSPACE @@ -1,7 +1,51 @@ workspace(name = "com_github_google_benchmark") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "rules_cc", + strip_prefix = "rules_cc-a508235df92e71d537fcbae0c7c952ea6957a912", + urls = ["https://github.com/bazelbuild/rules_cc/archive/a508235df92e71d537fcbae0c7c952ea6957a912.zip"], + sha256 = "d7dc12c1d5bc1a87474de8e3d17b7731a4dcebcfb8aa3990fe8ac7734ef12f2f", +) + +http_archive( + name = "com_google_absl", + sha256 = "f41868f7a938605c92936230081175d1eae87f6ea2c248f41077c8f88316f111", + strip_prefix = "abseil-cpp-20200225.2", + urls = ["https://github.com/abseil/abseil-cpp/archive/20200225.2.tar.gz"], +) + +http_archive( + name = "com_google_googletest", + strip_prefix = "googletest-3f0cf6b62ad1eb50d8736538363d3580dd640c3e", + urls = ["https://github.com/google/googletest/archive/3f0cf6b62ad1eb50d8736538363d3580dd640c3e.zip"], + sha256 = "8f827dd550db8b4fdf73904690df0be9fccc161017c9038a724bc9a0617a1bc8", +) + http_archive( - name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/3f0cf6b62ad1eb50d8736538363d3580dd640c3e.zip"], - strip_prefix = "googletest-3f0cf6b62ad1eb50d8736538363d3580dd640c3e", + name = "pybind11", + build_file = "@//bindings/python:pybind11.BUILD", + sha256 = "1eed57bc6863190e35637290f97a20c81cfe4d9090ac0a24f3bbf08f265eb71d", + strip_prefix = "pybind11-2.4.3", + urls = ["https://github.com/pybind/pybind11/archive/v2.4.3.tar.gz"], +) + +new_local_repository( + name = "python_headers", + build_file = "@//bindings/python:python_headers.BUILD", + path = "/usr/include/python3.6", # May be overwritten by setup.py. +) + +http_archive( + name = "rules_python", + url = "https://github.com/bazelbuild/rules_python/releases/download/0.1.0/rules_python-0.1.0.tar.gz", + sha256 = "b6d46438523a3ec0f3cead544190ee13223a52f6a6765a29eae7b7cc24cc83a0", +) + +load("@rules_python//python:pip.bzl", pip3_install="pip_install") + +pip3_install( + name = "py_deps", + requirements = "//:requirements.txt", ) diff --git a/libcxx/utils/google-benchmark/_config.yml b/libcxx/utils/google-benchmark/_config.yml new file mode 100644 index 0000000000000..1fa5ff852bda8 --- /dev/null +++ b/libcxx/utils/google-benchmark/_config.yml @@ -0,0 +1,2 @@ +theme: jekyll-theme-midnight +markdown: GFM diff --git a/libcxx/utils/google-benchmark/appveyor.yml b/libcxx/utils/google-benchmark/appveyor.yml index cf240190bea64..81da955f02815 100644 --- a/libcxx/utils/google-benchmark/appveyor.yml +++ b/libcxx/utils/google-benchmark/appveyor.yml @@ -41,7 +41,7 @@ build_script: - cmake --build . --config %configuration% test_script: - - ctest -c %configuration% --timeout 300 --output-on-failure + - ctest --build-config %configuration% --timeout 300 --output-on-failure artifacts: - path: '_build/CMakeFiles/*.log' diff --git a/libcxx/utils/google-benchmark/bindings/python/BUILD b/libcxx/utils/google-benchmark/bindings/python/BUILD new file mode 100644 index 0000000000000..9559a76b30a95 --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/BUILD @@ -0,0 +1,3 @@ +exports_files(glob(["*.BUILD"])) +exports_files(["build_defs.bzl"]) + diff --git a/libcxx/utils/google-benchmark/bindings/python/build_defs.bzl b/libcxx/utils/google-benchmark/bindings/python/build_defs.bzl new file mode 100644 index 0000000000000..45907aaa5e2d8 --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/build_defs.bzl @@ -0,0 +1,25 @@ +_SHARED_LIB_SUFFIX = { + "//conditions:default": ".so", + "//:windows": ".dll", +} + +def py_extension(name, srcs, hdrs = [], copts = [], features = [], deps = []): + for shared_lib_suffix in _SHARED_LIB_SUFFIX.values(): + shared_lib_name = name + shared_lib_suffix + native.cc_binary( + name = shared_lib_name, + linkshared = 1, + linkstatic = 1, + srcs = srcs + hdrs, + copts = copts, + features = features, + deps = deps, + ) + + return native.py_library( + name = name, + data = select({ + platform: [name + shared_lib_suffix] + for platform, shared_lib_suffix in _SHARED_LIB_SUFFIX.items() + }), + ) diff --git a/libcxx/utils/google-benchmark/bindings/python/google_benchmark/BUILD b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/BUILD new file mode 100644 index 0000000000000..3c1561f48eeed --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/BUILD @@ -0,0 +1,38 @@ +load("//bindings/python:build_defs.bzl", "py_extension") + +py_library( + name = "google_benchmark", + srcs = ["__init__.py"], + visibility = ["//visibility:public"], + deps = [ + ":_benchmark", + # pip; absl:app + ], +) + +py_extension( + name = "_benchmark", + srcs = ["benchmark.cc"], + copts = [ + "-fexceptions", + "-fno-strict-aliasing", + ], + features = ["-use_header_modules"], + deps = [ + "//:benchmark", + "@pybind11", + "@python_headers", + ], +) + +py_test( + name = "example", + srcs = ["example.py"], + python_version = "PY3", + srcs_version = "PY3", + visibility = ["//visibility:public"], + deps = [ + ":google_benchmark", + ], +) + diff --git a/libcxx/utils/google-benchmark/bindings/python/google_benchmark/__init__.py b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/__init__.py new file mode 100644 index 0000000000000..1055bf2418569 --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/__init__.py @@ -0,0 +1,158 @@ +# Copyright 2020 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Python benchmarking utilities. + +Example usage: + import google_benchmark as benchmark + + @benchmark.register + def my_benchmark(state): + ... # Code executed outside `while` loop is not timed. + + while state: + ... # Code executed within `while` loop is timed. + + if __name__ == '__main__': + benchmark.main() +""" + +from absl import app +from google_benchmark import _benchmark +from google_benchmark._benchmark import ( + Counter, + kNanosecond, + kMicrosecond, + kMillisecond, + kSecond, + oNone, + o1, + oN, + oNSquared, + oNCubed, + oLogN, + oNLogN, + oAuto, + oLambda, +) + + +__all__ = [ + "register", + "main", + "Counter", + "kNanosecond", + "kMicrosecond", + "kMillisecond", + "kSecond", + "oNone", + "o1", + "oN", + "oNSquared", + "oNCubed", + "oLogN", + "oNLogN", + "oAuto", + "oLambda", +] + +__version__ = "0.2.0" + + +class __OptionMaker: + """A stateless class to collect benchmark options. + + Collect all decorator calls like @option.range(start=0, limit=1<<5). + """ + + class Options: + """Pure data class to store options calls, along with the benchmarked function.""" + + def __init__(self, func): + self.func = func + self.builder_calls = [] + + @classmethod + def make(cls, func_or_options): + """Make Options from Options or the benchmarked function.""" + if isinstance(func_or_options, cls.Options): + return func_or_options + return cls.Options(func_or_options) + + def __getattr__(self, builder_name): + """Append option call in the Options.""" + + # The function that get returned on @option.range(start=0, limit=1<<5). + def __builder_method(*args, **kwargs): + + # The decorator that get called, either with the benchmared function + # or the previous Options + def __decorator(func_or_options): + options = self.make(func_or_options) + options.builder_calls.append((builder_name, args, kwargs)) + # The decorator returns Options so it is not technically a decorator + # and needs a final call to @regiser + return options + + return __decorator + + return __builder_method + + +# Alias for nicer API. +# We have to instantiate an object, even if stateless, to be able to use __getattr__ +# on option.range +option = __OptionMaker() + + +def register(undefined=None, *, name=None): + """Register function for benchmarking.""" + if undefined is None: + # Decorator is called without parenthesis so we return a decorator + return lambda f: register(f, name=name) + + # We have either the function to benchmark (simple case) or an instance of Options + # (@option._ case). + options = __OptionMaker.make(undefined) + + if name is None: + name = options.func.__name__ + + # We register the benchmark and reproduce all the @option._ calls onto the + # benchmark builder pattern + benchmark = _benchmark.RegisterBenchmark(name, options.func) + for name, args, kwargs in options.builder_calls[::-1]: + getattr(benchmark, name)(*args, **kwargs) + + # return the benchmarked function because the decorator does not modify it + return options.func + + +def _flags_parser(argv): + argv = _benchmark.Initialize(argv) + return app.parse_flags_with_usage(argv) + + +def _run_benchmarks(argv): + if len(argv) > 1: + raise app.UsageError("Too many command-line arguments.") + return _benchmark.RunSpecifiedBenchmarks() + + +def main(argv=None): + return app.run(_run_benchmarks, argv=argv, flags_parser=_flags_parser) + + +# Methods for use with custom main function. +initialize = _benchmark.Initialize +run_benchmarks = _benchmark.RunSpecifiedBenchmarks diff --git a/libcxx/utils/google-benchmark/bindings/python/google_benchmark/benchmark.cc b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/benchmark.cc new file mode 100644 index 0000000000000..1b01fe7f7f0f7 --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/benchmark.cc @@ -0,0 +1,181 @@ +// Benchmark for Python. + +#include +#include +#include + +#include "pybind11/operators.h" +#include "pybind11/pybind11.h" +#include "pybind11/stl.h" +#include "pybind11/stl_bind.h" + +#include "benchmark/benchmark.h" + +PYBIND11_MAKE_OPAQUE(benchmark::UserCounters); + +namespace { +namespace py = ::pybind11; + +std::vector Initialize(const std::vector& argv) { + // The `argv` pointers here become invalid when this function returns, but + // benchmark holds the pointer to `argv[0]`. We create a static copy of it + // so it persists, and replace the pointer below. + static std::string executable_name(argv[0]); + std::vector ptrs; + ptrs.reserve(argv.size()); + for (auto& arg : argv) { + ptrs.push_back(const_cast(arg.c_str())); + } + ptrs[0] = const_cast(executable_name.c_str()); + int argc = static_cast(argv.size()); + benchmark::Initialize(&argc, ptrs.data()); + std::vector remaining_argv; + remaining_argv.reserve(argc); + for (int i = 0; i < argc; ++i) { + remaining_argv.emplace_back(ptrs[i]); + } + return remaining_argv; +} + +benchmark::internal::Benchmark* RegisterBenchmark(const char* name, + py::function f) { + return benchmark::RegisterBenchmark( + name, [f](benchmark::State& state) { f(&state); }); +} + +PYBIND11_MODULE(_benchmark, m) { + using benchmark::TimeUnit; + py::enum_(m, "TimeUnit") + .value("kNanosecond", TimeUnit::kNanosecond) + .value("kMicrosecond", TimeUnit::kMicrosecond) + .value("kMillisecond", TimeUnit::kMillisecond) + .value("kSecond", TimeUnit::kSecond) + .export_values(); + + using benchmark::BigO; + py::enum_(m, "BigO") + .value("oNone", BigO::oNone) + .value("o1", BigO::o1) + .value("oN", BigO::oN) + .value("oNSquared", BigO::oNSquared) + .value("oNCubed", BigO::oNCubed) + .value("oLogN", BigO::oLogN) + .value("oNLogN", BigO::oLogN) + .value("oAuto", BigO::oAuto) + .value("oLambda", BigO::oLambda) + .export_values(); + + using benchmark::internal::Benchmark; + py::class_(m, "Benchmark") + // For methods returning a pointer tor the current object, reference + // return policy is used to ask pybind not to take ownership oof the + // returned object and avoid calling delete on it. + // https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies + // + // For methods taking a const std::vector<...>&, a copy is created + // because a it is bound to a Python list. + // https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html + .def("unit", &Benchmark::Unit, py::return_value_policy::reference) + .def("arg", &Benchmark::Arg, py::return_value_policy::reference) + .def("args", &Benchmark::Args, py::return_value_policy::reference) + .def("range", &Benchmark::Range, py::return_value_policy::reference, + py::arg("start"), py::arg("limit")) + .def("dense_range", &Benchmark::DenseRange, + py::return_value_policy::reference, py::arg("start"), + py::arg("limit"), py::arg("step") = 1) + .def("ranges", &Benchmark::Ranges, py::return_value_policy::reference) + .def("args_product", &Benchmark::ArgsProduct, + py::return_value_policy::reference) + .def("arg_name", &Benchmark::ArgName, py::return_value_policy::reference) + .def("arg_names", &Benchmark::ArgNames, + py::return_value_policy::reference) + .def("range_pair", &Benchmark::RangePair, + py::return_value_policy::reference, py::arg("lo1"), py::arg("hi1"), + py::arg("lo2"), py::arg("hi2")) + .def("range_multiplier", &Benchmark::RangeMultiplier, + py::return_value_policy::reference) + .def("min_time", &Benchmark::MinTime, py::return_value_policy::reference) + .def("iterations", &Benchmark::Iterations, + py::return_value_policy::reference) + .def("repetitions", &Benchmark::Repetitions, + py::return_value_policy::reference) + .def("report_aggregates_only", &Benchmark::ReportAggregatesOnly, + py::return_value_policy::reference, py::arg("value") = true) + .def("display_aggregates_only", &Benchmark::DisplayAggregatesOnly, + py::return_value_policy::reference, py::arg("value") = true) + .def("measure_process_cpu_time", &Benchmark::MeasureProcessCPUTime, + py::return_value_policy::reference) + .def("use_real_time", &Benchmark::UseRealTime, + py::return_value_policy::reference) + .def("use_manual_time", &Benchmark::UseManualTime, + py::return_value_policy::reference) + .def( + "complexity", + (Benchmark * (Benchmark::*)(benchmark::BigO)) & Benchmark::Complexity, + py::return_value_policy::reference, + py::arg("complexity") = benchmark::oAuto); + + using benchmark::Counter; + py::class_ py_counter(m, "Counter"); + + py::enum_(py_counter, "Flags") + .value("kDefaults", Counter::Flags::kDefaults) + .value("kIsRate", Counter::Flags::kIsRate) + .value("kAvgThreads", Counter::Flags::kAvgThreads) + .value("kAvgThreadsRate", Counter::Flags::kAvgThreadsRate) + .value("kIsIterationInvariant", Counter::Flags::kIsIterationInvariant) + .value("kIsIterationInvariantRate", + Counter::Flags::kIsIterationInvariantRate) + .value("kAvgIterations", Counter::Flags::kAvgIterations) + .value("kAvgIterationsRate", Counter::Flags::kAvgIterationsRate) + .value("kInvert", Counter::Flags::kInvert) + .export_values() + .def(py::self | py::self); + + py::enum_(py_counter, "OneK") + .value("kIs1000", Counter::OneK::kIs1000) + .value("kIs1024", Counter::OneK::kIs1024) + .export_values(); + + py_counter + .def(py::init(), + py::arg("value") = 0., py::arg("flags") = Counter::kDefaults, + py::arg("k") = Counter::kIs1000) + .def(py::init([](double value) { return Counter(value); })) + .def_readwrite("value", &Counter::value) + .def_readwrite("flags", &Counter::flags) + .def_readwrite("oneK", &Counter::oneK); + py::implicitly_convertible(); + py::implicitly_convertible(); + + py::bind_map(m, "UserCounters"); + + using benchmark::State; + py::class_(m, "State") + .def("__bool__", &State::KeepRunning) + .def_property_readonly("keep_running", &State::KeepRunning) + .def("pause_timing", &State::PauseTiming) + .def("resume_timing", &State::ResumeTiming) + .def("skip_with_error", &State::SkipWithError) + .def_property_readonly("error_occurred", &State::error_occurred) + .def("set_iteration_time", &State::SetIterationTime) + .def_property("bytes_processed", &State::bytes_processed, + &State::SetBytesProcessed) + .def_property("complexity_n", &State::complexity_length_n, + &State::SetComplexityN) + .def_property("items_processed", &State::items_processed, + &State::SetItemsProcessed) + .def("set_label", (void (State::*)(const char*)) & State::SetLabel) + .def("range", &State::range, py::arg("pos") = 0) + .def_property_readonly("iterations", &State::iterations) + .def_readwrite("counters", &State::counters) + .def_readonly("thread_index", &State::thread_index) + .def_readonly("threads", &State::threads); + + m.def("Initialize", Initialize); + m.def("RegisterBenchmark", RegisterBenchmark, + py::return_value_policy::reference); + m.def("RunSpecifiedBenchmarks", + []() { benchmark::RunSpecifiedBenchmarks(); }); +}; +} // namespace diff --git a/libcxx/utils/google-benchmark/bindings/python/google_benchmark/example.py b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/example.py new file mode 100644 index 0000000000000..9134e8cffeafb --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/google_benchmark/example.py @@ -0,0 +1,136 @@ +# Copyright 2020 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Example of Python using C++ benchmark framework. + +To run this example, you must first install the `google_benchmark` Python package. + +To install using `setup.py`, download and extract the `google_benchmark` source. +In the extracted directory, execute: + python setup.py install +""" + +import random +import time + +import google_benchmark as benchmark +from google_benchmark import Counter + + +@benchmark.register +def empty(state): + while state: + pass + + +@benchmark.register +def sum_million(state): + while state: + sum(range(1_000_000)) + +@benchmark.register +def pause_timing(state): + """Pause timing every iteration.""" + while state: + # Construct a list of random ints every iteration without timing it + state.pause_timing() + random_list = [random.randint(0, 100) for _ in range(100)] + state.resume_timing() + # Time the in place sorting algorithm + random_list.sort() + + +@benchmark.register +def skipped(state): + if True: # Test some predicate here. + state.skip_with_error("some error") + return # NOTE: You must explicitly return, or benchmark will continue. + + ... # Benchmark code would be here. + + +@benchmark.register +def manual_timing(state): + while state: + # Manually count Python CPU time + start = time.perf_counter() # perf_counter_ns() in Python 3.7+ + # Something to benchmark + time.sleep(0.01) + end = time.perf_counter() + state.set_iteration_time(end - start) + + +@benchmark.register +def custom_counters(state): + """Collect cutom metric using benchmark.Counter.""" + num_foo = 0.0 + while state: + # Benchmark some code here + pass + # Collect some custom metric named foo + num_foo += 0.13 + + # Automatic Counter from numbers. + state.counters["foo"] = num_foo + # Set a counter as a rate. + state.counters["foo_rate"] = Counter(num_foo, Counter.kIsRate) + # Set a counter as an inverse of rate. + state.counters["foo_inv_rate"] = Counter(num_foo, Counter.kIsRate | Counter.kInvert) + # Set a counter as a thread-average quantity. + state.counters["foo_avg"] = Counter(num_foo, Counter.kAvgThreads) + # There's also a combined flag: + state.counters["foo_avg_rate"] = Counter(num_foo, Counter.kAvgThreadsRate) + + +@benchmark.register +@benchmark.option.measure_process_cpu_time() +@benchmark.option.use_real_time() +def with_options(state): + while state: + sum(range(1_000_000)) + + +@benchmark.register(name="sum_million_microseconds") +@benchmark.option.unit(benchmark.kMicrosecond) +def with_options(state): + while state: + sum(range(1_000_000)) + + +@benchmark.register +@benchmark.option.arg(100) +@benchmark.option.arg(1000) +def passing_argument(state): + while state: + sum(range(state.range(0))) + + +@benchmark.register +@benchmark.option.range(8, limit=8 << 10) +def using_range(state): + while state: + sum(range(state.range(0))) + + +@benchmark.register +@benchmark.option.range_multiplier(2) +@benchmark.option.range(1 << 10, 1 << 18) +@benchmark.option.complexity(benchmark.oN) +def computing_complexity(state): + while state: + sum(range(state.range(0))) + state.complexity_n = state.range(0) + + +if __name__ == "__main__": + benchmark.main() diff --git a/libcxx/utils/google-benchmark/bindings/python/pybind11.BUILD b/libcxx/utils/google-benchmark/bindings/python/pybind11.BUILD new file mode 100644 index 0000000000000..bc833500383a2 --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/pybind11.BUILD @@ -0,0 +1,20 @@ +cc_library( + name = "pybind11", + hdrs = glob( + include = [ + "include/pybind11/*.h", + "include/pybind11/detail/*.h", + ], + exclude = [ + "include/pybind11/common.h", + "include/pybind11/eigen.h", + ], + ), + copts = [ + "-fexceptions", + "-Wno-undefined-inline", + "-Wno-pragma-once-outside-header", + ], + includes = ["include"], + visibility = ["//visibility:public"], +) diff --git a/libcxx/utils/google-benchmark/bindings/python/python_headers.BUILD b/libcxx/utils/google-benchmark/bindings/python/python_headers.BUILD new file mode 100644 index 0000000000000..9c34cf6ca4bd3 --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/python_headers.BUILD @@ -0,0 +1,6 @@ +cc_library( + name = "python_headers", + hdrs = glob(["**/*.h"]), + includes = ["."], + visibility = ["//visibility:public"], +) diff --git a/libcxx/utils/google-benchmark/bindings/python/requirements.txt b/libcxx/utils/google-benchmark/bindings/python/requirements.txt new file mode 100644 index 0000000000000..f5bbe7eca5cea --- /dev/null +++ b/libcxx/utils/google-benchmark/bindings/python/requirements.txt @@ -0,0 +1,2 @@ +absl-py>=0.7.1 + diff --git a/libcxx/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake b/libcxx/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake index d0d2099814402..858589e9775c6 100644 --- a/libcxx/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake +++ b/libcxx/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake @@ -34,9 +34,11 @@ function(add_cxx_compiler_flag FLAG) check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG}) set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") if(${MANGLED_FLAG}) - set(VARIANT ${ARGV1}) - if(ARGV1) + if(ARGC GREATER 1) + set(VARIANT ${ARGV1}) string(TOUPPER "_${VARIANT}" VARIANT) + else() + set(VARIANT "") endif() set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${BENCHMARK_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE) endif() @@ -49,9 +51,11 @@ function(add_required_cxx_compiler_flag FLAG) check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG}) set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") if(${MANGLED_FLAG}) - set(VARIANT ${ARGV1}) - if(ARGV1) + if(ARGC GREATER 1) + set(VARIANT ${ARGV1}) string(TOUPPER "_${VARIANT}" VARIANT) + else() + set(VARIANT "") endif() set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE) diff --git a/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake b/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake index 99b56dd623904..62e6741fe3de0 100644 --- a/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake +++ b/libcxx/utils/google-benchmark/cmake/CXXFeatureCheck.cmake @@ -27,6 +27,11 @@ function(cxx_feature_check FILE) return() endif() + if (ARGC GREATER 1) + message(STATUS "Enabling additional flags: ${ARGV1}") + list(APPEND BENCHMARK_CXX_LINKER_FLAGS ${ARGV1}) + endif() + if (NOT DEFINED COMPILE_${FEATURE}) message(STATUS "Performing Test ${FEATURE}") if(CMAKE_CROSSCOMPILING) @@ -37,9 +42,9 @@ function(cxx_feature_check FILE) if(COMPILE_${FEATURE}) message(WARNING "If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0") - set(RUN_${FEATURE} 0) + set(RUN_${FEATURE} 0 CACHE INTERNAL "") else() - set(RUN_${FEATURE} 1) + set(RUN_${FEATURE} 1 CACHE INTERNAL "") endif() else() message(STATUS "Performing Test ${FEATURE}") diff --git a/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake b/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake index 4f10f226d7a78..04a1f9b70d683 100644 --- a/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake +++ b/libcxx/utils/google-benchmark/cmake/GetGitVersion.cmake @@ -20,16 +20,20 @@ set(__get_git_version INCLUDED) function(get_git_version var) if(GIT_EXECUTABLE) - execute_process(COMMAND ${GIT_EXECUTABLE} describe --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 + execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} RESULT_VARIABLE status - OUTPUT_VARIABLE GIT_VERSION + OUTPUT_VARIABLE GIT_DESCRIBE_VERSION ERROR_QUIET) - if(${status}) - set(GIT_VERSION "v0.0.0") + if(status) + set(GIT_DESCRIBE_VERSION "v0.0.0") + endif() + + string(STRIP ${GIT_DESCRIBE_VERSION} GIT_DESCRIBE_VERSION) + if(GIT_DESCRIBE_VERSION MATCHES v[^-]*-) + string(REGEX REPLACE "v([^-]*)-([0-9]+)-.*" "\\1.\\2" GIT_VERSION ${GIT_DESCRIBE_VERSION}) else() - string(STRIP ${GIT_VERSION} GIT_VERSION) - string(REGEX REPLACE "-[0-9]+-g" "-" GIT_VERSION ${GIT_VERSION}) + string(REGEX REPLACE "v(.*)" "\\1" GIT_VERSION ${GIT_DESCRIBE_VERSION}) endif() # Work out if the repository is dirty @@ -43,12 +47,12 @@ function(get_git_version var) ERROR_QUIET) string(COMPARE NOTEQUAL "${GIT_DIFF_INDEX}" "" GIT_DIRTY) if (${GIT_DIRTY}) - set(GIT_VERSION "${GIT_VERSION}-dirty") + set(GIT_DESCRIBE_VERSION "${GIT_DESCRIBE_VERSION}-dirty") endif() + message(STATUS "git version: ${GIT_DESCRIBE_VERSION} normalized to ${GIT_VERSION}") else() - set(GIT_VERSION "v0.0.0") + set(GIT_VERSION "0.0.0") endif() - message(STATUS "git Version: ${GIT_VERSION}") set(${var} ${GIT_VERSION} PARENT_SCOPE) endfunction() diff --git a/libcxx/utils/google-benchmark/cmake/GoogleTest.cmake b/libcxx/utils/google-benchmark/cmake/GoogleTest.cmake new file mode 100644 index 0000000000000..dd611fc875f19 --- /dev/null +++ b/libcxx/utils/google-benchmark/cmake/GoogleTest.cmake @@ -0,0 +1,41 @@ +# Download and unpack googletest at configure time +set(GOOGLETEST_PREFIX "${benchmark_BINARY_DIR}/third_party/googletest") +configure_file(${benchmark_SOURCE_DIR}/cmake/GoogleTest.cmake.in ${GOOGLETEST_PREFIX}/CMakeLists.txt @ONLY) + +set(GOOGLETEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/googletest" CACHE PATH "") # Mind the quotes +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" + -DALLOW_DOWNLOADING_GOOGLETEST=${BENCHMARK_DOWNLOAD_DEPENDENCIES} -DGOOGLETEST_PATH:PATH=${GOOGLETEST_PATH} . + RESULT_VARIABLE result + WORKING_DIRECTORY ${GOOGLETEST_PREFIX} +) + +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() + +execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${GOOGLETEST_PREFIX} +) + +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() + +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +include(${GOOGLETEST_PREFIX}/googletest-paths.cmake) + +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. +add_subdirectory(${GOOGLETEST_SOURCE_DIR} + ${GOOGLETEST_BINARY_DIR} + EXCLUDE_FROM_ALL) + +set_target_properties(gtest PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $) +set_target_properties(gtest_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $) +set_target_properties(gmock PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $) +set_target_properties(gmock_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $) diff --git a/libcxx/utils/google-benchmark/cmake/GoogleTest.cmake.in b/libcxx/utils/google-benchmark/cmake/GoogleTest.cmake.in new file mode 100644 index 0000000000000..fd957ff564095 --- /dev/null +++ b/libcxx/utils/google-benchmark/cmake/GoogleTest.cmake.in @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 2.8.12) + +project(googletest-download NONE) + +# Enable ExternalProject CMake module +include(ExternalProject) + +option(ALLOW_DOWNLOADING_GOOGLETEST "If googletest src tree is not found in location specified by GOOGLETEST_PATH, do fetch the archive from internet" OFF) +set(GOOGLETEST_PATH "/usr/src/googletest" CACHE PATH + "Path to the googletest root tree. Should contain googletest and googlemock subdirs. And CMakeLists.txt in root, and in both of these subdirs") + +# Download and install GoogleTest + +message(STATUS "Looking for Google Test sources") +message(STATUS "Looking for Google Test sources in ${GOOGLETEST_PATH}") +if(EXISTS "${GOOGLETEST_PATH}" AND IS_DIRECTORY "${GOOGLETEST_PATH}" AND EXISTS "${GOOGLETEST_PATH}/CMakeLists.txt" AND + EXISTS "${GOOGLETEST_PATH}/googletest" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googletest" AND EXISTS "${GOOGLETEST_PATH}/googletest/CMakeLists.txt" AND + EXISTS "${GOOGLETEST_PATH}/googlemock" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googlemock" AND EXISTS "${GOOGLETEST_PATH}/googlemock/CMakeLists.txt") + message(STATUS "Found Google Test in ${GOOGLETEST_PATH}") + + ExternalProject_Add( + googletest + PREFIX "${CMAKE_BINARY_DIR}" + DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download" + SOURCE_DIR "${GOOGLETEST_PATH}" # use existing src dir. + BINARY_DIR "${CMAKE_BINARY_DIR}/build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" + ) +else() + if(NOT ALLOW_DOWNLOADING_GOOGLETEST) + message(SEND_ERROR "Did not find Google Test sources! Either pass correct path in GOOGLETEST_PATH, or enable BENCHMARK_DOWNLOAD_DEPENDENCIES, or disable BENCHMARK_ENABLE_GTEST_TESTS / BENCHMARK_ENABLE_TESTING.") + else() + message(WARNING "Did not find Google Test sources! Fetching from web...") + ExternalProject_Add( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG master + PREFIX "${CMAKE_BINARY_DIR}" + STAMP_DIR "${CMAKE_BINARY_DIR}/stamp" + DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download" + SOURCE_DIR "${CMAKE_BINARY_DIR}/src" + BINARY_DIR "${CMAKE_BINARY_DIR}/build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" + ) + endif() +endif() + +ExternalProject_Get_Property(googletest SOURCE_DIR BINARY_DIR) +file(WRITE googletest-paths.cmake +"set(GOOGLETEST_SOURCE_DIR \"${SOURCE_DIR}\") +set(GOOGLETEST_BINARY_DIR \"${BINARY_DIR}\") +") diff --git a/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake b/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake deleted file mode 100644 index b9c14436dbfa4..0000000000000 --- a/libcxx/utils/google-benchmark/cmake/HandleGTest.cmake +++ /dev/null @@ -1,113 +0,0 @@ - -include(split_list) - -macro(build_external_gtest) - include(ExternalProject) - set(GTEST_FLAGS "") - if (BENCHMARK_USE_LIBCXX) - if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - list(APPEND GTEST_FLAGS -stdlib=libc++) - else() - message(WARNING "Unsupported compiler (${CMAKE_CXX_COMPILER}) when using libc++") - endif() - endif() - if (BENCHMARK_BUILD_32_BITS) - list(APPEND GTEST_FLAGS -m32) - endif() - if (NOT "${CMAKE_CXX_FLAGS}" STREQUAL "") - list(APPEND GTEST_FLAGS ${CMAKE_CXX_FLAGS}) - endif() - string(TOUPPER "${CMAKE_BUILD_TYPE}" GTEST_BUILD_TYPE) - if ("${GTEST_BUILD_TYPE}" STREQUAL "COVERAGE") - set(GTEST_BUILD_TYPE "DEBUG") - endif() - # FIXME: Since 10/Feb/2017 the googletest trunk has had a bug where - # -Werror=unused-function fires during the build on OS X. This is a temporary - # workaround to keep our travis bots from failing. It should be removed - # once gtest is fixed. - if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - list(APPEND GTEST_FLAGS "-Wno-unused-function") - endif() - split_list(GTEST_FLAGS) - set(EXCLUDE_FROM_ALL_OPT "") - set(EXCLUDE_FROM_ALL_VALUE "") - if (${CMAKE_VERSION} VERSION_GREATER "3.0.99") - set(EXCLUDE_FROM_ALL_OPT "EXCLUDE_FROM_ALL") - set(EXCLUDE_FROM_ALL_VALUE "ON") - endif() - ExternalProject_Add(googletest - ${EXCLUDE_FROM_ALL_OPT} ${EXCLUDE_FROM_ALL_VALUE} - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG master - PREFIX "${CMAKE_BINARY_DIR}/googletest" - INSTALL_DIR "${CMAKE_BINARY_DIR}/googletest" - CMAKE_CACHE_ARGS - -DCMAKE_BUILD_TYPE:STRING=${GTEST_BUILD_TYPE} - -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} - -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} - -DCMAKE_INSTALL_PREFIX:PATH= - -DCMAKE_INSTALL_LIBDIR:PATH=/lib - -DCMAKE_CXX_FLAGS:STRING=${GTEST_FLAGS} - -Dgtest_force_shared_crt:BOOL=ON - ) - - ExternalProject_Get_Property(googletest install_dir) - set(GTEST_INCLUDE_DIRS ${install_dir}/include) - file(MAKE_DIRECTORY ${GTEST_INCLUDE_DIRS}) - - set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}") - set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") - if("${GTEST_BUILD_TYPE}" STREQUAL "DEBUG") - set(LIB_SUFFIX "d${CMAKE_STATIC_LIBRARY_SUFFIX}") - endif() - - # Use gmock_main instead of gtest_main because it initializes gtest as well. - # Note: The libraries are listed in reverse order of their dependancies. - foreach(LIB gtest gmock gmock_main) - add_library(${LIB} UNKNOWN IMPORTED) - set_target_properties(${LIB} PROPERTIES - IMPORTED_LOCATION ${install_dir}/lib/${LIB_PREFIX}${LIB}${LIB_SUFFIX} - INTERFACE_INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIRS} - INTERFACE_LINK_LIBRARIES "${GTEST_BOTH_LIBRARIES}" - ) - add_dependencies(${LIB} googletest) - list(APPEND GTEST_BOTH_LIBRARIES ${LIB}) - endforeach() -endmacro(build_external_gtest) - -if (BENCHMARK_ENABLE_GTEST_TESTS) - if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest) - set(GTEST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/googletest") - set(INSTALL_GTEST OFF CACHE INTERNAL "") - set(INSTALL_GMOCK OFF CACHE INTERNAL "") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/googletest) - set(GTEST_BOTH_LIBRARIES gtest gmock gmock_main) - foreach(HEADER test mock) - # CMake 2.8 and older don't respect INTERFACE_INCLUDE_DIRECTORIES, so we - # have to add the paths ourselves. - set(HFILE g${HEADER}/g${HEADER}.h) - set(HPATH ${GTEST_ROOT}/google${HEADER}/include) - find_path(HEADER_PATH_${HEADER} ${HFILE} - NO_DEFAULT_PATHS - HINTS ${HPATH} - ) - if (NOT HEADER_PATH_${HEADER}) - message(FATAL_ERROR "Failed to find header ${HFILE} in ${HPATH}") - endif() - list(APPEND GTEST_INCLUDE_DIRS ${HEADER_PATH_${HEADER}}) - endforeach() - elseif(BENCHMARK_DOWNLOAD_DEPENDENCIES) - build_external_gtest() - else() - find_package(GTest REQUIRED) - find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h - HINTS ${GTEST_INCLUDE_DIRS}) - if (NOT GMOCK_INCLUDE_DIRS) - message(FATAL_ERROR "Failed to find header gmock/gmock.h with hint ${GTEST_INCLUDE_DIRS}") - endif() - set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS}) - # FIXME: We don't currently require the gmock library to build the tests, - # and it's likely we won't find it, so we don't try. As long as we've - # found the gmock/gmock.h header and gtest_main that should be good enough. - endif() -endif() diff --git a/libcxx/utils/google-benchmark/cmake/benchmark.pc.in b/libcxx/utils/google-benchmark/cmake/benchmark.pc.in index 1e84bff68d811..34beb012eef1a 100644 --- a/libcxx/utils/google-benchmark/cmake/benchmark.pc.in +++ b/libcxx/utils/google-benchmark/cmake/benchmark.pc.in @@ -1,11 +1,12 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} -libdir=${prefix}/lib -includedir=${prefix}/include +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: @PROJECT_NAME@ Description: Google microbenchmark framework Version: @VERSION@ Libs: -L${libdir} -lbenchmark +Libs.private: -lpthread Cflags: -I${includedir} diff --git a/libcxx/utils/google-benchmark/cmake/gnu_posix_regex.cpp b/libcxx/utils/google-benchmark/cmake/gnu_posix_regex.cpp index 105189f02ee6f..b5b91cdab7c2a 100644 --- a/libcxx/utils/google-benchmark/cmake/gnu_posix_regex.cpp +++ b/libcxx/utils/google-benchmark/cmake/gnu_posix_regex.cpp @@ -9,3 +9,4 @@ int main() { } return regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0; } + diff --git a/libcxx/utils/google-benchmark/cmake/posix_regex.cpp b/libcxx/utils/google-benchmark/cmake/posix_regex.cpp index 02f6dfc278a7c..466dc62560a27 100644 --- a/libcxx/utils/google-benchmark/cmake/posix_regex.cpp +++ b/libcxx/utils/google-benchmark/cmake/posix_regex.cpp @@ -11,3 +11,4 @@ int main() { regfree(&re); return ret; } + diff --git a/libcxx/utils/google-benchmark/cmake/std_regex.cpp b/libcxx/utils/google-benchmark/cmake/std_regex.cpp index 8177c482e838b..696f2a26bce02 100644 --- a/libcxx/utils/google-benchmark/cmake/std_regex.cpp +++ b/libcxx/utils/google-benchmark/cmake/std_regex.cpp @@ -7,3 +7,4 @@ int main() { std::regex_constants::extended | std::regex_constants::nosubs); return std::regex_search(str, re) ? 0 : -1; } + diff --git a/libcxx/utils/google-benchmark/dependencies.md b/libcxx/utils/google-benchmark/dependencies.md new file mode 100644 index 0000000000000..6289b4e3548bb --- /dev/null +++ b/libcxx/utils/google-benchmark/dependencies.md @@ -0,0 +1,18 @@ +# Build tool dependency policy + +To ensure the broadest compatibility when building the benchmark library, but +still allow forward progress, we require any build tooling to be available for: + +* Debian stable AND +* The last two Ubuntu LTS releases AND + +Currently, this means using build tool versions that are available for Ubuntu +16.04 (Xenial), Ubuntu 18.04 (Bionic), and Debian stretch. + +_Note, [travis](.travis.yml) runs under Ubuntu 14.04 (Trusty) for linux builds._ + +## cmake +The current supported version is cmake 3.5.1 as of 2018-06-06. + +_Note, this version is also available for Ubuntu 14.04, the previous Ubuntu LTS +release, as `cmake3`._ diff --git a/libcxx/utils/google-benchmark/docs/AssemblyTests.md b/libcxx/utils/google-benchmark/docs/AssemblyTests.md index 0d06f50ac652d..1fbdc269b53d6 100644 --- a/libcxx/utils/google-benchmark/docs/AssemblyTests.md +++ b/libcxx/utils/google-benchmark/docs/AssemblyTests.md @@ -144,3 +144,4 @@ tests to other architectures and compilers (using `CHECK` prefixes). Furthermore, the tests fail for builds which specify additional flags that modify code generation, including `--coverage` or `-fsanitize=`. + diff --git a/libcxx/utils/google-benchmark/docs/_config.yml b/libcxx/utils/google-benchmark/docs/_config.yml new file mode 100644 index 0000000000000..fc24e7a62dc28 --- /dev/null +++ b/libcxx/utils/google-benchmark/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-hacker \ No newline at end of file diff --git a/libcxx/utils/google-benchmark/docs/perf_counters.md b/libcxx/utils/google-benchmark/docs/perf_counters.md new file mode 100644 index 0000000000000..74560e9669712 --- /dev/null +++ b/libcxx/utils/google-benchmark/docs/perf_counters.md @@ -0,0 +1,34 @@ + + +# User-Requested Performance Counters + +When running benchmarks, the user may choose to request collection of +performance counters. This may be useful in investigation scenarios - narrowing +down the cause of a regression; or verifying that the underlying cause of a +performance improvement matches expectations. + +This feature is available if: + +* The benchmark is run on an architecture featuring a Performance Monitoring + Unit (PMU), +* The benchmark is compiled with support for collecting counters. Currently, + this requires [libpfm](http://perfmon2.sourceforge.net/) be available at build + time + +The feature does not require modifying benchmark code. Counter collection is +handled at the boundaries where timer collection is also handled. + +To opt-in: + +* Install `libpfm4-dev`, e.g. `apt-get install libpfm4-dev`. +* Enable the cmake flag BENCHMARK_ENABLE_LIBPFM. + +To use, pass a comma-separated list of counter names through the +`--benchmark_perf_counters` flag. The names are decoded through libpfm - meaning, +they are platform specific, but some (e.g. `CYCLES` or `INSTRUCTIONS`) are +mapped by libpfm to platform-specifics - see libpfm +[documentation](http://perfmon2.sourceforge.net/docs.html) for more details. + +The counter values are reported back through the [User Counters](../README.md#custom-counters) +mechanism, meaning, they are available in all the formats (e.g. JSON) supported +by User Counters. \ No newline at end of file diff --git a/libcxx/utils/google-benchmark/docs/random_interleaving.md b/libcxx/utils/google-benchmark/docs/random_interleaving.md new file mode 100644 index 0000000000000..c083036841480 --- /dev/null +++ b/libcxx/utils/google-benchmark/docs/random_interleaving.md @@ -0,0 +1,13 @@ + + +# Random Interleaving + +[Random Interleaving](https://github.com/google/benchmark/issues/1051) is a +technique to lower run-to-run variance. It randomly interleaves repetitions of a +microbenchmark with repetitions from other microbenchmarks in the same benchmark +test. Data shows it is able to lower run-to-run variance by +[40%](https://github.com/google/benchmark/issues/1051) on average. + +To use, you mainly need to set `--benchmark_enable_random_interleaving=true`, +and optionally specify non-zero repetition count `--benchmark_repetitions=9` +and optionally decrease the per-repetition time `--benchmark_min_time=0.1`. diff --git a/libcxx/utils/google-benchmark/releasing.md b/libcxx/utils/google-benchmark/docs/releasing.md similarity index 64% rename from libcxx/utils/google-benchmark/releasing.md rename to libcxx/utils/google-benchmark/docs/releasing.md index f0cd7010e3a90..7a6dfc4017b28 100644 --- a/libcxx/utils/google-benchmark/releasing.md +++ b/libcxx/utils/google-benchmark/docs/releasing.md @@ -1,6 +1,6 @@ # How to release -* Make sure you're on master and synced to HEAD +* Make sure you're on main and synced to HEAD * Ensure the project builds and tests run (sanity check only, obviously) * `parallel -j0 exec ::: test/*_test` can help ensure everything at least passes @@ -8,6 +8,12 @@ * `git log $(git describe --abbrev=0 --tags)..HEAD` gives you the list of commits between the last annotated tag and HEAD * Pick the most interesting. +* Create one last commit that updates the version saved in `CMakeLists.txt` to the release version you're creating. (This version will be used if benchmark is installed from the archive you'll be creating in the next step.) + +``` +project (benchmark VERSION 1.5.3 LANGUAGES CXX) +``` + * Create a release through github's interface * Note this will create a lightweight tag. * Update this to an annotated tag: diff --git a/libcxx/utils/google-benchmark/docs/tools.md b/libcxx/utils/google-benchmark/docs/tools.md index 4a3b2e9bd2c9c..f2d0c497f3fc7 100644 --- a/libcxx/utils/google-benchmark/docs/tools.md +++ b/libcxx/utils/google-benchmark/docs/tools.md @@ -4,7 +4,11 @@ The `compare.py` can be used to compare the result of benchmarks. -**NOTE**: the utility relies on the scipy package which can be installed using [these instructions](https://www.scipy.org/install.html). +### Dependencies +The utility relies on the [scipy](https://www.scipy.org) package which can be installed using pip: +```bash +pip3 install -r requirements.txt +``` ### Displaying aggregates only diff --git a/libcxx/utils/google-benchmark/include/benchmark/benchmark.h b/libcxx/utils/google-benchmark/include/benchmark/benchmark.h index a0fd7c6e1cade..9b5480244d6fb 100644 --- a/libcxx/utils/google-benchmark/include/benchmark/benchmark.h +++ b/libcxx/utils/google-benchmark/include/benchmark/benchmark.h @@ -42,6 +42,7 @@ BENCHMARK(BM_StringCopy); int main(int argc, char** argv) { benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); return 0; } @@ -56,8 +57,7 @@ static void BM_memcpy(benchmark::State& state) { memset(src, 'x', state.range(0)); for (auto _ : state) memcpy(dst, src, state.range(0)); - state.SetBytesProcessed(int64_t(state.iterations()) * - int64_t(state.range(0))); + state.SetBytesProcessed(state.iterations() * state.range(0)); delete[] src; delete[] dst; } BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10); @@ -122,8 +122,7 @@ template int BM_Sequential(benchmark::State& state) { q.Wait(&v); } // actually messages, not bytes: - state.SetBytesProcessed( - static_cast(state.iterations())*state.range(0)); + state.SetBytesProcessed(state.iterations() * state.range(0)); } BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue)->Range(1<<0, 1<<10); @@ -169,6 +168,12 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #define BENCHMARK_HAS_CXX11 #endif +// This _MSC_VER check should detect VS 2017 v15.3 and newer. +#if __cplusplus >= 201703L || \ + (defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L) +#define BENCHMARK_HAS_CXX17 +#endif + #include #include @@ -178,6 +183,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #include #include #include +#include #include #if defined(BENCHMARK_HAS_CXX11) @@ -200,13 +206,19 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); TypeName& operator=(const TypeName&) = delete #endif -#if defined(__GNUC__) +#ifdef BENCHMARK_HAS_CXX17 +#define BENCHMARK_UNUSED [[maybe_unused]] +#elif defined(__GNUC__) || defined(__clang__) #define BENCHMARK_UNUSED __attribute__((unused)) +#else +#define BENCHMARK_UNUSED +#endif + +#if defined(__GNUC__) || defined(__clang__) #define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline)) #define BENCHMARK_NOEXCEPT noexcept #define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) #elif defined(_MSC_VER) && !defined(__clang__) -#define BENCHMARK_UNUSED #define BENCHMARK_ALWAYS_INLINE __forceinline #if _MSC_VER >= 1900 #define BENCHMARK_NOEXCEPT noexcept @@ -217,7 +229,6 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #endif #define __func__ __FUNCTION__ #else -#define BENCHMARK_UNUSED #define BENCHMARK_ALWAYS_INLINE #define BENCHMARK_NOEXCEPT #define BENCHMARK_NOEXCEPT_OP(x) @@ -246,11 +257,17 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #endif #if defined(__GNUC__) || __has_builtin(__builtin_unreachable) - #define BENCHMARK_UNREACHABLE() __builtin_unreachable() +#define BENCHMARK_UNREACHABLE() __builtin_unreachable() #elif defined(_MSC_VER) - #define BENCHMARK_UNREACHABLE() __assume(false) +#define BENCHMARK_UNREACHABLE() __assume(false) +#else +#define BENCHMARK_UNREACHABLE() ((void)0) +#endif + +#ifdef BENCHMARK_HAS_CXX11 +#define BENCHMARK_OVERRIDE override #else - #define BENCHMARK_UNREACHABLE() ((void)0) +#define BENCHMARK_OVERRIDE #endif namespace benchmark { @@ -258,6 +275,7 @@ class BenchmarkReporter; class MemoryManager; void Initialize(int* argc, char** argv); +void Shutdown(); // Report to stdout all arguments in 'argv' as unrecognized except the first. // Returns true there is at least on unrecognized argument (i.e. 'argc' > 1). @@ -284,6 +302,9 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, // allocation measurements for benchmark runs. void RegisterMemoryManager(MemoryManager* memory_manager); +// Add a key-value pair to output as part of the context stanza in the report. +void AddCustomContext(const std::string& key, const std::string& value); + namespace internal { class Benchmark; class BenchmarkImp; @@ -370,7 +391,10 @@ class Counter { // It will be presented divided by the number of iterations. kAvgIterations = 1U << 3U, // Mark the counter as a iteration-average rate. See above. - kAvgIterationsRate = kIsRate | kAvgIterations + kAvgIterationsRate = kIsRate | kAvgIterations, + + // In the end, invert the result. This is always done last! + kInvert = 1U << 31U }; enum OneK { @@ -405,7 +429,7 @@ typedef std::map UserCounters; // TimeUnit is passed to a benchmark in order to specify the order of magnitude // for the measured time. -enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond }; +enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond }; // BigO is passed to a benchmark in order to specify the asymptotic // computational @@ -413,14 +437,17 @@ enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond }; // calculated automatically to the best fit. enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda }; +typedef uint64_t IterationCount; + // BigOFunc is passed to a benchmark in order to specify the asymptotic // computational complexity for the benchmark. -typedef double(BigOFunc)(int64_t); +typedef double(BigOFunc)(IterationCount); // StatisticsFunc is passed to a benchmark in order to compute some descriptive // statistics over all the measurements of some type typedef double(StatisticsFunc)(const std::vector&); +namespace internal { struct Statistics { std::string name_; StatisticsFunc* compute_; @@ -429,10 +456,10 @@ struct Statistics { : name_(name), compute_(compute) {} }; -namespace internal { -struct BenchmarkInstance; +class BenchmarkInstance; class ThreadTimer; class ThreadManager; +class PerfCountersMeasurement; enum AggregationReportMode #if defined(BENCHMARK_HAS_CXX11) @@ -488,7 +515,7 @@ class State { // while (state.KeepRunningBatch(1000)) { // // process 1000 elements // } - bool KeepRunningBatch(size_t n); + bool KeepRunningBatch(IterationCount n); // REQUIRES: timer is running and 'SkipWithError(...)' has not been called // by the current thread. @@ -538,6 +565,9 @@ class State { // responsibility to exit the scope as needed. void SkipWithError(const char* msg); + // Returns true if an error has been reported with 'SkipWithError(...)'. + bool error_occurred() const { return error_occurred_; } + // REQUIRES: called exactly once per iteration of the benchmarking loop. // Set the manually measured time for this benchmark iteration, which // is used instead of automatically measured time if UseManualTime() was @@ -574,7 +604,7 @@ class State { void SetComplexityN(int64_t complexity_n) { complexity_n_ = complexity_n; } BENCHMARK_ALWAYS_INLINE - int64_t complexity_length_n() { return complexity_n_; } + int64_t complexity_length_n() const { return complexity_n_; } // If this routine is called with items > 0, then an items/s // label is printed on the benchmark report line for the currently @@ -627,7 +657,7 @@ class State { int64_t range_y() const { return range(1); } BENCHMARK_ALWAYS_INLINE - size_t iterations() const { + IterationCount iterations() const { if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) { return 0; } @@ -638,15 +668,15 @@ class State { : // items we expect on the first cache line (ie 64 bytes of the struct) // When total_iterations_ is 0, KeepRunning() and friends will return false. // May be larger than max_iterations. - size_t total_iterations_; + IterationCount total_iterations_; // When using KeepRunningBatch(), batch_leftover_ holds the number of // iterations beyond max_iters that were run. Used to track // completed_iterations_ accurately. - size_t batch_leftover_; + IterationCount batch_leftover_; public: - const size_t max_iterations; + const IterationCount max_iterations; private: bool started_; @@ -667,30 +697,32 @@ class State { const int threads; private: - State(size_t max_iters, const std::vector& ranges, int thread_i, - int n_threads, internal::ThreadTimer* timer, - internal::ThreadManager* manager); + State(IterationCount max_iters, const std::vector& ranges, + int thread_i, int n_threads, internal::ThreadTimer* timer, + internal::ThreadManager* manager, + internal::PerfCountersMeasurement* perf_counters_measurement); void StartKeepRunning(); // Implementation of KeepRunning() and KeepRunningBatch(). // is_batch must be true unless n is 1. - bool KeepRunningInternal(size_t n, bool is_batch); + bool KeepRunningInternal(IterationCount n, bool is_batch); void FinishKeepRunning(); - internal::ThreadTimer* timer_; - internal::ThreadManager* manager_; + internal::ThreadTimer* const timer_; + internal::ThreadManager* const manager_; + internal::PerfCountersMeasurement* const perf_counters_measurement_; - friend struct internal::BenchmarkInstance; + friend class internal::BenchmarkInstance; }; inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() { return KeepRunningInternal(1, /*is_batch=*/false); } -inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(size_t n) { +inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(IterationCount n) { return KeepRunningInternal(n, /*is_batch=*/true); } -inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(size_t n, +inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n, bool is_batch) { // total_iterations_ is set to 0 by the constructor, and always set to a // nonzero value by StartKepRunning(). @@ -754,7 +786,7 @@ struct State::StateIterator { } private: - size_t cached_; + IterationCount cached_; State* const parent_; }; @@ -783,6 +815,9 @@ class Benchmark { // Note: the following methods all return "this" so that multiple // method calls can be chained together in one expression. + // Specify the name of the benchmark + Benchmark* Name(const std::string& name); + // Run this benchmark once with "x" as the extra argument passed // to the function. // REQUIRES: The function passed to the constructor must accept an arg1. @@ -821,6 +856,11 @@ class Benchmark { // REQUIRES: The function passed to the constructor must accept arg1, arg2 ... Benchmark* Ranges(const std::vector >& ranges); + // Run this benchmark once for each combination of values in the (cartesian) + // product of the supplied argument lists. + // REQUIRES: The function passed to the constructor must accept arg1, arg2 ... + Benchmark* ArgsProduct(const std::vector >& arglists); + // Equivalent to ArgNames({name}) Benchmark* ArgName(const std::string& name); @@ -858,7 +898,7 @@ class Benchmark { // NOTE: This function should only be used when *exact* iteration control is // needed and never to control or limit how long a benchmark runs, where // `--benchmark_min_time=N` or `MinTime(...)` should be used instead. - Benchmark* Iterations(size_t n); + Benchmark* Iterations(IterationCount n); // Specify the amount of times to repeat this benchmark. This option overrides // the `benchmark_repetitions` flag. @@ -874,11 +914,18 @@ class Benchmark { // Same as ReportAggregatesOnly(), but applies to display reporter only. Benchmark* DisplayAggregatesOnly(bool value = true); - // If a particular benchmark is I/O bound, runs multiple threads internally or - // if for some reason CPU timings are not representative, call this method. If - // called, the elapsed time will be used to control how many iterations are - // run, and in the printing of items/second or MB/seconds values. If not - // called, the cpu time used by the benchmark will be used. + // By default, the CPU time is measured only for the main thread, which may + // be unrepresentative if the benchmark uses threads internally. If called, + // the total CPU time spent by all the threads will be measured instead. + // By default, the only the main thread CPU time will be measured. + Benchmark* MeasureProcessCPUTime(); + + // If a particular benchmark should use the Wall clock instead of the CPU time + // (be it either the CPU time of the main thread only (default), or the + // total CPU usage of the benchmark), call this method. If called, the elapsed + // (wall) time will be used to control how many iterations are run, and in the + // printing of items/second or MB/seconds values. + // If not called, the CPU time used by the benchmark will be used. Benchmark* UseRealTime(); // If a benchmark must measure time manually (e.g. if GPU execution time is @@ -942,6 +989,7 @@ class Benchmark { private: friend class BenchmarkFamilies; + friend class BenchmarkInstance; std::string name_; AggregationReportMode aggregation_report_mode_; @@ -950,8 +998,9 @@ class Benchmark { TimeUnit time_unit_; int range_multiplier_; double min_time_; - size_t iterations_; + IterationCount iterations_; int repetitions_; + bool measure_process_cpu_time_; bool use_real_time_; bool use_manual_time_; BigO complexity_; @@ -988,7 +1037,7 @@ class FunctionBenchmark : public Benchmark { FunctionBenchmark(const char* name, Function* func) : Benchmark(name), func_(func) {} - virtual void Run(State& st); + virtual void Run(State& st) BENCHMARK_OVERRIDE; private: Function* func_; @@ -998,7 +1047,7 @@ class FunctionBenchmark : public Benchmark { template class LambdaBenchmark : public Benchmark { public: - virtual void Run(State& st) { lambda_(st); } + virtual void Run(State& st) BENCHMARK_OVERRIDE { lambda_(st); } private: template @@ -1050,7 +1099,7 @@ class Fixture : public internal::Benchmark { public: Fixture() : internal::Benchmark("") {} - virtual void Run(State& st) { + virtual void Run(State& st) BENCHMARK_OVERRIDE { this->SetUp(st); this->BenchmarkCase(st); this->TearDown(st); @@ -1083,9 +1132,12 @@ class Fixture : public internal::Benchmark { // Helpers for generating unique variable names #define BENCHMARK_PRIVATE_NAME(n) \ - BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n) + BENCHMARK_PRIVATE_CONCAT(benchmark_uniq_, BENCHMARK_PRIVATE_UNIQUE_ID, n) #define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c) #define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c +// Helper for concatenation with macro name expansion +#define BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method) \ + BaseClass##_##Method##_Benchmark #define BENCHMARK_PRIVATE_DECLARE(n) \ static ::benchmark::internal::Benchmark* BENCHMARK_PRIVATE_NAME(n) \ @@ -1155,37 +1207,37 @@ class Fixture : public internal::Benchmark { #define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a) #endif -#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ - class BaseClass##_##Method##_Benchmark : public BaseClass { \ - public: \ - BaseClass##_##Method##_Benchmark() : BaseClass() { \ - this->SetName(#BaseClass "/" #Method); \ - } \ - \ - protected: \ - virtual void BenchmarkCase(::benchmark::State&); \ +#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ + class BaseClass##_##Method##_Benchmark : public BaseClass { \ + public: \ + BaseClass##_##Method##_Benchmark() : BaseClass() { \ + this->SetName(#BaseClass "/" #Method); \ + } \ + \ + protected: \ + virtual void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE; \ }; -#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \ - class BaseClass##_##Method##_Benchmark : public BaseClass { \ - public: \ - BaseClass##_##Method##_Benchmark() : BaseClass() { \ - this->SetName(#BaseClass "<" #a ">/" #Method); \ - } \ - \ - protected: \ - virtual void BenchmarkCase(::benchmark::State&); \ +#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \ + class BaseClass##_##Method##_Benchmark : public BaseClass { \ + public: \ + BaseClass##_##Method##_Benchmark() : BaseClass() { \ + this->SetName(#BaseClass "<" #a ">/" #Method); \ + } \ + \ + protected: \ + virtual void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE; \ }; -#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \ - class BaseClass##_##Method##_Benchmark : public BaseClass { \ - public: \ - BaseClass##_##Method##_Benchmark() : BaseClass() { \ - this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \ - } \ - \ - protected: \ - virtual void BenchmarkCase(::benchmark::State&); \ +#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \ + class BaseClass##_##Method##_Benchmark : public BaseClass { \ + public: \ + BaseClass##_##Method##_Benchmark() : BaseClass() { \ + this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \ + } \ + \ + protected: \ + virtual void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE; \ }; #ifdef BENCHMARK_HAS_CXX11 @@ -1197,7 +1249,7 @@ class Fixture : public internal::Benchmark { } \ \ protected: \ - virtual void BenchmarkCase(::benchmark::State&); \ + virtual void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE; \ }; #else #define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(n, a) \ @@ -1206,27 +1258,27 @@ class Fixture : public internal::Benchmark { #define BENCHMARK_DEFINE_F(BaseClass, Method) \ BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) \ BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b) \ BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #ifdef BENCHMARK_HAS_CXX11 #define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...) \ BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #else #define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, a) \ BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) #endif #define BENCHMARK_REGISTER_F(BaseClass, Method) \ - BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark) + BENCHMARK_PRIVATE_REGISTER_F(BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)) #define BENCHMARK_PRIVATE_REGISTER_F(TestName) \ BENCHMARK_PRIVATE_DECLARE(TestName) = \ @@ -1236,23 +1288,23 @@ class Fixture : public internal::Benchmark { #define BENCHMARK_F(BaseClass, Method) \ BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \ BENCHMARK_REGISTER_F(BaseClass, Method); \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) \ BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \ BENCHMARK_REGISTER_F(BaseClass, Method); \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b) \ BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \ BENCHMARK_REGISTER_F(BaseClass, Method); \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #ifdef BENCHMARK_HAS_CXX11 #define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \ BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \ BENCHMARK_REGISTER_F(BaseClass, Method); \ - void BaseClass##_##Method##_Benchmark::BenchmarkCase + void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase #else #define BENCHMARK_TEMPLATE_F(BaseClass, Method, a) \ BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) @@ -1264,6 +1316,8 @@ class Fixture : public internal::Benchmark { ::benchmark::Initialize(&argc, argv); \ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \ ::benchmark::RunSpecifiedBenchmarks(); \ + ::benchmark::Shutdown(); \ + return 0; \ } \ int main(int, char**) @@ -1280,10 +1334,16 @@ struct CPUInfo { int num_sharing; }; + enum Scaling { + UNKNOWN, + ENABLED, + DISABLED + }; + int num_cpus; + Scaling scaling; double cycles_per_second; std::vector caches; - bool scaling_enabled; std::vector load_avg; static const CPUInfo& Get(); @@ -1293,15 +1353,33 @@ struct CPUInfo { BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo); }; -//Adding Struct for System Information +// Adding Struct for System Information struct SystemInfo { std::string name; static const SystemInfo& Get(); + private: SystemInfo(); BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo); }; +// BenchmarkName contains the components of the Benchmark's name +// which allows individual fields to be modified or cleared before +// building the final name using 'str()'. +struct BenchmarkName { + std::string function_name; + std::string args; + std::string min_time; + std::string iterations; + std::string repetitions; + std::string time_type; + std::string threads; + + // Return the full name of the benchmark with each non-empty + // field separated by a '/' + std::string str() const; +}; + // Interface for custom benchmark result printers. // By default, benchmark reports are printed to stdout. However an application // can control the destination of the reports by calling @@ -1319,12 +1397,14 @@ class BenchmarkReporter { }; struct Run { + static const int64_t no_repetition_index = -1; enum RunType { RT_Iteration, RT_Aggregate }; Run() : run_type(RT_Iteration), error_occurred(false), iterations(1), + threads(1), time_unit(kNanosecond), real_accumulated_time(0), cpu_accumulated_time(0), @@ -1340,14 +1420,19 @@ class BenchmarkReporter { max_bytes_used(0) {} std::string benchmark_name() const; - std::string run_name; - RunType run_type; // is this a measurement, or an aggregate? + BenchmarkName run_name; + int64_t family_index; + int64_t per_family_instance_index; + RunType run_type; std::string aggregate_name; std::string report_label; // Empty if not set by benchmark. bool error_occurred; std::string error_message; - int64_t iterations; + IterationCount iterations; + int64_t threads; + int64_t repetition_index; + int64_t repetitions; TimeUnit time_unit; double real_accumulated_time; double cpu_accumulated_time; @@ -1373,7 +1458,7 @@ class BenchmarkReporter { int64_t complexity_n; // what statistics to compute from the measurements - const std::vector* statistics; + const std::vector* statistics; // Inform print function whether the current run is a complexity report bool report_big_o; @@ -1387,6 +1472,19 @@ class BenchmarkReporter { int64_t max_bytes_used; }; + struct PerFamilyRunReports { + PerFamilyRunReports() : num_runs_total(0), num_runs_done(0) {} + + // How many runs will all instances of this benchmark perform? + int num_runs_total; + + // How many runs have happened already? + int num_runs_done; + + // The reports about (non-errneous!) runs of this family. + std::vector Runs; + }; + // Construct a BenchmarkReporter with the output stream set to 'std::cout' // and the error stream set to 'std::cerr' BenchmarkReporter(); @@ -1459,8 +1557,8 @@ class ConsoleReporter : public BenchmarkReporter { prev_counters_(), printed_header_(false) {} - virtual bool ReportContext(const Context& context); - virtual void ReportRuns(const std::vector& reports); + virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; + virtual void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; protected: virtual void PrintRunData(const Run& report); @@ -1475,9 +1573,9 @@ class ConsoleReporter : public BenchmarkReporter { class JSONReporter : public BenchmarkReporter { public: JSONReporter() : first_report_(true) {} - virtual bool ReportContext(const Context& context); - virtual void ReportRuns(const std::vector& reports); - virtual void Finalize(); + virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; + virtual void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; + virtual void Finalize() BENCHMARK_OVERRIDE; private: void PrintRunData(const Run& report); @@ -1485,12 +1583,13 @@ class JSONReporter : public BenchmarkReporter { bool first_report_; }; -class BENCHMARK_DEPRECATED_MSG("The CSV Reporter will be removed in a future release") - CSVReporter : public BenchmarkReporter { +class BENCHMARK_DEPRECATED_MSG( + "The CSV Reporter will be removed in a future release") CSVReporter + : public BenchmarkReporter { public: CSVReporter() : printed_header_(false) {} - virtual bool ReportContext(const Context& context); - virtual void ReportRuns(const std::vector& reports); + virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE; + virtual void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE; private: void PrintRunData(const Run& report); @@ -1524,6 +1623,8 @@ class MemoryManager { inline const char* GetTimeUnitString(TimeUnit unit) { switch (unit) { + case kSecond: + return "s"; case kMillisecond: return "ms"; case kMicrosecond: @@ -1536,6 +1637,8 @@ inline const char* GetTimeUnitString(TimeUnit unit) { inline double GetTimeUnitMultiplier(TimeUnit unit) { switch (unit) { + case kSecond: + return 1; case kMillisecond: return 1e3; case kMicrosecond: diff --git a/libcxx/utils/google-benchmark/mingw.py b/libcxx/utils/google-benchmark/mingw.py deleted file mode 100644 index 0b69692ca2a40..0000000000000 --- a/libcxx/utils/google-benchmark/mingw.py +++ /dev/null @@ -1,320 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -import argparse -import errno -import logging -import os -import platform -import re -import sys -import subprocess -import tempfile - -try: - import winreg -except ImportError: - import _winreg as winreg -try: - import urllib.request as request -except ImportError: - import urllib as request -try: - import urllib.parse as parse -except ImportError: - import urlparse as parse - -class EmptyLogger(object): - ''' - Provides an implementation that performs no logging - ''' - def debug(self, *k, **kw): - pass - def info(self, *k, **kw): - pass - def warn(self, *k, **kw): - pass - def error(self, *k, **kw): - pass - def critical(self, *k, **kw): - pass - def setLevel(self, *k, **kw): - pass - -urls = ( - 'http://downloads.sourceforge.net/project/mingw-w64/Toolchains%20' - 'targetting%20Win32/Personal%20Builds/mingw-builds/installer/' - 'repository.txt', - 'http://downloads.sourceforge.net/project/mingwbuilds/host-windows/' - 'repository.txt' -) -''' -A list of mingw-build repositories -''' - -def repository(urls = urls, log = EmptyLogger()): - ''' - Downloads and parse mingw-build repository files and parses them - ''' - log.info('getting mingw-builds repository') - versions = {} - re_sourceforge = re.compile(r'http://sourceforge.net/projects/([^/]+)/files') - re_sub = r'http://downloads.sourceforge.net/project/\1' - for url in urls: - log.debug(' - requesting: %s', url) - socket = request.urlopen(url) - repo = socket.read() - if not isinstance(repo, str): - repo = repo.decode(); - socket.close() - for entry in repo.split('\n')[:-1]: - value = entry.split('|') - version = tuple([int(n) for n in value[0].strip().split('.')]) - version = versions.setdefault(version, {}) - arch = value[1].strip() - if arch == 'x32': - arch = 'i686' - elif arch == 'x64': - arch = 'x86_64' - arch = version.setdefault(arch, {}) - threading = arch.setdefault(value[2].strip(), {}) - exceptions = threading.setdefault(value[3].strip(), {}) - revision = exceptions.setdefault(int(value[4].strip()[3:]), - re_sourceforge.sub(re_sub, value[5].strip())) - return versions - -def find_in_path(file, path=None): - ''' - Attempts to find an executable in the path - ''' - if platform.system() == 'Windows': - file += '.exe' - if path is None: - path = os.environ.get('PATH', '') - if type(path) is type(''): - path = path.split(os.pathsep) - return list(filter(os.path.exists, - map(lambda dir, file=file: os.path.join(dir, file), path))) - -def find_7zip(log = EmptyLogger()): - ''' - Attempts to find 7zip for unpacking the mingw-build archives - ''' - log.info('finding 7zip') - path = find_in_path('7z') - if not path: - key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\7-Zip') - path, _ = winreg.QueryValueEx(key, 'Path') - path = [os.path.join(path, '7z.exe')] - log.debug('found \'%s\'', path[0]) - return path[0] - -find_7zip() - -def unpack(archive, location, log = EmptyLogger()): - ''' - Unpacks a mingw-builds archive - ''' - sevenzip = find_7zip(log) - log.info('unpacking %s', os.path.basename(archive)) - cmd = [sevenzip, 'x', archive, '-o' + location, '-y'] - log.debug(' - %r', cmd) - with open(os.devnull, 'w') as devnull: - subprocess.check_call(cmd, stdout = devnull) - -def download(url, location, log = EmptyLogger()): - ''' - Downloads and unpacks a mingw-builds archive - ''' - log.info('downloading MinGW') - log.debug(' - url: %s', url) - log.debug(' - location: %s', location) - - re_content = re.compile(r'attachment;[ \t]*filename=(")?([^"]*)(")?[\r\n]*') - - stream = request.urlopen(url) - try: - content = stream.getheader('Content-Disposition') or '' - except AttributeError: - content = stream.headers.getheader('Content-Disposition') or '' - matches = re_content.match(content) - if matches: - filename = matches.group(2) - else: - parsed = parse.urlparse(stream.geturl()) - filename = os.path.basename(parsed.path) - - try: - os.makedirs(location) - except OSError as e: - if e.errno == errno.EEXIST and os.path.isdir(location): - pass - else: - raise - - archive = os.path.join(location, filename) - with open(archive, 'wb') as out: - while True: - buf = stream.read(1024) - if not buf: - break - out.write(buf) - unpack(archive, location, log = log) - os.remove(archive) - - possible = os.path.join(location, 'mingw64') - if not os.path.exists(possible): - possible = os.path.join(location, 'mingw32') - if not os.path.exists(possible): - raise ValueError('Failed to find unpacked MinGW: ' + possible) - return possible - -def root(location = None, arch = None, version = None, threading = None, - exceptions = None, revision = None, log = EmptyLogger()): - ''' - Returns the root folder of a specific version of the mingw-builds variant - of gcc. Will download the compiler if needed - ''' - - # Get the repository if we don't have all the information - if not (arch and version and threading and exceptions and revision): - versions = repository(log = log) - - # Determine some defaults - version = version or max(versions.keys()) - if not arch: - arch = platform.machine().lower() - if arch == 'x86': - arch = 'i686' - elif arch == 'amd64': - arch = 'x86_64' - if not threading: - keys = versions[version][arch].keys() - if 'posix' in keys: - threading = 'posix' - elif 'win32' in keys: - threading = 'win32' - else: - threading = keys[0] - if not exceptions: - keys = versions[version][arch][threading].keys() - if 'seh' in keys: - exceptions = 'seh' - elif 'sjlj' in keys: - exceptions = 'sjlj' - else: - exceptions = keys[0] - if revision == None: - revision = max(versions[version][arch][threading][exceptions].keys()) - if not location: - location = os.path.join(tempfile.gettempdir(), 'mingw-builds') - - # Get the download url - url = versions[version][arch][threading][exceptions][revision] - - # Tell the user whatzzup - log.info('finding MinGW %s', '.'.join(str(v) for v in version)) - log.debug(' - arch: %s', arch) - log.debug(' - threading: %s', threading) - log.debug(' - exceptions: %s', exceptions) - log.debug(' - revision: %s', revision) - log.debug(' - url: %s', url) - - # Store each specific revision differently - slug = '{version}-{arch}-{threading}-{exceptions}-rev{revision}' - slug = slug.format( - version = '.'.join(str(v) for v in version), - arch = arch, - threading = threading, - exceptions = exceptions, - revision = revision - ) - if arch == 'x86_64': - root_dir = os.path.join(location, slug, 'mingw64') - elif arch == 'i686': - root_dir = os.path.join(location, slug, 'mingw32') - else: - raise ValueError('Unknown MinGW arch: ' + arch) - - # Download if needed - if not os.path.exists(root_dir): - downloaded = download(url, os.path.join(location, slug), log = log) - if downloaded != root_dir: - raise ValueError('The location of mingw did not match\n%s\n%s' - % (downloaded, root_dir)) - - return root_dir - -def str2ver(string): - ''' - Converts a version string into a tuple - ''' - try: - version = tuple(int(v) for v in string.split('.')) - if len(version) is not 3: - raise ValueError() - except ValueError: - raise argparse.ArgumentTypeError( - 'please provide a three digit version string') - return version - -def main(): - ''' - Invoked when the script is run directly by the python interpreter - ''' - parser = argparse.ArgumentParser( - description = 'Downloads a specific version of MinGW', - formatter_class = argparse.ArgumentDefaultsHelpFormatter - ) - parser.add_argument('--location', - help = 'the location to download the compiler to', - default = os.path.join(tempfile.gettempdir(), 'mingw-builds')) - parser.add_argument('--arch', required = True, choices = ['i686', 'x86_64'], - help = 'the target MinGW architecture string') - parser.add_argument('--version', type = str2ver, - help = 'the version of GCC to download') - parser.add_argument('--threading', choices = ['posix', 'win32'], - help = 'the threading type of the compiler') - parser.add_argument('--exceptions', choices = ['sjlj', 'seh', 'dwarf'], - help = 'the method to throw exceptions') - parser.add_argument('--revision', type=int, - help = 'the revision of the MinGW release') - group = parser.add_mutually_exclusive_group() - group.add_argument('-v', '--verbose', action='store_true', - help='increase the script output verbosity') - group.add_argument('-q', '--quiet', action='store_true', - help='only print errors and warning') - args = parser.parse_args() - - # Create the logger - logger = logging.getLogger('mingw') - handler = logging.StreamHandler() - formatter = logging.Formatter('%(message)s') - handler.setFormatter(formatter) - logger.addHandler(handler) - logger.setLevel(logging.INFO) - if args.quiet: - logger.setLevel(logging.WARN) - if args.verbose: - logger.setLevel(logging.DEBUG) - - # Get MinGW - root_dir = root(location = args.location, arch = args.arch, - version = args.version, threading = args.threading, - exceptions = args.exceptions, revision = args.revision, - log = logger) - - sys.stdout.write('%s\n' % os.path.join(root_dir, 'bin')) - -if __name__ == '__main__': - try: - main() - except IOError as e: - sys.stderr.write('IO error: %s\n' % e) - sys.exit(1) - except OSError as e: - sys.stderr.write('OS error: %s\n' % e) - sys.exit(1) - except KeyboardInterrupt as e: - sys.stderr.write('Killed\n') - sys.exit(1) diff --git a/libcxx/utils/google-benchmark/requirements.txt b/libcxx/utils/google-benchmark/requirements.txt new file mode 100644 index 0000000000000..85e8986040685 --- /dev/null +++ b/libcxx/utils/google-benchmark/requirements.txt @@ -0,0 +1,2 @@ +numpy == 1.19.4 +scipy == 1.5.4 diff --git a/libcxx/utils/google-benchmark/setup.py b/libcxx/utils/google-benchmark/setup.py new file mode 100644 index 0000000000000..5cdab10cf77c7 --- /dev/null +++ b/libcxx/utils/google-benchmark/setup.py @@ -0,0 +1,140 @@ +import os +import posixpath +import re +import shutil +import sys + +from distutils import sysconfig +import setuptools +from setuptools.command import build_ext + + +HERE = os.path.dirname(os.path.abspath(__file__)) + + +IS_WINDOWS = sys.platform.startswith("win") + + +def _get_version(): + """Parse the version string from __init__.py.""" + with open( + os.path.join(HERE, "bindings", "python", "google_benchmark", "__init__.py") + ) as init_file: + try: + version_line = next( + line for line in init_file if line.startswith("__version__") + ) + except StopIteration: + raise ValueError("__version__ not defined in __init__.py") + else: + namespace = {} + exec(version_line, namespace) # pylint: disable=exec-used + return namespace["__version__"] + + +def _parse_requirements(path): + with open(os.path.join(HERE, path)) as requirements: + return [ + line.rstrip() + for line in requirements + if not (line.isspace() or line.startswith("#")) + ] + + +class BazelExtension(setuptools.Extension): + """A C/C++ extension that is defined as a Bazel BUILD target.""" + + def __init__(self, name, bazel_target): + self.bazel_target = bazel_target + self.relpath, self.target_name = posixpath.relpath(bazel_target, "//").split( + ":" + ) + setuptools.Extension.__init__(self, name, sources=[]) + + +class BuildBazelExtension(build_ext.build_ext): + """A command that runs Bazel to build a C/C++ extension.""" + + def run(self): + for ext in self.extensions: + self.bazel_build(ext) + build_ext.build_ext.run(self) + + def bazel_build(self, ext): + """Runs the bazel build to create the package.""" + with open("WORKSPACE", "r") as workspace: + workspace_contents = workspace.read() + + with open("WORKSPACE", "w") as workspace: + workspace.write( + re.sub( + r'(?<=path = ").*(?=", # May be overwritten by setup\.py\.)', + sysconfig.get_python_inc().replace(os.path.sep, posixpath.sep), + workspace_contents, + ) + ) + + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + + bazel_argv = [ + "bazel", + "build", + ext.bazel_target, + "--symlink_prefix=" + os.path.join(self.build_temp, "bazel-"), + "--compilation_mode=" + ("dbg" if self.debug else "opt"), + ] + + if IS_WINDOWS: + # Link with python*.lib. + for library_dir in self.library_dirs: + bazel_argv.append("--linkopt=/LIBPATH:" + library_dir) + + self.spawn(bazel_argv) + + shared_lib_suffix = '.dll' if IS_WINDOWS else '.so' + ext_bazel_bin_path = os.path.join( + self.build_temp, 'bazel-bin', + ext.relpath, ext.target_name + shared_lib_suffix) + + ext_dest_path = self.get_ext_fullpath(ext.name) + ext_dest_dir = os.path.dirname(ext_dest_path) + if not os.path.exists(ext_dest_dir): + os.makedirs(ext_dest_dir) + shutil.copyfile(ext_bazel_bin_path, ext_dest_path) + + +setuptools.setup( + name="google_benchmark", + version=_get_version(), + url="https://github.com/google/benchmark", + description="A library to benchmark code snippets.", + author="Google", + author_email="benchmark-py@google.com", + # Contained modules and scripts. + package_dir={"": "bindings/python"}, + packages=setuptools.find_packages("bindings/python"), + install_requires=_parse_requirements("bindings/python/requirements.txt"), + cmdclass=dict(build_ext=BuildBazelExtension), + ext_modules=[ + BazelExtension( + "google_benchmark._benchmark", + "//bindings/python/google_benchmark:_benchmark", + ) + ], + zip_safe=False, + # PyPI package information. + classifiers=[ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Topic :: Software Development :: Testing", + "Topic :: System :: Benchmark", + ], + license="Apache 2.0", + keywords="benchmark", +) diff --git a/libcxx/utils/google-benchmark/src/CMakeLists.txt b/libcxx/utils/google-benchmark/src/CMakeLists.txt index 7a77fdf41de90..a6c8e9a7a0b7e 100644 --- a/libcxx/utils/google-benchmark/src/CMakeLists.txt +++ b/libcxx/utils/google-benchmark/src/CMakeLists.txt @@ -1,4 +1,5 @@ # Allow the source files to find headers in src/ +include(GNUInstallDirs) include_directories(${PROJECT_SOURCE_DIR}/src) if (DEFINED BENCHMARK_CXX_LINKER_FLAGS) @@ -17,6 +18,7 @@ foreach(item ${BENCHMARK_MAIN}) endforeach() add_library(benchmark ${SOURCE_FILES}) +add_library(benchmark::benchmark ALIAS benchmark) set_target_properties(benchmark PROPERTIES OUTPUT_NAME "benchmark" VERSION ${GENERIC_LIB_VERSION} @@ -26,6 +28,12 @@ target_include_directories(benchmark PUBLIC $ ) +# libpfm, if available +if (HAVE_LIBPFM) + target_link_libraries(benchmark libpfm.a) + add_definitions(-DHAVE_LIBPFM) +endif() + # Link threads. target_link_libraries(benchmark ${BENCHMARK_CXX_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) find_library(LIBRT rt) @@ -33,6 +41,14 @@ if(LIBRT) target_link_libraries(benchmark ${LIBRT}) endif() +if(CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER) +endif() +if(NOT CMAKE_THREAD_LIBS_INIT AND "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}" MATCHES ".*-fsanitize=[^ ]*address.*") + message(WARNING "CMake's FindThreads.cmake did not fail, but CMAKE_THREAD_LIBS_INIT ended up being empty. This was fixed in https://github.com/Kitware/CMake/commit/d53317130e84898c5328c237186dbd995aaf1c12 Let's guess that -pthread is sufficient.") + target_link_libraries(benchmark -pthread) +endif() + # We need extra libraries on Windows if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(benchmark shlwapi) @@ -45,6 +61,7 @@ endif() # Benchmark main library add_library(benchmark_main "benchmark_main.cc") +add_library(benchmark::benchmark_main ALIAS benchmark_main) set_target_properties(benchmark_main PROPERTIES OUTPUT_NAME "benchmark_main" VERSION ${GENERIC_LIB_VERSION} @@ -53,13 +70,8 @@ set_target_properties(benchmark_main PROPERTIES target_include_directories(benchmark PUBLIC $ ) -target_link_libraries(benchmark_main benchmark) +target_link_libraries(benchmark_main benchmark::benchmark) -set(include_install_dir "include") -set(lib_install_dir "lib/") -set(bin_install_dir "bin/") -set(config_install_dir "lib/cmake/${PROJECT_NAME}") -set(pkgconfig_install_dir "lib/pkgconfig") set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") @@ -83,26 +95,26 @@ if (BENCHMARK_ENABLE_INSTALL) install( TARGETS benchmark benchmark_main EXPORT ${targets_export_name} - ARCHIVE DESTINATION ${lib_install_dir} - LIBRARY DESTINATION ${lib_install_dir} - RUNTIME DESTINATION ${bin_install_dir} - INCLUDES DESTINATION ${include_install_dir}) + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark" - DESTINATION ${include_install_dir} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.*h") install( FILES "${project_config}" "${version_config}" - DESTINATION "${config_install_dir}") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") install( FILES "${pkg_config}" - DESTINATION "${pkgconfig_install_dir}") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") install( EXPORT "${targets_export_name}" NAMESPACE "${namespace}" - DESTINATION "${config_install_dir}") + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") endif() diff --git a/libcxx/utils/google-benchmark/src/benchmark.cc b/libcxx/utils/google-benchmark/src/benchmark.cc index aab07500af422..89f64967bf18f 100644 --- a/libcxx/utils/google-benchmark/src/benchmark.cc +++ b/libcxx/utils/google-benchmark/src/benchmark.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "benchmark/benchmark.h" + #include "benchmark_api_internal.h" #include "benchmark_runner.h" #include "internal_macros.h" @@ -32,7 +33,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -45,85 +49,94 @@ #include "internal_macros.h" #include "log.h" #include "mutex.h" +#include "perf_counters.h" #include "re.h" #include "statistics.h" #include "string_util.h" #include "thread_manager.h" #include "thread_timer.h" -DEFINE_bool(benchmark_list_tests, false, - "Print a list of benchmarks. This option overrides all other " - "options."); - -DEFINE_string(benchmark_filter, ".", - "A regular expression that specifies the set of benchmarks " - "to execute. If this flag is empty, or if this flag is the " - "string \"all\", all benchmarks linked into the binary are " - "run."); - -DEFINE_double(benchmark_min_time, 0.5, - "Minimum number of seconds we should run benchmark before " - "results are considered significant. For cpu-time based " - "tests, this is the lower bound on the total cpu time " - "used by all threads that make up the test. For real-time " - "based tests, this is the lower bound on the elapsed time " - "of the benchmark execution, regardless of number of " - "threads."); - -DEFINE_int32(benchmark_repetitions, 1, - "The number of runs of each benchmark. If greater than 1, the " - "mean and standard deviation of the runs will be reported."); - -DEFINE_bool( - benchmark_report_aggregates_only, false, - "Report the result of each benchmark repetitions. When 'true' is specified " - "only the mean, standard deviation, and other statistics are reported for " - "repeated benchmarks. Affects all reporters."); - -DEFINE_bool( - benchmark_display_aggregates_only, false, - "Display the result of each benchmark repetitions. When 'true' is " - "specified only the mean, standard deviation, and other statistics are " - "displayed for repeated benchmarks. Unlike " - "benchmark_report_aggregates_only, only affects the display reporter, but " - "*NOT* file reporter, which will still contain all the output."); - -DEFINE_string(benchmark_format, "console", - "The format to use for console output. Valid values are " - "'console', 'json', or 'csv'."); - -DEFINE_string(benchmark_out_format, "json", - "The format to use for file output. Valid values are " - "'console', 'json', or 'csv'."); - -DEFINE_string(benchmark_out, "", "The file to write additional output to"); - -DEFINE_string(benchmark_color, "auto", - "Whether to use colors in the output. Valid values: " - "'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use " - "colors if the output is being sent to a terminal and the TERM " - "environment variable is set to a terminal type that supports " - "colors."); - -DEFINE_bool(benchmark_counters_tabular, false, - "Whether to use tabular format when printing user counters to " - "the console. Valid values: 'true'/'yes'/1, 'false'/'no'/0." - "Defaults to false."); - -DEFINE_int32(v, 0, "The level of verbose logging to output"); +// Print a list of benchmarks. This option overrides all other options. +DEFINE_bool(benchmark_list_tests, false); + +// A regular expression that specifies the set of benchmarks to execute. If +// this flag is empty, or if this flag is the string \"all\", all benchmarks +// linked into the binary are run. +DEFINE_string(benchmark_filter, "."); + +// Minimum number of seconds we should run benchmark before results are +// considered significant. For cpu-time based tests, this is the lower bound +// on the total cpu time used by all threads that make up the test. For +// real-time based tests, this is the lower bound on the elapsed time of the +// benchmark execution, regardless of number of threads. +DEFINE_double(benchmark_min_time, 0.5); + +// The number of runs of each benchmark. If greater than 1, the mean and +// standard deviation of the runs will be reported. +DEFINE_int32(benchmark_repetitions, 1); + +// If set, enable random interleaving of repetitions of all benchmarks. +// See http://github.com/google/benchmark/issues/1051 for details. +DEFINE_bool(benchmark_enable_random_interleaving, false); + +// Report the result of each benchmark repetitions. When 'true' is specified +// only the mean, standard deviation, and other statistics are reported for +// repeated benchmarks. Affects all reporters. +DEFINE_bool(benchmark_report_aggregates_only, false); + +// Display the result of each benchmark repetitions. When 'true' is specified +// only the mean, standard deviation, and other statistics are displayed for +// repeated benchmarks. Unlike benchmark_report_aggregates_only, only affects +// the display reporter, but *NOT* file reporter, which will still contain +// all the output. +DEFINE_bool(benchmark_display_aggregates_only, false); + +// The format to use for console output. +// Valid values are 'console', 'json', or 'csv'. +DEFINE_string(benchmark_format, "console"); + +// The format to use for file output. +// Valid values are 'console', 'json', or 'csv'. +DEFINE_string(benchmark_out_format, "json"); + +// The file to write additional output to. +DEFINE_string(benchmark_out, ""); + +// Whether to use colors in the output. Valid values: +// 'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use colors if +// the output is being sent to a terminal and the TERM environment variable is +// set to a terminal type that supports colors. +DEFINE_string(benchmark_color, "auto"); + +// Whether to use tabular format when printing user counters to the console. +// Valid values: 'true'/'yes'/1, 'false'/'no'/0. Defaults to false. +DEFINE_bool(benchmark_counters_tabular, false); + +// The level of verbose logging to output +DEFINE_int32(v, 0); + +// List of additional perf counters to collect, in libpfm format. For more +// information about libpfm: https://man7.org/linux/man-pages/man3/libpfm.3.html +DEFINE_string(benchmark_perf_counters, ""); namespace benchmark { - namespace internal { +// Extra context to include in the output formatted as comma-separated key-value +// pairs. Kept internal as it's only used for parsing from env/command line. +DEFINE_kvpairs(benchmark_context, {}); + +std::map* global_context = nullptr; + // FIXME: wouldn't LTO mess this up? void UseCharPointer(char const volatile*) {} } // namespace internal -State::State(size_t max_iters, const std::vector& ranges, int thread_i, - int n_threads, internal::ThreadTimer* timer, - internal::ThreadManager* manager) +State::State(IterationCount max_iters, const std::vector& ranges, + int thread_i, int n_threads, internal::ThreadTimer* timer, + internal::ThreadManager* manager, + internal::PerfCountersMeasurement* perf_counters_measurement) : total_iterations_(0), batch_leftover_(0), max_iterations(max_iters), @@ -136,7 +149,8 @@ State::State(size_t max_iters, const std::vector& ranges, int thread_i, thread_index(thread_i), threads(n_threads), timer_(timer), - manager_(manager) { + manager_(manager), + perf_counters_measurement_(perf_counters_measurement) { CHECK(max_iterations != 0) << "At least one iteration must be run"; CHECK_LT(thread_index, threads) << "thread_index must be less than threads"; @@ -148,7 +162,7 @@ State::State(size_t max_iters, const std::vector& ranges, int thread_i, // which must be suppressed. #if defined(__INTEL_COMPILER) #pragma warning push -#pragma warning(disable:1875) +#pragma warning(disable : 1875) #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Winvalid-offsetof" @@ -169,11 +183,23 @@ void State::PauseTiming() { // Add in time accumulated so far CHECK(started_ && !finished_ && !error_occurred_); timer_->StopTimer(); + if (perf_counters_measurement_) { + auto measurements = perf_counters_measurement_->StopAndGetMeasurements(); + for (const auto& name_and_measurement : measurements) { + auto name = name_and_measurement.first; + auto measurement = name_and_measurement.second; + CHECK_EQ(counters[name], 0.0); + counters[name] = Counter(measurement, Counter::kAvgIterations); + } + } } void State::ResumeTiming() { CHECK(started_ && !finished_ && !error_occurred_); timer_->StartTimer(); + if (perf_counters_measurement_) { + perf_counters_measurement_->Start(); + } } void State::SkipWithError(const char* msg) { @@ -221,6 +247,37 @@ void State::FinishKeepRunning() { namespace internal { namespace { +// Flushes streams after invoking reporter methods that write to them. This +// ensures users get timely updates even when streams are not line-buffered. +void FlushStreams(BenchmarkReporter* reporter) { + if (!reporter) return; + std::flush(reporter->GetOutputStream()); + std::flush(reporter->GetErrorStream()); +} + +// Reports in both display and file reporters. +void Report(BenchmarkReporter* display_reporter, + BenchmarkReporter* file_reporter, const RunResults& run_results) { + auto report_one = [](BenchmarkReporter* reporter, bool aggregates_only, + const RunResults& results) { + assert(reporter); + // If there are no aggregates, do output non-aggregates. + aggregates_only &= !results.aggregates_only.empty(); + if (!aggregates_only) reporter->ReportRuns(results.non_aggregates); + if (!results.aggregates_only.empty()) + reporter->ReportRuns(results.aggregates_only); + }; + + report_one(display_reporter, run_results.display_report_aggregates_only, + run_results); + if (file_reporter) + report_one(file_reporter, run_results.file_report_aggregates_only, + run_results); + + FlushStreams(display_reporter); + FlushStreams(file_reporter); +} + void RunBenchmarks(const std::vector& benchmarks, BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter) { @@ -233,10 +290,10 @@ void RunBenchmarks(const std::vector& benchmarks, size_t stat_field_width = 0; for (const BenchmarkInstance& benchmark : benchmarks) { name_field_width = - std::max(name_field_width, benchmark.name.size()); - might_have_aggregates |= benchmark.repetitions > 1; + std::max(name_field_width, benchmark.name().str().size()); + might_have_aggregates |= benchmark.repetitions() > 1; - for (const auto& Stat : *benchmark.statistics) + for (const auto& Stat : benchmark.statistics()) stat_field_width = std::max(stat_field_width, Stat.name_.size()); } if (might_have_aggregates) name_field_width += 1 + stat_field_width; @@ -245,50 +302,86 @@ void RunBenchmarks(const std::vector& benchmarks, BenchmarkReporter::Context context; context.name_field_width = name_field_width; - // Keep track of running times of all instances of current benchmark - std::vector complexity_reports; - - // We flush streams after invoking reporter methods that write to them. This - // ensures users get timely updates even when streams are not line-buffered. - auto flushStreams = [](BenchmarkReporter* reporter) { - if (!reporter) return; - std::flush(reporter->GetOutputStream()); - std::flush(reporter->GetErrorStream()); - }; + // Keep track of running times of all instances of each benchmark family. + std::map + per_family_reports; if (display_reporter->ReportContext(context) && (!file_reporter || file_reporter->ReportContext(context))) { - flushStreams(display_reporter); - flushStreams(file_reporter); - - for (const auto& benchmark : benchmarks) { - RunResults run_results = RunBenchmark(benchmark, &complexity_reports); - - auto report = [&run_results](BenchmarkReporter* reporter, - bool report_aggregates_only) { - assert(reporter); - // If there are no aggregates, do output non-aggregates. - report_aggregates_only &= !run_results.aggregates_only.empty(); - if (!report_aggregates_only) - reporter->ReportRuns(run_results.non_aggregates); - if (!run_results.aggregates_only.empty()) - reporter->ReportRuns(run_results.aggregates_only); - }; - - report(display_reporter, run_results.display_report_aggregates_only); - if (file_reporter) - report(file_reporter, run_results.file_report_aggregates_only); - - flushStreams(display_reporter); - flushStreams(file_reporter); + FlushStreams(display_reporter); + FlushStreams(file_reporter); + + size_t num_repetitions_total = 0; + + std::vector runners; + runners.reserve(benchmarks.size()); + for (const BenchmarkInstance& benchmark : benchmarks) { + BenchmarkReporter::PerFamilyRunReports* reports_for_family = nullptr; + if (benchmark.complexity() != oNone) + reports_for_family = &per_family_reports[benchmark.family_index()]; + + runners.emplace_back(benchmark, reports_for_family); + int num_repeats_of_this_instance = runners.back().GetNumRepeats(); + num_repetitions_total += num_repeats_of_this_instance; + if (reports_for_family) + reports_for_family->num_runs_total += num_repeats_of_this_instance; + } + assert(runners.size() == benchmarks.size() && "Unexpected runner count."); + + std::vector repetition_indices; + repetition_indices.reserve(num_repetitions_total); + for (size_t runner_index = 0, num_runners = runners.size(); + runner_index != num_runners; ++runner_index) { + const internal::BenchmarkRunner& runner = runners[runner_index]; + std::fill_n(std::back_inserter(repetition_indices), + runner.GetNumRepeats(), runner_index); + } + assert(repetition_indices.size() == num_repetitions_total && + "Unexpected number of repetition indexes."); + + if (FLAGS_benchmark_enable_random_interleaving) { + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(repetition_indices.begin(), repetition_indices.end(), g); + } + + for (size_t repetition_index : repetition_indices) { + internal::BenchmarkRunner& runner = runners[repetition_index]; + runner.DoOneRepetition(); + if (runner.HasRepeatsRemaining()) continue; + // FIXME: report each repetition separately, not all of them in bulk. + + RunResults run_results = runner.GetResults(); + + // Maybe calculate complexity report + if (const auto* reports_for_family = runner.GetReportsForFamily()) { + if (reports_for_family->num_runs_done == + reports_for_family->num_runs_total) { + auto additional_run_stats = ComputeBigO(reports_for_family->Runs); + run_results.aggregates_only.insert(run_results.aggregates_only.end(), + additional_run_stats.begin(), + additional_run_stats.end()); + per_family_reports.erase( + (int)reports_for_family->Runs.front().family_index); + } + } + + Report(display_reporter, file_reporter, run_results); } } display_reporter->Finalize(); if (file_reporter) file_reporter->Finalize(); - flushStreams(display_reporter); - flushStreams(file_reporter); + FlushStreams(display_reporter); + FlushStreams(file_reporter); } +// Disable deprecated warnings temporarily because we need to reference +// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + std::unique_ptr CreateReporter( std::string const& name, ConsoleReporter::OutputOptions output_opts) { typedef std::unique_ptr PtrType; @@ -304,6 +397,10 @@ std::unique_ptr CreateReporter( } } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } // end namespace bool IsZero(double n) { @@ -312,7 +409,7 @@ bool IsZero(double n) { ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) { int output_opts = ConsoleReporter::OO_Defaults; - auto is_benchmark_color = [force_no_color] () -> bool { + auto is_benchmark_color = [force_no_color]() -> bool { if (force_no_color) { return false; } @@ -372,7 +469,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, if (!fname.empty()) { output_file.open(fname); if (!output_file.is_open()) { - Err << "invalid file name: '" << fname << std::endl; + Err << "invalid file name: '" << fname << "'" << std::endl; std::exit(1); } if (!file_reporter) { @@ -393,7 +490,8 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, } if (FLAGS_benchmark_list_tests) { - for (auto const& benchmark : benchmarks) Out << benchmark.name << "\n"; + for (auto const& benchmark : benchmarks) + Out << benchmark.name().str() << "\n"; } else { internal::RunBenchmarks(benchmarks, display_reporter, file_reporter); } @@ -405,6 +503,16 @@ void RegisterMemoryManager(MemoryManager* manager) { internal::memory_manager = manager; } +void AddCustomContext(const std::string& key, const std::string& value) { + if (internal::global_context == nullptr) { + internal::global_context = new std::map(); + } + if (!internal::global_context->emplace(key, value).second) { + std::cerr << "Failed to add custom context \"" << key << "\" as it already " + << "exists with value \"" << value << "\"\n"; + } +} + namespace internal { void PrintUsageAndExit() { @@ -414,6 +522,7 @@ void PrintUsageAndExit() { " [--benchmark_filter=]\n" " [--benchmark_min_time=]\n" " [--benchmark_repetitions=]\n" + " [--benchmark_enable_random_interleaving={true|false}]\n" " [--benchmark_report_aggregates_only={true|false}]\n" " [--benchmark_display_aggregates_only={true|false}]\n" " [--benchmark_format=]\n" @@ -421,6 +530,7 @@ void PrintUsageAndExit() { " [--benchmark_out_format=]\n" " [--benchmark_color={auto|true|false}]\n" " [--benchmark_counters_tabular={true|false}]\n" + " [--benchmark_context==,...]\n" " [--v=]\n"); exit(0); } @@ -429,7 +539,7 @@ void ParseCommandLineFlags(int* argc, char** argv) { using namespace benchmark; BenchmarkReporter::Context::executable_name = (argc && *argc > 0) ? argv[0] : "unknown"; - for (int i = 1; i < *argc; ++i) { + for (int i = 1; argc && i < *argc; ++i) { if (ParseBoolFlag(argv[i], "benchmark_list_tests", &FLAGS_benchmark_list_tests) || ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) || @@ -437,6 +547,8 @@ void ParseCommandLineFlags(int* argc, char** argv) { &FLAGS_benchmark_min_time) || ParseInt32Flag(argv[i], "benchmark_repetitions", &FLAGS_benchmark_repetitions) || + ParseBoolFlag(argv[i], "benchmark_enable_random_interleaving", + &FLAGS_benchmark_enable_random_interleaving) || ParseBoolFlag(argv[i], "benchmark_report_aggregates_only", &FLAGS_benchmark_report_aggregates_only) || ParseBoolFlag(argv[i], "benchmark_display_aggregates_only", @@ -451,6 +563,10 @@ void ParseCommandLineFlags(int* argc, char** argv) { ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) || ParseBoolFlag(argv[i], "benchmark_counters_tabular", &FLAGS_benchmark_counters_tabular) || + ParseStringFlag(argv[i], "benchmark_perf_counters", + &FLAGS_benchmark_perf_counters) || + ParseKeyValueFlag(argv[i], "benchmark_context", + &FLAGS_benchmark_context) || ParseInt32Flag(argv[i], "v", &FLAGS_v)) { for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1]; @@ -461,13 +577,17 @@ void ParseCommandLineFlags(int* argc, char** argv) { } } for (auto const* flag : - {&FLAGS_benchmark_format, &FLAGS_benchmark_out_format}) + {&FLAGS_benchmark_format, &FLAGS_benchmark_out_format}) { if (*flag != "console" && *flag != "json" && *flag != "csv") { PrintUsageAndExit(); } + } if (FLAGS_benchmark_color.empty()) { PrintUsageAndExit(); } + for (const auto& kv : FLAGS_benchmark_context) { + AddCustomContext(kv.first, kv.second); + } } int InitializeStreams() { @@ -482,6 +602,10 @@ void Initialize(int* argc, char** argv) { internal::LogLevel() = FLAGS_v; } +void Shutdown() { + delete internal::global_context; +} + bool ReportUnrecognizedArguments(int argc, char** argv) { for (int i = 1; i < argc; ++i) { fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0], diff --git a/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc b/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc index 8d3108363b8c1..89da519afc8cb 100644 --- a/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc +++ b/libcxx/utils/google-benchmark/src/benchmark_api_internal.cc @@ -1,15 +1,94 @@ #include "benchmark_api_internal.h" +#include + +#include "string_util.h" + namespace benchmark { namespace internal { +BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx, + int per_family_instance_idx, + const std::vector& args, + int thread_count) + : benchmark_(*benchmark), + family_index_(family_idx), + per_family_instance_index_(per_family_instance_idx), + aggregation_report_mode_(benchmark_.aggregation_report_mode_), + args_(args), + time_unit_(benchmark_.time_unit_), + measure_process_cpu_time_(benchmark_.measure_process_cpu_time_), + use_real_time_(benchmark_.use_real_time_), + use_manual_time_(benchmark_.use_manual_time_), + complexity_(benchmark_.complexity_), + complexity_lambda_(benchmark_.complexity_lambda_), + statistics_(benchmark_.statistics_), + repetitions_(benchmark_.repetitions_), + min_time_(benchmark_.min_time_), + iterations_(benchmark_.iterations_), + threads_(thread_count) { + name_.function_name = benchmark_.name_; + + size_t arg_i = 0; + for (const auto& arg : args) { + if (!name_.args.empty()) { + name_.args += '/'; + } + + if (arg_i < benchmark->arg_names_.size()) { + const auto& arg_name = benchmark_.arg_names_[arg_i]; + if (!arg_name.empty()) { + name_.args += StrFormat("%s:", arg_name.c_str()); + } + } + + name_.args += StrFormat("%" PRId64, arg); + ++arg_i; + } + + if (!IsZero(benchmark->min_time_)) { + name_.min_time = StrFormat("min_time:%0.3f", benchmark_.min_time_); + } + + if (benchmark_.iterations_ != 0) { + name_.iterations = StrFormat( + "iterations:%lu", static_cast(benchmark_.iterations_)); + } + + if (benchmark_.repetitions_ != 0) { + name_.repetitions = StrFormat("repeats:%d", benchmark_.repetitions_); + } + + if (benchmark_.measure_process_cpu_time_) { + name_.time_type = "process_time"; + } + + if (benchmark_.use_manual_time_) { + if (!name_.time_type.empty()) { + name_.time_type += '/'; + } + name_.time_type += "manual_time"; + } else if (benchmark_.use_real_time_) { + if (!name_.time_type.empty()) { + name_.time_type += '/'; + } + name_.time_type += "real_time"; + } + + if (!benchmark_.thread_counts_.empty()) { + name_.threads = StrFormat("threads:%d", threads_); + } +} + State BenchmarkInstance::Run( - size_t iters, int thread_id, internal::ThreadTimer* timer, - internal::ThreadManager* manager) const { - State st(iters, arg, thread_id, threads, timer, manager); - benchmark->Run(st); + IterationCount iters, int thread_id, internal::ThreadTimer* timer, + internal::ThreadManager* manager, + internal::PerfCountersMeasurement* perf_counters_measurement) const { + State st(iters, args_, thread_id, threads_, timer, manager, + perf_counters_measurement); + benchmark_.Run(st); return st; } -} // internal -} // benchmark +} // namespace internal +} // namespace benchmark diff --git a/libcxx/utils/google-benchmark/src/benchmark_api_internal.h b/libcxx/utils/google-benchmark/src/benchmark_api_internal.h index 0524a85c01d00..9296b7d2c8165 100644 --- a/libcxx/utils/google-benchmark/src/benchmark_api_internal.h +++ b/libcxx/utils/google-benchmark/src/benchmark_api_internal.h @@ -1,9 +1,6 @@ #ifndef BENCHMARK_API_INTERNAL_H #define BENCHMARK_API_INTERNAL_H -#include "benchmark/benchmark.h" -#include "commandlineflags.h" - #include #include #include @@ -11,31 +8,60 @@ #include #include +#include "benchmark/benchmark.h" +#include "commandlineflags.h" + namespace benchmark { namespace internal { // Information kept per benchmark we may want to run -struct BenchmarkInstance { - std::string name; - Benchmark* benchmark; - AggregationReportMode aggregation_report_mode; - std::vector arg; - TimeUnit time_unit; - int range_multiplier; - bool use_real_time; - bool use_manual_time; - BigO complexity; - BigOFunc* complexity_lambda; - UserCounters counters; - const std::vector* statistics; - bool last_benchmark_instance; - int repetitions; - double min_time; - size_t iterations; - int threads; // Number of concurrent threads to us - - State Run(size_t iters, int thread_id, internal::ThreadTimer* timer, - internal::ThreadManager* manager) const; +class BenchmarkInstance { + public: + BenchmarkInstance(Benchmark* benchmark, int family_index, + int per_family_instance_index, + const std::vector& args, int threads); + + const BenchmarkName& name() const { return name_; } + int family_index() const { return family_index_; } + int per_family_instance_index() const { return per_family_instance_index_; } + AggregationReportMode aggregation_report_mode() const { + return aggregation_report_mode_; + } + TimeUnit time_unit() const { return time_unit_; } + bool measure_process_cpu_time() const { return measure_process_cpu_time_; } + bool use_real_time() const { return use_real_time_; } + bool use_manual_time() const { return use_manual_time_; } + BigO complexity() const { return complexity_; } + BigOFunc& complexity_lambda() const { return *complexity_lambda_; } + const std::vector& statistics() const { return statistics_; } + int repetitions() const { return repetitions_; } + double min_time() const { return min_time_; } + IterationCount iterations() const { return iterations_; } + int threads() const { return threads_; } + + State Run(IterationCount iters, int thread_id, internal::ThreadTimer* timer, + internal::ThreadManager* manager, + internal::PerfCountersMeasurement* perf_counters_measurement) const; + + private: + BenchmarkName name_; + Benchmark& benchmark_; + const int family_index_; + const int per_family_instance_index_; + AggregationReportMode aggregation_report_mode_; + const std::vector& args_; + TimeUnit time_unit_; + bool measure_process_cpu_time_; + bool use_real_time_; + bool use_manual_time_; + BigO complexity_; + BigOFunc* complexity_lambda_; + UserCounters counters_; + const std::vector& statistics_; + int repetitions_; + double min_time_; + IterationCount iterations_; + int threads_; // Number of concurrent threads to us }; bool FindBenchmarksInternal(const std::string& re, diff --git a/libcxx/utils/google-benchmark/src/benchmark_name.cc b/libcxx/utils/google-benchmark/src/benchmark_name.cc new file mode 100644 index 0000000000000..2a17ebce277f5 --- /dev/null +++ b/libcxx/utils/google-benchmark/src/benchmark_name.cc @@ -0,0 +1,58 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +namespace benchmark { + +namespace { + +// Compute the total size of a pack of std::strings +size_t size_impl() { return 0; } + +template +size_t size_impl(const Head& head, const Tail&... tail) { + return head.size() + size_impl(tail...); +} + +// Join a pack of std::strings using a delimiter +// TODO: use absl::StrJoin +void join_impl(std::string&, char) {} + +template +void join_impl(std::string& s, const char delimiter, const Head& head, + const Tail&... tail) { + if (!s.empty() && !head.empty()) { + s += delimiter; + } + + s += head; + + join_impl(s, delimiter, tail...); +} + +template +std::string join(char delimiter, const Ts&... ts) { + std::string s; + s.reserve(sizeof...(Ts) + size_impl(ts...)); + join_impl(s, delimiter, ts...); + return s; +} +} // namespace + +std::string BenchmarkName::str() const { + return join('/', function_name, args, min_time, iterations, repetitions, + time_type, threads); +} +} // namespace benchmark diff --git a/libcxx/utils/google-benchmark/src/benchmark_register.cc b/libcxx/utils/google-benchmark/src/benchmark_register.cc index f17f5b223cec6..574462220e7c2 100644 --- a/libcxx/utils/google-benchmark/src/benchmark_register.cc +++ b/libcxx/utils/google-benchmark/src/benchmark_register.cc @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -127,8 +129,13 @@ bool BenchmarkFamilies::FindBenchmarks( // Special list of thread counts to use when none are specified const std::vector one_thread = {1}; + int next_family_index = 0; + MutexLock l(mutex_); for (std::unique_ptr& family : families_) { + int family_index = next_family_index; + int per_family_instance_index = 0; + // Family was deleted or benchmark doesn't match if (!family) continue; @@ -148,71 +155,24 @@ bool BenchmarkFamilies::FindBenchmarks( } // reserve in the special case the regex ".", since we know the final // family size. - if (spec == ".") benchmarks->reserve(family_size); + if (spec == ".") benchmarks->reserve(benchmarks->size() + family_size); for (auto const& args : family->args_) { for (int num_threads : *thread_counts) { - BenchmarkInstance instance; - instance.name = family->name_; - instance.benchmark = family.get(); - instance.aggregation_report_mode = family->aggregation_report_mode_; - instance.arg = args; - instance.time_unit = family->time_unit_; - instance.range_multiplier = family->range_multiplier_; - instance.min_time = family->min_time_; - instance.iterations = family->iterations_; - instance.repetitions = family->repetitions_; - instance.use_real_time = family->use_real_time_; - instance.use_manual_time = family->use_manual_time_; - instance.complexity = family->complexity_; - instance.complexity_lambda = family->complexity_lambda_; - instance.statistics = &family->statistics_; - instance.threads = num_threads; - - // Add arguments to instance name - size_t arg_i = 0; - for (auto const& arg : args) { - instance.name += "/"; - - if (arg_i < family->arg_names_.size()) { - const auto& arg_name = family->arg_names_[arg_i]; - if (!arg_name.empty()) { - instance.name += - StrFormat("%s:", family->arg_names_[arg_i].c_str()); - } - } - - // we know that the args are always non-negative (see 'AddRange()'), - // thus print as 'unsigned'. BUT, do a cast due to the 32-bit builds. - instance.name += StrFormat("%lu", static_cast(arg)); - ++arg_i; - } + BenchmarkInstance instance(family.get(), family_index, + per_family_instance_index, args, + num_threads); - if (!IsZero(family->min_time_)) - instance.name += StrFormat("/min_time:%0.3f", family->min_time_); - if (family->iterations_ != 0) { - instance.name += - StrFormat("/iterations:%lu", - static_cast(family->iterations_)); - } - if (family->repetitions_ != 0) - instance.name += StrFormat("/repeats:%d", family->repetitions_); - - if (family->use_manual_time_) { - instance.name += "/manual_time"; - } else if (family->use_real_time_) { - instance.name += "/real_time"; - } + const auto full_name = instance.name().str(); + if ((re.Match(full_name) && !isNegativeFilter) || + (!re.Match(full_name) && isNegativeFilter)) { + benchmarks->push_back(std::move(instance)); - // Add the number of threads used to the name - if (!family->thread_counts_.empty()) { - instance.name += StrFormat("/threads:%d", instance.threads); - } + ++per_family_instance_index; - if ((re.Match(instance.name) && !isNegativeFilter) || - (!re.Match(instance.name) && isNegativeFilter)) { - instance.last_benchmark_instance = (&args == &family->args_.back()); - benchmarks->push_back(std::move(instance)); + // Only bump the next family index once we've estabilished that + // at least one instance of this family will be run. + if (next_family_index == family_index) ++next_family_index; } } } @@ -247,6 +207,7 @@ Benchmark::Benchmark(const char* name) min_time_(0), iterations_(0), repetitions_(0), + measure_process_cpu_time_(false), use_real_time_(false), use_manual_time_(false), complexity_(oNone), @@ -258,6 +219,11 @@ Benchmark::Benchmark(const char* name) Benchmark::~Benchmark() {} +Benchmark* Benchmark::Name(const std::string& name) { + SetName(name.c_str()); + return this; +} + Benchmark* Benchmark::Arg(int64_t x) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); args_.push_back({x}); @@ -284,33 +250,41 @@ Benchmark* Benchmark::Ranges( const std::vector>& ranges) { CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(ranges.size())); std::vector> arglists(ranges.size()); - std::size_t total = 1; for (std::size_t i = 0; i < ranges.size(); i++) { AddRange(&arglists[i], ranges[i].first, ranges[i].second, range_multiplier_); - total *= arglists[i].size(); } - std::vector ctr(arglists.size(), 0); + ArgsProduct(arglists); - for (std::size_t i = 0; i < total; i++) { - std::vector tmp; - tmp.reserve(arglists.size()); - - for (std::size_t j = 0; j < arglists.size(); j++) { - tmp.push_back(arglists[j].at(ctr[j])); - } + return this; +} - args_.push_back(std::move(tmp)); +Benchmark* Benchmark::ArgsProduct( + const std::vector>& arglists) { + CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(arglists.size())); - for (std::size_t j = 0; j < arglists.size(); j++) { - if (ctr[j] + 1 < arglists[j].size()) { - ++ctr[j]; - break; - } - ctr[j] = 0; + std::vector indices(arglists.size()); + const std::size_t total = std::accumulate( + std::begin(arglists), std::end(arglists), std::size_t{1}, + [](const std::size_t res, const std::vector& arglist) { + return res * arglist.size(); + }); + std::vector args; + args.reserve(arglists.size()); + for (std::size_t i = 0; i < total; i++) { + for (std::size_t arg = 0; arg < arglists.size(); arg++) { + args.push_back(arglists[arg][indices[arg]]); } + args_.push_back(args); + args.clear(); + + std::size_t arg = 0; + do { + indices[arg] = (indices[arg] + 1) % arglists[arg].size(); + } while (indices[arg++] == 0 && arg < arglists.size()); } + return this; } @@ -328,7 +302,6 @@ Benchmark* Benchmark::ArgNames(const std::vector& names) { Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); - CHECK_GE(start, 0); CHECK_LE(start, limit); for (int64_t arg = start; arg <= limit; arg += step) { args_.push_back({arg}); @@ -360,7 +333,7 @@ Benchmark* Benchmark::MinTime(double t) { return this; } -Benchmark* Benchmark::Iterations(size_t n) { +Benchmark* Benchmark::Iterations(IterationCount n) { CHECK(n > 0); CHECK(IsZero(min_time_)); iterations_ = n; @@ -394,6 +367,12 @@ Benchmark* Benchmark::DisplayAggregatesOnly(bool value) { return this; } +Benchmark* Benchmark::MeasureProcessCPUTime() { + // Can be used together with UseRealTime() / UseManualTime(). + measure_process_cpu_time_ = true; + return this; +} + Benchmark* Benchmark::UseRealTime() { CHECK(!use_manual_time_) << "Cannot set UseRealTime and UseManualTime simultaneously."; diff --git a/libcxx/utils/google-benchmark/src/benchmark_register.h b/libcxx/utils/google-benchmark/src/benchmark_register.h index 0705e219f2fa2..09496607f224d 100644 --- a/libcxx/utils/google-benchmark/src/benchmark_register.h +++ b/libcxx/utils/google-benchmark/src/benchmark_register.h @@ -1,33 +1,108 @@ #ifndef BENCHMARK_REGISTER_H #define BENCHMARK_REGISTER_H +#include #include #include "check.h" +namespace benchmark { +namespace internal { + +// Append the powers of 'mult' in the closed interval [lo, hi]. +// Returns iterator to the start of the inserted range. template -void AddRange(std::vector* dst, T lo, T hi, int mult) { +typename std::vector::iterator +AddPowers(std::vector* dst, T lo, T hi, int mult) { CHECK_GE(lo, 0); CHECK_GE(hi, lo); CHECK_GE(mult, 2); - // Add "lo" - dst->push_back(lo); + const size_t start_offset = dst->size(); static const T kmax = std::numeric_limits::max(); - // Now space out the benchmarks in multiples of "mult" - for (T i = 1; i < kmax / mult; i *= mult) { - if (i >= hi) break; - if (i > lo) { + // Space out the values in multiples of "mult" + for (T i = static_cast(1); i <= hi; i *= mult) { + if (i >= lo) { dst->push_back(i); } + // Break the loop here since multiplying by + // 'mult' would move outside of the range of T + if (i > kmax / mult) break; + } + + return dst->begin() + start_offset; +} + +template +void AddNegatedPowers(std::vector* dst, T lo, T hi, int mult) { + // We negate lo and hi so we require that they cannot be equal to 'min'. + CHECK_GT(lo, std::numeric_limits::min()); + CHECK_GT(hi, std::numeric_limits::min()); + CHECK_GE(hi, lo); + CHECK_LE(hi, 0); + + // Add positive powers, then negate and reverse. + // Casts necessary since small integers get promoted + // to 'int' when negating. + const auto lo_complement = static_cast(-lo); + const auto hi_complement = static_cast(-hi); + + const auto it = AddPowers(dst, hi_complement, lo_complement, mult); + + std::for_each(it, dst->end(), [](T& t) { t *= -1; }); + std::reverse(it, dst->end()); +} + +template +void AddRange(std::vector* dst, T lo, T hi, int mult) { + static_assert(std::is_integral::value && std::is_signed::value, + "Args type must be a signed integer"); + + CHECK_GE(hi, lo); + CHECK_GE(mult, 2); + + // Add "lo" + dst->push_back(lo); + + // Handle lo == hi as a special case, so we then know + // lo < hi and so it is safe to add 1 to lo and subtract 1 + // from hi without falling outside of the range of T. + if (lo == hi) return; + + // Ensure that lo_inner <= hi_inner below. + if (lo + 1 == hi) { + dst->push_back(hi); + return; } - // Add "hi" (if different from "lo") - if (hi != lo) { + // Add all powers of 'mult' in the range [lo+1, hi-1] (inclusive). + const auto lo_inner = static_cast(lo + 1); + const auto hi_inner = static_cast(hi - 1); + + // Insert negative values + if (lo_inner < 0) { + AddNegatedPowers(dst, lo_inner, std::min(hi_inner, T{-1}), mult); + } + + // Treat 0 as a special case (see discussion on #762). + if (lo < 0 && hi >= 0) { + dst->push_back(0); + } + + // Insert positive values + if (hi_inner > 0) { + AddPowers(dst, std::max(lo_inner, T{1}), hi_inner, mult); + } + + // Add "hi" (if different from last value). + if (hi != dst->back()) { dst->push_back(hi); } } +} // namespace internal +} // namespace benchmark + #endif // BENCHMARK_REGISTER_H diff --git a/libcxx/utils/google-benchmark/src/benchmark_runner.cc b/libcxx/utils/google-benchmark/src/benchmark_runner.cc index 38faeec8e3ee7..6742d42dbecd3 100644 --- a/libcxx/utils/google-benchmark/src/benchmark_runner.cc +++ b/libcxx/utils/google-benchmark/src/benchmark_runner.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "benchmark_runner.h" + #include "benchmark/benchmark.h" #include "benchmark_api_internal.h" #include "internal_macros.h" @@ -45,6 +46,7 @@ #include "internal_macros.h" #include "log.h" #include "mutex.h" +#include "perf_counters.h" #include "re.h" #include "statistics.h" #include "string_util.h" @@ -59,34 +61,41 @@ MemoryManager* memory_manager = nullptr; namespace { -static const size_t kMaxIterations = 1000000000; +static constexpr IterationCount kMaxIterations = 1000000000; BenchmarkReporter::Run CreateRunReport( const benchmark::internal::BenchmarkInstance& b, - const internal::ThreadManager::Result& results, size_t memory_iterations, - const MemoryManager::Result& memory_result, double seconds) { + const internal::ThreadManager::Result& results, + IterationCount memory_iterations, + const MemoryManager::Result& memory_result, double seconds, + int64_t repetition_index, int64_t repeats) { // Create report about this benchmark run. BenchmarkReporter::Run report; - report.run_name = b.name; + report.run_name = b.name(); + report.family_index = b.family_index(); + report.per_family_instance_index = b.per_family_instance_index(); report.error_occurred = results.has_error_; report.error_message = results.error_message_; report.report_label = results.report_label_; // This is the total iterations across all threads. report.iterations = results.iterations; - report.time_unit = b.time_unit; + report.time_unit = b.time_unit(); + report.threads = b.threads(); + report.repetition_index = repetition_index; + report.repetitions = repeats; if (!report.error_occurred) { - if (b.use_manual_time) { + if (b.use_manual_time()) { report.real_accumulated_time = results.manual_time_used; } else { report.real_accumulated_time = results.real_time_used; } report.cpu_accumulated_time = results.cpu_time_used; report.complexity_n = results.complexity_n; - report.complexity = b.complexity; - report.complexity_lambda = b.complexity_lambda; - report.statistics = b.statistics; + report.complexity = b.complexity(); + report.complexity_lambda = b.complexity_lambda(); + report.statistics = &b.statistics(); report.counters = results.counters; if (memory_iterations > 0) { @@ -98,18 +107,24 @@ BenchmarkReporter::Run CreateRunReport( report.max_bytes_used = memory_result.max_bytes_used; } - internal::Finish(&report.counters, results.iterations, seconds, b.threads); + internal::Finish(&report.counters, results.iterations, seconds, + b.threads()); } return report; } // Execute one thread of benchmark b for the specified number of iterations. -// Adds the stats collected for the thread into *total. -void RunInThread(const BenchmarkInstance* b, size_t iters, int thread_id, - ThreadManager* manager) { - internal::ThreadTimer timer; - State st = b->Run(iters, thread_id, &timer, manager); - CHECK(st.iterations() >= st.max_iterations) +// Adds the stats collected for the thread into manager->results. +void RunInThread(const BenchmarkInstance* b, IterationCount iters, + int thread_id, ThreadManager* manager, + PerfCountersMeasurement* perf_counters_measurement) { + internal::ThreadTimer timer( + b->measure_process_cpu_time() + ? internal::ThreadTimer::CreateProcessCpuTime() + : internal::ThreadTimer::Create()); + State st = + b->Run(iters, thread_id, &timer, manager, perf_counters_measurement); + CHECK(st.error_occurred() || st.iterations() >= st.max_iterations) << "Benchmark returned before State::KeepRunning() returned false!"; { MutexLock l(manager->GetBenchmarkMutex()); @@ -124,225 +139,209 @@ void RunInThread(const BenchmarkInstance* b, size_t iters, int thread_id, manager->NotifyThreadComplete(); } -class BenchmarkRunner { - public: - BenchmarkRunner(const benchmark::internal::BenchmarkInstance& b_, - std::vector* complexity_reports_) - : b(b_), - complexity_reports(*complexity_reports_), - min_time(!IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time), - repeats(b.repetitions != 0 ? b.repetitions +} // end namespace + +BenchmarkRunner::BenchmarkRunner( + const benchmark::internal::BenchmarkInstance& b_, + BenchmarkReporter::PerFamilyRunReports* reports_for_family_) + : b(b_), + reports_for_family(reports_for_family_), + min_time(!IsZero(b.min_time()) ? b.min_time() : FLAGS_benchmark_min_time), + repeats(b.repetitions() != 0 ? b.repetitions() : FLAGS_benchmark_repetitions), - has_explicit_iteration_count(b.iterations != 0), - pool(b.threads - 1), - iters(has_explicit_iteration_count ? b.iterations : 1) { + has_explicit_iteration_count(b.iterations() != 0), + pool(b.threads() - 1), + iters(has_explicit_iteration_count ? b.iterations() : 1), + perf_counters_measurement( + PerfCounters::Create(StrSplit(FLAGS_benchmark_perf_counters, ','))), + perf_counters_measurement_ptr(perf_counters_measurement.IsValid() + ? &perf_counters_measurement + : nullptr) { + run_results.display_report_aggregates_only = + (FLAGS_benchmark_report_aggregates_only || + FLAGS_benchmark_display_aggregates_only); + run_results.file_report_aggregates_only = + FLAGS_benchmark_report_aggregates_only; + if (b.aggregation_report_mode() != internal::ARM_Unspecified) { run_results.display_report_aggregates_only = - (FLAGS_benchmark_report_aggregates_only || - FLAGS_benchmark_display_aggregates_only); + (b.aggregation_report_mode() & + internal::ARM_DisplayReportAggregatesOnly); run_results.file_report_aggregates_only = - FLAGS_benchmark_report_aggregates_only; - if (b.aggregation_report_mode != internal::ARM_Unspecified) { - run_results.display_report_aggregates_only = - (b.aggregation_report_mode & - internal::ARM_DisplayReportAggregatesOnly); - run_results.file_report_aggregates_only = - (b.aggregation_report_mode & internal::ARM_FileReportAggregatesOnly); - } + (b.aggregation_report_mode() & internal::ARM_FileReportAggregatesOnly); + CHECK(FLAGS_benchmark_perf_counters.empty() || + perf_counters_measurement.IsValid()) + << "Perf counters were requested but could not be set up."; + } +} - for (int repetition_num = 0; repetition_num < repeats; repetition_num++) { - const bool is_the_first_repetition = repetition_num == 0; - DoOneRepetition(is_the_first_repetition); - } +BenchmarkRunner::IterationResults BenchmarkRunner::DoNIterations() { + VLOG(2) << "Running " << b.name().str() << " for " << iters << "\n"; - // Calculate additional statistics - run_results.aggregates_only = ComputeStats(run_results.non_aggregates); + std::unique_ptr manager; + manager.reset(new internal::ThreadManager(b.threads())); - // Maybe calculate complexity report - if ((b.complexity != oNone) && b.last_benchmark_instance) { - auto additional_run_stats = ComputeBigO(complexity_reports); - run_results.aggregates_only.insert(run_results.aggregates_only.end(), - additional_run_stats.begin(), - additional_run_stats.end()); - complexity_reports.clear(); - } + // Run all but one thread in separate threads + for (std::size_t ti = 0; ti < pool.size(); ++ti) { + pool[ti] = std::thread(&RunInThread, &b, iters, static_cast(ti + 1), + manager.get(), perf_counters_measurement_ptr); } + // And run one thread here directly. + // (If we were asked to run just one thread, we don't create new threads.) + // Yes, we need to do this here *after* we start the separate threads. + RunInThread(&b, iters, 0, manager.get(), perf_counters_measurement_ptr); - RunResults&& get_results() { return std::move(run_results); } + // The main thread has finished. Now let's wait for the other threads. + manager->WaitForAllThreads(); + for (std::thread& thread : pool) thread.join(); - private: - RunResults run_results; + IterationResults i; + // Acquire the measurements/counters from the manager, UNDER THE LOCK! + { + MutexLock l(manager->GetBenchmarkMutex()); + i.results = manager->results; + } - const benchmark::internal::BenchmarkInstance& b; - std::vector& complexity_reports; + // And get rid of the manager. + manager.reset(); - const double min_time; - const int repeats; - const bool has_explicit_iteration_count; + // Adjust real/manual time stats since they were reported per thread. + i.results.real_time_used /= b.threads(); + i.results.manual_time_used /= b.threads(); + // If we were measuring whole-process CPU usage, adjust the CPU time too. + if (b.measure_process_cpu_time()) i.results.cpu_time_used /= b.threads(); - std::vector pool; + VLOG(2) << "Ran in " << i.results.cpu_time_used << "/" + << i.results.real_time_used << "\n"; - size_t iters; // preserved between repetitions! - // So only the first repetition has to find/calculate it, - // the other repetitions will just use that precomputed iteration count. + // By using KeepRunningBatch a benchmark can iterate more times than + // requested, so take the iteration count from i.results. + i.iters = i.results.iterations / b.threads(); - struct IterationResults { - internal::ThreadManager::Result results; - size_t iters; - double seconds; - }; - IterationResults DoNIterations() { - VLOG(2) << "Running " << b.name << " for " << iters << "\n"; + // Base decisions off of real time if requested by this benchmark. + i.seconds = i.results.cpu_time_used; + if (b.use_manual_time()) { + i.seconds = i.results.manual_time_used; + } else if (b.use_real_time()) { + i.seconds = i.results.real_time_used; + } - std::unique_ptr manager; - manager.reset(new internal::ThreadManager(b.threads)); + return i; +} - // Run all but one thread in separate threads - for (std::size_t ti = 0; ti < pool.size(); ++ti) { - pool[ti] = std::thread(&RunInThread, &b, iters, static_cast(ti + 1), - manager.get()); - } - // And run one thread here directly. - // (If we were asked to run just one thread, we don't create new threads.) - // Yes, we need to do this here *after* we start the separate threads. - RunInThread(&b, iters, 0, manager.get()); +IterationCount BenchmarkRunner::PredictNumItersNeeded( + const IterationResults& i) const { + // See how much iterations should be increased by. + // Note: Avoid division by zero with max(seconds, 1ns). + double multiplier = min_time * 1.4 / std::max(i.seconds, 1e-9); + // If our last run was at least 10% of FLAGS_benchmark_min_time then we + // use the multiplier directly. + // Otherwise we use at most 10 times expansion. + // NOTE: When the last run was at least 10% of the min time the max + // expansion should be 14x. + bool is_significant = (i.seconds / min_time) > 0.1; + multiplier = is_significant ? multiplier : std::min(10.0, multiplier); + if (multiplier <= 1.0) multiplier = 2.0; + + // So what seems to be the sufficiently-large iteration count? Round up. + const IterationCount max_next_iters = static_cast( + std::lround(std::max(multiplier * static_cast(i.iters), + static_cast(i.iters) + 1.0))); + // But we do have *some* sanity limits though.. + const IterationCount next_iters = std::min(max_next_iters, kMaxIterations); + + VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n"; + return next_iters; // round up before conversion to integer. +} - // The main thread has finished. Now let's wait for the other threads. - manager->WaitForAllThreads(); - for (std::thread& thread : pool) thread.join(); +bool BenchmarkRunner::ShouldReportIterationResults( + const IterationResults& i) const { + // Determine if this run should be reported; + // Either it has run for a sufficient amount of time + // or because an error was reported. + return i.results.has_error_ || + i.iters >= kMaxIterations || // Too many iterations already. + i.seconds >= min_time || // The elapsed time is large enough. + // CPU time is specified but the elapsed real time greatly exceeds + // the minimum time. + // Note that user provided timers are except from this sanity check. + ((i.results.real_time_used >= 5 * min_time) && !b.use_manual_time()); +} - IterationResults i; - // Acquire the measurements/counters from the manager, UNDER THE LOCK! - { - MutexLock l(manager->GetBenchmarkMutex()); - i.results = manager->results; - } +void BenchmarkRunner::DoOneRepetition() { + assert(HasRepeatsRemaining() && "Already done all repetitions?"); + + const bool is_the_first_repetition = num_repetitions_done == 0; + IterationResults i; + + // We *may* be gradually increasing the length (iteration count) + // of the benchmark until we decide the results are significant. + // And once we do, we report those last results and exit. + // Please do note that the if there are repetitions, the iteration count + // is *only* calculated for the *first* repetition, and other repetitions + // simply use that precomputed iteration count. + for (;;) { + i = DoNIterations(); + + // Do we consider the results to be significant? + // If we are doing repetitions, and the first repetition was already done, + // it has calculated the correct iteration time, so we have run that very + // iteration count just now. No need to calculate anything. Just report. + // Else, the normal rules apply. + const bool results_are_significant = !is_the_first_repetition || + has_explicit_iteration_count || + ShouldReportIterationResults(i); + + if (results_are_significant) break; // Good, let's report them! + + // Nope, bad iteration. Let's re-estimate the hopefully-sufficient + // iteration count, and run the benchmark again... + + iters = PredictNumItersNeeded(i); + assert(iters > i.iters && + "if we did more iterations than we want to do the next time, " + "then we should have accepted the current iteration run."); + } - // And get rid of the manager. + // Oh, one last thing, we need to also produce the 'memory measurements'.. + MemoryManager::Result memory_result; + IterationCount memory_iterations = 0; + if (memory_manager != nullptr) { + // Only run a few iterations to reduce the impact of one-time + // allocations in benchmarks that are not properly managed. + memory_iterations = std::min(16, iters); + memory_manager->Start(); + std::unique_ptr manager; + manager.reset(new internal::ThreadManager(1)); + RunInThread(&b, memory_iterations, 0, manager.get(), + perf_counters_measurement_ptr); + manager->WaitForAllThreads(); manager.reset(); - // Adjust real/manual time stats since they were reported per thread. - i.results.real_time_used /= b.threads; - i.results.manual_time_used /= b.threads; - - VLOG(2) << "Ran in " << i.results.cpu_time_used << "/" - << i.results.real_time_used << "\n"; - - // So for how long were we running? - i.iters = iters; - // Base decisions off of real time if requested by this benchmark. - i.seconds = i.results.cpu_time_used; - if (b.use_manual_time) { - i.seconds = i.results.manual_time_used; - } else if (b.use_real_time) { - i.seconds = i.results.real_time_used; - } - - return i; + memory_manager->Stop(&memory_result); } - size_t PredictNumItersNeeded(const IterationResults& i) const { - // See how much iterations should be increased by. - // Note: Avoid division by zero with max(seconds, 1ns). - double multiplier = min_time * 1.4 / std::max(i.seconds, 1e-9); - // If our last run was at least 10% of FLAGS_benchmark_min_time then we - // use the multiplier directly. - // Otherwise we use at most 10 times expansion. - // NOTE: When the last run was at least 10% of the min time the max - // expansion should be 14x. - bool is_significant = (i.seconds / min_time) > 0.1; - multiplier = is_significant ? multiplier : std::min(10.0, multiplier); - if (multiplier <= 1.0) multiplier = 2.0; - - // So what seems to be the sufficiently-large iteration count? Round up. - const size_t max_next_iters = - 0.5 + std::max(multiplier * i.iters, i.iters + 1.0); - // But we do have *some* sanity limits though.. - const size_t next_iters = std::min(max_next_iters, kMaxIterations); - - VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n"; - return next_iters; // round up before conversion to integer. - } + // Ok, now actualy report. + BenchmarkReporter::Run report = + CreateRunReport(b, i.results, memory_iterations, memory_result, i.seconds, + num_repetitions_done, repeats); - bool ShouldReportIterationResults(const IterationResults& i) const { - // Determine if this run should be reported; - // Either it has run for a sufficient amount of time - // or because an error was reported. - return i.results.has_error_ || - i.iters >= kMaxIterations || // Too many iterations already. - i.seconds >= min_time || // The elapsed time is large enough. - // CPU time is specified but the elapsed real time greatly exceeds - // the minimum time. - // Note that user provided timers are except from this sanity check. - ((i.results.real_time_used >= 5 * min_time) && !b.use_manual_time); + if (reports_for_family) { + ++reports_for_family->num_runs_done; + if (!report.error_occurred) reports_for_family->Runs.push_back(report); } - void DoOneRepetition(bool is_the_first_repetition) { - IterationResults i; - - // We *may* be gradually increasing the length (iteration count) - // of the benchmark until we decide the results are significant. - // And once we do, we report those last results and exit. - // Please do note that the if there are repetitions, the iteration count - // is *only* calculated for the *first* repetition, and other repetitions - // simply use that precomputed iteration count. - for (;;) { - i = DoNIterations(); - - // Do we consider the results to be significant? - // If we are doing repetitions, and the first repetition was already done, - // it has calculated the correct iteration time, so we have run that very - // iteration count just now. No need to calculate anything. Just report. - // Else, the normal rules apply. - const bool results_are_significant = !is_the_first_repetition || - has_explicit_iteration_count || - ShouldReportIterationResults(i); - - if (results_are_significant) break; // Good, let's report them! - - // Nope, bad iteration. Let's re-estimate the hopefully-sufficient - // iteration count, and run the benchmark again... - - iters = PredictNumItersNeeded(i); - assert(iters > i.iters && - "if we did more iterations than we want to do the next time, " - "then we should have accepted the current iteration run."); - } - - // Oh, one last thing, we need to also produce the 'memory measurements'.. - MemoryManager::Result memory_result; - size_t memory_iterations = 0; - if (memory_manager != nullptr) { - // Only run a few iterations to reduce the impact of one-time - // allocations in benchmarks that are not properly managed. - memory_iterations = std::min(16, iters); - memory_manager->Start(); - std::unique_ptr manager; - manager.reset(new internal::ThreadManager(1)); - RunInThread(&b, memory_iterations, 0, manager.get()); - manager->WaitForAllThreads(); - manager.reset(); - - memory_manager->Stop(&memory_result); - } - - // Ok, now actualy report. - BenchmarkReporter::Run report = CreateRunReport( - b, i.results, memory_iterations, memory_result, i.seconds); + run_results.non_aggregates.push_back(report); - if (!report.error_occurred && b.complexity != oNone) - complexity_reports.push_back(report); + ++num_repetitions_done; +} - run_results.non_aggregates.push_back(report); - } -}; +RunResults&& BenchmarkRunner::GetResults() { + assert(!HasRepeatsRemaining() && "Did not run all repetitions yet?"); -} // end namespace + // Calculate additional statistics over the repetitions of this instance. + run_results.aggregates_only = ComputeStats(run_results.non_aggregates); -RunResults RunBenchmark( - const benchmark::internal::BenchmarkInstance& b, - std::vector* complexity_reports) { - internal::BenchmarkRunner r(b, complexity_reports); - return r.get_results(); + return std::move(run_results); } } // end namespace internal diff --git a/libcxx/utils/google-benchmark/src/benchmark_runner.h b/libcxx/utils/google-benchmark/src/benchmark_runner.h index 96e8282a11aa8..8a855236b2277 100644 --- a/libcxx/utils/google-benchmark/src/benchmark_runner.h +++ b/libcxx/utils/google-benchmark/src/benchmark_runner.h @@ -15,8 +15,13 @@ #ifndef BENCHMARK_RUNNER_H_ #define BENCHMARK_RUNNER_H_ +#include +#include + #include "benchmark_api_internal.h" #include "internal_macros.h" +#include "perf_counters.h" +#include "thread_manager.h" DECLARE_double(benchmark_min_time); @@ -26,6 +31,8 @@ DECLARE_bool(benchmark_report_aggregates_only); DECLARE_bool(benchmark_display_aggregates_only); +DECLARE_string(benchmark_perf_counters); + namespace benchmark { namespace internal { @@ -40,9 +47,57 @@ struct RunResults { bool file_report_aggregates_only = false; }; -RunResults RunBenchmark( - const benchmark::internal::BenchmarkInstance& b, - std::vector* complexity_reports); +class BenchmarkRunner { + public: + BenchmarkRunner(const benchmark::internal::BenchmarkInstance& b_, + BenchmarkReporter::PerFamilyRunReports* reports_for_family); + + int GetNumRepeats() const { return repeats; } + + bool HasRepeatsRemaining() const { + return GetNumRepeats() != num_repetitions_done; + } + + void DoOneRepetition(); + + RunResults&& GetResults(); + + BenchmarkReporter::PerFamilyRunReports* GetReportsForFamily() const { + return reports_for_family; + }; + + private: + RunResults run_results; + + const benchmark::internal::BenchmarkInstance& b; + BenchmarkReporter::PerFamilyRunReports* reports_for_family; + + const double min_time; + const int repeats; + const bool has_explicit_iteration_count; + + int num_repetitions_done = 0; + + std::vector pool; + + IterationCount iters; // preserved between repetitions! + // So only the first repetition has to find/calculate it, + // the other repetitions will just use that precomputed iteration count. + + PerfCountersMeasurement perf_counters_measurement; + PerfCountersMeasurement* const perf_counters_measurement_ptr; + + struct IterationResults { + internal::ThreadManager::Result results; + IterationCount iters; + double seconds; + }; + IterationResults DoNIterations(); + + IterationCount PredictNumItersNeeded(const IterationResults& i) const; + + bool ShouldReportIterationResults(const IterationResults& i) const; +}; } // namespace internal diff --git a/libcxx/utils/google-benchmark/src/commandlineflags.cc b/libcxx/utils/google-benchmark/src/commandlineflags.cc index 734e88bbec686..5724aaa29402e 100644 --- a/libcxx/utils/google-benchmark/src/commandlineflags.cc +++ b/libcxx/utils/google-benchmark/src/commandlineflags.cc @@ -14,13 +14,20 @@ #include "commandlineflags.h" +#include #include #include #include #include #include +#include +#include + +#include "../src/string_util.h" namespace benchmark { +namespace { + // Parses 'str' for a 32-bit signed integer. If successful, writes // the result to *value and returns true; otherwise leaves *value // unchanged and returns false. @@ -75,6 +82,30 @@ bool ParseDouble(const std::string& src_text, const char* str, double* value) { return true; } +// Parses 'str' into KV pairs. If successful, writes the result to *value and +// returns true; otherwise leaves *value unchanged and returns false. +bool ParseKvPairs(const std::string& src_text, const char* str, + std::map* value) { + std::map kvs; + for (const auto& kvpair : StrSplit(str, ',')) { + const auto kv = StrSplit(kvpair, '='); + if (kv.size() != 2) { + std::cerr << src_text << " is expected to be a comma-separated list of " + << "= strings, but actually has value \"" << str + << "\".\n"; + return false; + } + if (!kvs.emplace(kv[0], kv[1]).second) { + std::cerr << src_text << " is expected to contain unique keys but key \"" + << kv[0] << "\" was repeated.\n"; + return false; + } + } + + *value = kvs; + return true; +} + // Returns the name of the environment variable corresponding to the // given flag. For example, FlagToEnvVar("foo") will return // "BENCHMARK_FOO" in the open-source version. @@ -85,47 +116,59 @@ static std::string FlagToEnvVar(const char* flag) { for (size_t i = 0; i != flag_str.length(); ++i) env_var += static_cast(::toupper(flag_str.c_str()[i])); - return "BENCHMARK_" + env_var; + return env_var; } -// Reads and returns the Boolean environment variable corresponding to -// the given flag; if it's not set, returns default_value. -// -// The value is considered true iff it's not "0". -bool BoolFromEnv(const char* flag, bool default_value) { +} // namespace + +bool BoolFromEnv(const char* flag, bool default_val) { const std::string env_var = FlagToEnvVar(flag); - const char* const string_value = getenv(env_var.c_str()); - return string_value == nullptr ? default_value - : strcmp(string_value, "0") != 0; + const char* const value_str = getenv(env_var.c_str()); + return value_str == nullptr ? default_val : IsTruthyFlagValue(value_str); } -// Reads and returns a 32-bit integer stored in the environment -// variable corresponding to the given flag; if it isn't set or -// doesn't represent a valid 32-bit integer, returns default_value. -int32_t Int32FromEnv(const char* flag, int32_t default_value) { +int32_t Int32FromEnv(const char* flag, int32_t default_val) { const std::string env_var = FlagToEnvVar(flag); - const char* const string_value = getenv(env_var.c_str()); - if (string_value == nullptr) { - // The environment variable is not set. - return default_value; + const char* const value_str = getenv(env_var.c_str()); + int32_t value = default_val; + if (value_str == nullptr || + !ParseInt32(std::string("Environment variable ") + env_var, value_str, + &value)) { + return default_val; } + return value; +} - int32_t result = default_value; - if (!ParseInt32(std::string("Environment variable ") + env_var, string_value, - &result)) { - std::cout << "The default value " << default_value << " is used.\n"; - return default_value; +double DoubleFromEnv(const char* flag, double default_val) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value_str = getenv(env_var.c_str()); + double value = default_val; + if (value_str == nullptr || + !ParseDouble(std::string("Environment variable ") + env_var, value_str, + &value)) { + return default_val; } - - return result; + return value; } -// Reads and returns the string environment variable corresponding to -// the given flag; if it's not set, returns default_value. -const char* StringFromEnv(const char* flag, const char* default_value) { +const char* StringFromEnv(const char* flag, const char* default_val) { const std::string env_var = FlagToEnvVar(flag); const char* const value = getenv(env_var.c_str()); - return value == nullptr ? default_value : value; + return value == nullptr ? default_val : value; +} + +std::map KvPairsFromEnv( + const char* flag, std::map default_val) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value_str = getenv(env_var.c_str()); + + if (value_str == nullptr) return default_val; + + std::map value; + if (!ParseKvPairs("Environment variable " + env_var, value_str, &value)) { + return default_val; + } + return value; } // Parses a string as a command line flag. The string should have @@ -205,14 +248,39 @@ bool ParseStringFlag(const char* str, const char* flag, std::string* value) { return true; } +bool ParseKeyValueFlag( + const char* str, const char* flag, + std::map* value) { + const char* const value_str = ParseFlagValue(str, flag, false); + + if (value_str == nullptr) return false; + + for (const auto& kvpair : StrSplit(value_str, ',')) { + const auto kv = StrSplit(kvpair, '='); + if (kv.size() != 2) return false; + value->emplace(kv[0], kv[1]); + } + + return true; +} + bool IsFlag(const char* str, const char* flag) { return (ParseFlagValue(str, flag, true) != nullptr); } bool IsTruthyFlagValue(const std::string& value) { - if (value.empty()) return true; - char ch = value[0]; - return isalnum(ch) && - !(ch == '0' || ch == 'f' || ch == 'F' || ch == 'n' || ch == 'N'); + if (value.size() == 1) { + char v = value[0]; + return isalnum(v) && + !(v == '0' || v == 'f' || v == 'F' || v == 'n' || v == 'N'); + } else if (!value.empty()) { + std::string value_lower(value); + std::transform(value_lower.begin(), value_lower.end(), value_lower.begin(), + [](char c) { return static_cast(::tolower(c)); }); + return !(value_lower == "false" || value_lower == "no" || + value_lower == "off"); + } else + return true; } + } // end namespace benchmark diff --git a/libcxx/utils/google-benchmark/src/commandlineflags.h b/libcxx/utils/google-benchmark/src/commandlineflags.h index 945c9a9fc4af3..0c988cccb3ae1 100644 --- a/libcxx/utils/google-benchmark/src/commandlineflags.h +++ b/libcxx/utils/google-benchmark/src/commandlineflags.h @@ -2,6 +2,7 @@ #define BENCHMARK_COMMANDLINEFLAGS_H_ #include +#include #include // Macro for referencing flags. @@ -10,31 +11,61 @@ // Macros for declaring flags. #define DECLARE_bool(name) extern bool FLAG(name) #define DECLARE_int32(name) extern int32_t FLAG(name) -#define DECLARE_int64(name) extern int64_t FLAG(name) #define DECLARE_double(name) extern double FLAG(name) #define DECLARE_string(name) extern std::string FLAG(name) +#define DECLARE_kvpairs(name) \ + extern std::map FLAG(name) // Macros for defining flags. -#define DEFINE_bool(name, default_val, doc) bool FLAG(name) = (default_val) -#define DEFINE_int32(name, default_val, doc) int32_t FLAG(name) = (default_val) -#define DEFINE_int64(name, default_val, doc) int64_t FLAG(name) = (default_val) -#define DEFINE_double(name, default_val, doc) double FLAG(name) = (default_val) -#define DEFINE_string(name, default_val, doc) \ - std::string FLAG(name) = (default_val) +#define DEFINE_bool(name, default_val) \ + bool FLAG(name) = benchmark::BoolFromEnv(#name, default_val) +#define DEFINE_int32(name, default_val) \ + int32_t FLAG(name) = benchmark::Int32FromEnv(#name, default_val) +#define DEFINE_double(name, default_val) \ + double FLAG(name) = benchmark::DoubleFromEnv(#name, default_val) +#define DEFINE_string(name, default_val) \ + std::string FLAG(name) = benchmark::StringFromEnv(#name, default_val) +#define DEFINE_kvpairs(name, default_val) \ + std::map FLAG(name) = \ + benchmark::KvPairsFromEnv(#name, default_val) namespace benchmark { -// Parses 'str' for a 32-bit signed integer. If successful, writes the result -// to *value and returns true; otherwise leaves *value unchanged and returns -// false. -bool ParseInt32(const std::string& src_text, const char* str, int32_t* value); -// Parses a bool/Int32/string from the environment variable -// corresponding to the given Google Test flag. +// Parses a bool from the environment variable corresponding to the given flag. +// +// If the variable exists, returns IsTruthyFlagValue() value; if not, +// returns the given default value. bool BoolFromEnv(const char* flag, bool default_val); + +// Parses an Int32 from the environment variable corresponding to the given +// flag. +// +// If the variable exists, returns ParseInt32() value; if not, returns +// the given default value. int32_t Int32FromEnv(const char* flag, int32_t default_val); + +// Parses an Double from the environment variable corresponding to the given +// flag. +// +// If the variable exists, returns ParseDouble(); if not, returns +// the given default value. double DoubleFromEnv(const char* flag, double default_val); + +// Parses a string from the environment variable corresponding to the given +// flag. +// +// If variable exists, returns its value; if not, returns +// the given default value. const char* StringFromEnv(const char* flag, const char* default_val); +// Parses a set of kvpairs from the environment variable corresponding to the +// given flag. +// +// If variable exists, returns its value; if not, returns +// the given default value. +std::map KvPairsFromEnv( + const char* flag, std::map default_val); + // Parses a string for a bool flag, in the form of either // "--flag=value" or "--flag". // @@ -46,34 +77,40 @@ const char* StringFromEnv(const char* flag, const char* default_val); // true. On failure, returns false without changing *value. bool ParseBoolFlag(const char* str, const char* flag, bool* value); -// Parses a string for an Int32 flag, in the form of -// "--flag=value". +// Parses a string for an Int32 flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. bool ParseInt32Flag(const char* str, const char* flag, int32_t* value); -// Parses a string for a Double flag, in the form of -// "--flag=value". +// Parses a string for a Double flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. bool ParseDoubleFlag(const char* str, const char* flag, double* value); -// Parses a string for a string flag, in the form of -// "--flag=value". +// Parses a string for a string flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. bool ParseStringFlag(const char* str, const char* flag, std::string* value); +// Parses a string for a kvpairs flag in the form "--flag=key=value,key=value" +// +// On success, stores the value of the flag in *value and returns true. On +// failure returns false, though *value may have been mutated. +bool ParseKeyValueFlag(const char* str, const char* flag, + std::map* value); + // Returns true if the string matches the flag. bool IsFlag(const char* str, const char* flag); // Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or -// some non-alphanumeric character. As a special case, also returns true if -// value is the empty string. +// some non-alphanumeric character. Also returns false if the value matches +// one of 'no', 'false', 'off' (case-insensitive). As a special case, also +// returns true if value is the empty string. bool IsTruthyFlagValue(const std::string& value); + } // end namespace benchmark #endif // BENCHMARK_COMMANDLINEFLAGS_H_ diff --git a/libcxx/utils/google-benchmark/src/complexity.cc b/libcxx/utils/google-benchmark/src/complexity.cc index 6ef17660c9546..29f7c3b03155a 100644 --- a/libcxx/utils/google-benchmark/src/complexity.cc +++ b/libcxx/utils/google-benchmark/src/complexity.cc @@ -29,20 +29,23 @@ BigOFunc* FittingCurve(BigO complexity) { static const double kLog2E = 1.44269504088896340736; switch (complexity) { case oN: - return [](int64_t n) -> double { return static_cast(n); }; + return [](IterationCount n) -> double { return static_cast(n); }; case oNSquared: - return [](int64_t n) -> double { return std::pow(n, 2); }; + return [](IterationCount n) -> double { return std::pow(n, 2); }; case oNCubed: - return [](int64_t n) -> double { return std::pow(n, 3); }; + return [](IterationCount n) -> double { return std::pow(n, 3); }; case oLogN: /* Note: can't use log2 because Android's GNU STL lacks it */ - return [](int64_t n) { return kLog2E * log(static_cast(n)); }; + return + [](IterationCount n) { return kLog2E * log(static_cast(n)); }; case oNLogN: /* Note: can't use log2 because Android's GNU STL lacks it */ - return [](int64_t n) { return kLog2E * n * log(static_cast(n)); }; + return [](IterationCount n) { + return kLog2E * n * log(static_cast(n)); + }; case o1: default: - return [](int64_t) { return 1.0; }; + return [](IterationCount) { return 1.0; }; } } @@ -79,7 +82,6 @@ std::string GetBigOString(BigO complexity) { LeastSq MinimalLeastSq(const std::vector& n, const std::vector& time, BigOFunc* fitting_curve) { - double sigma_gn = 0.0; double sigma_gn_squared = 0.0; double sigma_time = 0.0; double sigma_time_gn = 0.0; @@ -87,7 +89,6 @@ LeastSq MinimalLeastSq(const std::vector& n, // Calculate least square fitting parameter for (size_t i = 0; i < n.size(); ++i) { double gn_i = fitting_curve(n[i]); - sigma_gn += gn_i; sigma_gn_squared += gn_i * gn_i; sigma_time += time[i]; sigma_time_gn += time[i] * gn_i; @@ -183,14 +184,21 @@ std::vector ComputeBigO( result_real = MinimalLeastSq(n, real_time, result_cpu.complexity); } - std::string run_name = reports[0].benchmark_name().substr( - 0, reports[0].benchmark_name().find('/')); + // Drop the 'args' when reporting complexity. + auto run_name = reports[0].run_name; + run_name.args.clear(); // Get the data from the accumulator to BenchmarkReporter::Run's. Run big_o; big_o.run_name = run_name; + big_o.family_index = reports[0].family_index; + big_o.per_family_instance_index = reports[0].per_family_instance_index; big_o.run_type = BenchmarkReporter::Run::RT_Aggregate; + big_o.repetitions = reports[0].repetitions; + big_o.repetition_index = Run::no_repetition_index; + big_o.threads = reports[0].threads; big_o.aggregate_name = "BigO"; + big_o.report_label = reports[0].report_label; big_o.iterations = 0; big_o.real_accumulated_time = result_real.coef; big_o.cpu_accumulated_time = result_cpu.coef; @@ -207,11 +215,15 @@ std::vector ComputeBigO( // Only add label to mean/stddev if it is same for all runs Run rms; rms.run_name = run_name; - big_o.report_label = reports[0].report_label; + rms.family_index = reports[0].family_index; + rms.per_family_instance_index = reports[0].per_family_instance_index; rms.run_type = BenchmarkReporter::Run::RT_Aggregate; rms.aggregate_name = "RMS"; rms.report_label = big_o.report_label; rms.iterations = 0; + rms.repetition_index = Run::no_repetition_index; + rms.repetitions = reports[0].repetitions; + rms.threads = reports[0].threads; rms.real_accumulated_time = result_real.rms / multiplier; rms.cpu_accumulated_time = result_cpu.rms / multiplier; rms.report_rms = true; diff --git a/libcxx/utils/google-benchmark/src/console_reporter.cc b/libcxx/utils/google-benchmark/src/console_reporter.cc index ca364727cb46a..6fd764525e814 100644 --- a/libcxx/utils/google-benchmark/src/console_reporter.cc +++ b/libcxx/utils/google-benchmark/src/console_reporter.cc @@ -12,21 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "benchmark/benchmark.h" -#include "complexity.h" -#include "counter.h" - #include #include #include +#include #include #include #include #include +#include "benchmark/benchmark.h" #include "check.h" #include "colorprint.h" #include "commandlineflags.h" +#include "complexity.h" +#include "counter.h" #include "internal_macros.h" #include "string_util.h" #include "timers.h" @@ -64,9 +64,8 @@ void ConsoleReporter::PrintHeader(const Run& run) { str += " UserCounters..."; } } - str += "\n"; std::string line = std::string(str.length(), '-'); - GetOutputStream() << line << "\n" << str << line << "\n"; + GetOutputStream() << line << "\n" << str << "\n" << line << "\n"; } void ConsoleReporter::ReportRuns(const std::vector& reports) { @@ -157,16 +156,14 @@ void ConsoleReporter::PrintRunData(const Run& result) { const std::size_t cNameLen = std::max(std::string::size_type(10), c.first.length()); auto const& s = HumanReadableNumber(c.second.value, c.second.oneK); + const char* unit = ""; + if (c.second.flags & Counter::kIsRate) + unit = (c.second.flags & Counter::kInvert) ? "s" : "/s"; if (output_options_ & OO_Tabular) { - if (c.second.flags & Counter::kIsRate) { - printer(Out, COLOR_DEFAULT, " %*s/s", cNameLen - 2, s.c_str()); - } else { - printer(Out, COLOR_DEFAULT, " %*s", cNameLen, s.c_str()); - } - } else { - const char* unit = (c.second.flags & Counter::kIsRate) ? "/s" : ""; - printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), + printer(Out, COLOR_DEFAULT, " %*s%s", cNameLen - strlen(unit), s.c_str(), unit); + } else { + printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), unit); } } diff --git a/libcxx/utils/google-benchmark/src/counter.cc b/libcxx/utils/google-benchmark/src/counter.cc index cb604e060b623..cf5b78ee3ac6b 100644 --- a/libcxx/utils/google-benchmark/src/counter.cc +++ b/libcxx/utils/google-benchmark/src/counter.cc @@ -17,7 +17,7 @@ namespace benchmark { namespace internal { -double Finish(Counter const& c, int64_t iterations, double cpu_time, +double Finish(Counter const& c, IterationCount iterations, double cpu_time, double num_threads) { double v = c.value; if (c.flags & Counter::kIsRate) { @@ -32,10 +32,15 @@ double Finish(Counter const& c, int64_t iterations, double cpu_time, if (c.flags & Counter::kAvgIterations) { v /= iterations; } + + if (c.flags & Counter::kInvert) { // Invert is *always* last. + v = 1.0 / v; + } return v; } -void Finish(UserCounters* l, int64_t iterations, double cpu_time, double num_threads) { +void Finish(UserCounters* l, IterationCount iterations, double cpu_time, + double num_threads) { for (auto& c : *l) { c.second.value = Finish(c.second, iterations, cpu_time, num_threads); } diff --git a/libcxx/utils/google-benchmark/src/counter.h b/libcxx/utils/google-benchmark/src/counter.h index d884e50aa12b6..1f5a58e31f0ca 100644 --- a/libcxx/utils/google-benchmark/src/counter.h +++ b/libcxx/utils/google-benchmark/src/counter.h @@ -12,15 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifndef BENCHMARK_COUNTER_H_ +#define BENCHMARK_COUNTER_H_ + #include "benchmark/benchmark.h" namespace benchmark { // these counter-related functions are hidden to reduce API surface. namespace internal { -void Finish(UserCounters* l, int64_t iterations, double time, double num_threads); +void Finish(UserCounters* l, IterationCount iterations, double time, + double num_threads); void Increment(UserCounters* l, UserCounters const& r); bool SameNames(UserCounters const& l, UserCounters const& r); } // end namespace internal } // end namespace benchmark + +#endif // BENCHMARK_COUNTER_H_ diff --git a/libcxx/utils/google-benchmark/src/csv_reporter.cc b/libcxx/utils/google-benchmark/src/csv_reporter.cc index d2f1d27eb62cb..af2c18fc8a6ee 100644 --- a/libcxx/utils/google-benchmark/src/csv_reporter.cc +++ b/libcxx/utils/google-benchmark/src/csv_reporter.cc @@ -37,6 +37,18 @@ std::vector elements = { "error_occurred", "error_message"}; } // namespace +std::string CsvEscape(const std::string & s) { + std::string tmp; + tmp.reserve(s.size() + 2); + for (char c : s) { + switch (c) { + case '"' : tmp += "\"\""; break; + default : tmp += c; break; + } + } + return '"' + tmp + '"'; +} + bool CSVReporter::ReportContext(const Context& context) { PrintBasicContext(&GetErrorStream(), context); return true; @@ -89,18 +101,11 @@ void CSVReporter::ReportRuns(const std::vector& reports) { void CSVReporter::PrintRunData(const Run& run) { std::ostream& Out = GetOutputStream(); - - // Field with embedded double-quote characters must be doubled and the field - // delimited with double-quotes. - std::string name = run.benchmark_name(); - ReplaceAll(&name, "\"", "\"\""); - Out << '"' << name << "\","; + Out << CsvEscape(run.benchmark_name()) << ","; if (run.error_occurred) { Out << std::string(elements.size() - 3, ','); Out << "true,"; - std::string msg = run.error_message; - ReplaceAll(&msg, "\"", "\"\""); - Out << '"' << msg << "\"\n"; + Out << CsvEscape(run.error_message) << "\n"; return; } @@ -130,11 +135,7 @@ void CSVReporter::PrintRunData(const Run& run) { } Out << ","; if (!run.report_label.empty()) { - // Field with embedded double-quote characters must be doubled and the field - // delimited with double-quotes. - std::string label = run.report_label; - ReplaceAll(&label, "\"", "\"\""); - Out << "\"" << label << "\""; + Out << CsvEscape(run.report_label); } Out << ",,"; // for error_occurred and error_message diff --git a/libcxx/utils/google-benchmark/src/cycleclock.h b/libcxx/utils/google-benchmark/src/cycleclock.h index 92f4a495f0a1f..f22ca9f7d2998 100644 --- a/libcxx/utils/google-benchmark/src/cycleclock.h +++ b/libcxx/utils/google-benchmark/src/cycleclock.h @@ -36,7 +36,7 @@ // declarations of some other intrinsics, breaking compilation. // Therefore, we simply declare __rdtsc ourselves. See also // http://connect.microsoft.com/VisualStudio/feedback/details/262047 -#if defined(COMPILER_MSVC) && !defined(_M_IX86) +#if defined(COMPILER_MSVC) && !defined(_M_IX86) && !defined(_M_ARM64) extern "C" uint64_t __rdtsc(); #pragma intrinsic(__rdtsc) #endif @@ -114,6 +114,12 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { // when I know it will work. Otherwise, I'll use __rdtsc and hope // the code is being compiled with a non-ancient compiler. _asm rdtsc +#elif defined(COMPILER_MSVC) && defined(_M_ARM64) + // See https://docs.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=vs-2019 + // and https://reviews.llvm.org/D53115 + int64_t virtual_timer_value; + virtual_timer_value = _ReadStatusReg(ARM64_CNTVCT); + return virtual_timer_value; #elif defined(COMPILER_MSVC) return __rdtsc(); #elif defined(BENCHMARK_OS_NACL) @@ -167,10 +173,19 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { struct timeval tv; gettimeofday(&tv, nullptr); return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; +#elif defined(__loongarch__) + struct timeval tv; + gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; #elif defined(__s390__) // Covers both s390 and s390x. // Return the CPU clock. uint64_t tsc; +#if defined(BENCHMARK_OS_ZOS) && defined(COMPILER_IBMXL) + // z/OS XL compiler HLASM syntax. + asm(" stck %0" : "=m"(tsc) : : "cc"); +#else asm("stck %0" : "=Q"(tsc) : : "cc"); +#endif return tsc; #elif defined(__riscv) // RISC-V // Use RDCYCLE (and RDCYCLEH on riscv32) @@ -193,6 +208,10 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { asm volatile("rdcycle %0" : "=r"(cycles)); return cycles; #endif +#elif defined(__e2k__) || defined(__elbrus__) + struct timeval tv; + gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; #else // The soft failover to a generic implementation is automatic only for ARM. // For other platforms the developer is expected to make an attempt to create diff --git a/libcxx/utils/google-benchmark/src/internal_macros.h b/libcxx/utils/google-benchmark/src/internal_macros.h index 5dbf4fd27521b..91f367b894bcd 100644 --- a/libcxx/utils/google-benchmark/src/internal_macros.h +++ b/libcxx/utils/google-benchmark/src/internal_macros.h @@ -13,7 +13,11 @@ #endif #if defined(__clang__) - #if !defined(COMPILER_CLANG) + #if defined(__ibmxl__) + #if !defined(COMPILER_IBMXL) + #define COMPILER_IBMXL + #endif + #elif !defined(COMPILER_CLANG) #define COMPILER_CLANG #endif #elif defined(_MSC_VER) @@ -58,6 +62,8 @@ #define BENCHMARK_OS_NETBSD 1 #elif defined(__OpenBSD__) #define BENCHMARK_OS_OPENBSD 1 +#elif defined(__DragonFly__) + #define BENCHMARK_OS_DRAGONFLY 1 #elif defined(__linux__) #define BENCHMARK_OS_LINUX 1 #elif defined(__native_client__) @@ -70,6 +76,10 @@ #define BENCHMARK_OS_FUCHSIA 1 #elif defined (__SVR4) && defined (__sun) #define BENCHMARK_OS_SOLARIS 1 +#elif defined(__QNX__) +#define BENCHMARK_OS_QNX 1 +#elif defined(__MVS__) +#define BENCHMARK_OS_ZOS 1 #endif #if defined(__ANDROID__) && defined(__GLIBCXX__) diff --git a/libcxx/utils/google-benchmark/src/json_reporter.cc b/libcxx/utils/google-benchmark/src/json_reporter.cc index 7d01e8e4e316c..26898456f8546 100644 --- a/libcxx/utils/google-benchmark/src/json_reporter.cc +++ b/libcxx/utils/google-benchmark/src/json_reporter.cc @@ -16,6 +16,7 @@ #include "complexity.h" #include +#include #include #include // for setprecision #include @@ -28,39 +29,73 @@ #include "timers.h" namespace benchmark { +namespace internal { +extern std::map* global_context; +} namespace { +std::string StrEscape(const std::string & s) { + std::string tmp; + tmp.reserve(s.size()); + for (char c : s) { + switch (c) { + case '\b': tmp += "\\b"; break; + case '\f': tmp += "\\f"; break; + case '\n': tmp += "\\n"; break; + case '\r': tmp += "\\r"; break; + case '\t': tmp += "\\t"; break; + case '\\': tmp += "\\\\"; break; + case '"' : tmp += "\\\""; break; + default : tmp += c; break; + } + } + return tmp; +} + std::string FormatKV(std::string const& key, std::string const& value) { - return StrFormat("\"%s\": \"%s\"", key.c_str(), value.c_str()); + return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(), StrEscape(value).c_str()); } std::string FormatKV(std::string const& key, const char* value) { - return StrFormat("\"%s\": \"%s\"", key.c_str(), value); + return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(), StrEscape(value).c_str()); } std::string FormatKV(std::string const& key, bool value) { - return StrFormat("\"%s\": %s", key.c_str(), value ? "true" : "false"); + return StrFormat("\"%s\": %s", StrEscape(key).c_str(), value ? "true" : "false"); } std::string FormatKV(std::string const& key, int64_t value) { std::stringstream ss; - ss << '"' << key << "\": " << value; + ss << '"' << StrEscape(key) << "\": " << value; return ss.str(); } -std::string FormatKV(std::string const& key, double value) { +std::string FormatKV(std::string const& key, IterationCount value) { std::stringstream ss; - ss << '"' << key << "\": "; + ss << '"' << StrEscape(key) << "\": " << value; + return ss.str(); +} - const auto max_digits10 = std::numeric_limits::max_digits10; - const auto max_fractional_digits10 = max_digits10 - 1; +std::string FormatKV(std::string const& key, double value) { + std::stringstream ss; + ss << '"' << StrEscape(key) << "\": "; - ss << std::scientific << std::setprecision(max_fractional_digits10) << value; + if (std::isnan(value)) + ss << (value < 0 ? "-" : "") << "NaN"; + else if (std::isinf(value)) + ss << (value < 0 ? "-" : "") << "Infinity"; + else { + const auto max_digits10 = + std::numeric_limits::max_digits10; + const auto max_fractional_digits10 = max_digits10 - 1; + ss << std::scientific << std::setprecision(max_fractional_digits10) + << value; + } return ss.str(); } -int64_t RoundDouble(double v) { return static_cast(v + 0.5); } +int64_t RoundDouble(double v) { return std::lround(v); } } // end namespace @@ -80,12 +115,7 @@ bool JSONReporter::ReportContext(const Context& context) { out << indent << FormatKV("host_name", context.sys_info.name) << ",\n"; if (Context::executable_name) { - // windows uses backslash for its path separator, - // which must be escaped in JSON otherwise it blows up conforming JSON - // decoders - std::string executable_name = Context::executable_name; - ReplaceAll(&executable_name, "\\", "\\\\"); - out << indent << FormatKV("executable", executable_name) << ",\n"; + out << indent << FormatKV("executable", Context::executable_name) << ",\n"; } CPUInfo const& info = context.cpu_info; @@ -95,8 +125,10 @@ bool JSONReporter::ReportContext(const Context& context) { << FormatKV("mhz_per_cpu", RoundDouble(info.cycles_per_second / 1000000.0)) << ",\n"; - out << indent << FormatKV("cpu_scaling_enabled", info.scaling_enabled) - << ",\n"; + if (CPUInfo::Scaling::UNKNOWN != info.scaling) { + out << indent << FormatKV("cpu_scaling_enabled", info.scaling == CPUInfo::Scaling::ENABLED ? true : false) + << ",\n"; + } out << indent << "\"caches\": [\n"; indent = std::string(6, ' '); @@ -108,7 +140,7 @@ bool JSONReporter::ReportContext(const Context& context) { out << cache_indent << FormatKV("level", static_cast(CI.level)) << ",\n"; out << cache_indent - << FormatKV("size", static_cast(CI.size) * 1000u) << ",\n"; + << FormatKV("size", static_cast(CI.size)) << ",\n"; out << cache_indent << FormatKV("num_sharing", static_cast(CI.num_sharing)) << "\n"; @@ -131,6 +163,13 @@ bool JSONReporter::ReportContext(const Context& context) { const char build_type[] = "debug"; #endif out << indent << FormatKV("library_build_type", build_type) << "\n"; + + if (internal::global_context != nullptr) { + for (const auto& kv: *internal::global_context) { + out << indent << FormatKV(kv.first, kv.second) << "\n"; + } + } + // Close context block and open the list of benchmarks. out << inner_indent << "},\n"; out << inner_indent << "\"benchmarks\": [\n"; @@ -168,7 +207,11 @@ void JSONReporter::PrintRunData(Run const& run) { std::string indent(6, ' '); std::ostream& out = GetOutputStream(); out << indent << FormatKV("name", run.benchmark_name()) << ",\n"; - out << indent << FormatKV("run_name", run.run_name) << ",\n"; + out << indent << FormatKV("family_index", run.family_index) << ",\n"; + out << indent + << FormatKV("per_family_instance_index", run.per_family_instance_index) + << ",\n"; + out << indent << FormatKV("run_name", run.run_name.str()) << ",\n"; out << indent << FormatKV("run_type", [&run]() -> const char* { switch (run.run_type) { case BenchmarkReporter::Run::RT_Iteration: @@ -178,6 +221,12 @@ void JSONReporter::PrintRunData(Run const& run) { } BENCHMARK_UNREACHABLE(); }()) << ",\n"; + out << indent << FormatKV("repetitions", run.repetitions) << ",\n"; + if (run.run_type != BenchmarkReporter::Run::RT_Aggregate) { + out << indent << FormatKV("repetition_index", run.repetition_index) + << ",\n"; + } + out << indent << FormatKV("threads", run.threads) << ",\n"; if (run.run_type == BenchmarkReporter::Run::RT_Aggregate) { out << indent << FormatKV("aggregate_name", run.aggregate_name) << ",\n"; } diff --git a/libcxx/utils/google-benchmark/src/mutex.h b/libcxx/utils/google-benchmark/src/mutex.h index 5f461d05a0c64..9cc414ec467e6 100644 --- a/libcxx/utils/google-benchmark/src/mutex.h +++ b/libcxx/utils/google-benchmark/src/mutex.h @@ -9,60 +9,60 @@ // Enable thread safety attributes only with clang. // The attributes can be safely erased when compiling with other compilers. #if defined(HAVE_THREAD_SAFETY_ATTRIBUTES) -#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#define THREAD_ANNOTATION_ATTRIBUTE_(x) __attribute__((x)) #else -#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#define THREAD_ANNOTATION_ATTRIBUTE_(x) // no-op #endif -#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) +#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(capability(x)) -#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) +#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE_(scoped_lockable) -#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) +#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(guarded_by(x)) -#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) +#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(pt_guarded_by(x)) #define ACQUIRED_BEFORE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(acquired_before(__VA_ARGS__)) #define ACQUIRED_AFTER(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(acquired_after(__VA_ARGS__)) #define REQUIRES(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(requires_capability(__VA_ARGS__)) #define REQUIRES_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(requires_shared_capability(__VA_ARGS__)) #define ACQUIRE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(acquire_capability(__VA_ARGS__)) #define ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(acquire_shared_capability(__VA_ARGS__)) #define RELEASE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(release_capability(__VA_ARGS__)) #define RELEASE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(release_shared_capability(__VA_ARGS__)) #define TRY_ACQUIRE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_capability(__VA_ARGS__)) #define TRY_ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_shared_capability(__VA_ARGS__)) -#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) +#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE_(locks_excluded(__VA_ARGS__)) -#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) +#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(assert_capability(x)) #define ASSERT_SHARED_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + THREAD_ANNOTATION_ATTRIBUTE_(assert_shared_capability(x)) -#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) +#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(lock_returned(x)) #define NO_THREAD_SAFETY_ANALYSIS \ - THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + THREAD_ANNOTATION_ATTRIBUTE_(no_thread_safety_analysis) namespace benchmark { @@ -71,7 +71,7 @@ typedef std::condition_variable Condition; // NOTE: Wrappers for std::mutex and std::unique_lock are provided so that // we can annotate them with thread safety attributes and use the // -Wthread-safety warning with clang. The standard library types cannot be -// used directly because they do not provided the required annotations. +// used directly because they do not provide the required annotations. class CAPABILITY("mutex") Mutex { public: Mutex() {} diff --git a/libcxx/utils/google-benchmark/src/perf_counters.cc b/libcxx/utils/google-benchmark/src/perf_counters.cc new file mode 100644 index 0000000000000..4ddf0de2502c7 --- /dev/null +++ b/libcxx/utils/google-benchmark/src/perf_counters.cc @@ -0,0 +1,132 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "perf_counters.h" + +#include +#include + +#if defined HAVE_LIBPFM +#include "perfmon/pfmlib.h" +#include "perfmon/pfmlib_perf_event.h" +#endif + +namespace benchmark { +namespace internal { + +constexpr size_t PerfCounterValues::kMaxCounters; + +#if defined HAVE_LIBPFM +const bool PerfCounters::kSupported = true; + +bool PerfCounters::Initialize() { return pfm_initialize() == PFM_SUCCESS; } + +PerfCounters PerfCounters::Create( + const std::vector& counter_names) { + if (counter_names.empty()) { + return NoCounters(); + } + if (counter_names.size() > PerfCounterValues::kMaxCounters) { + GetErrorLogInstance() + << counter_names.size() + << " counters were requested. The minimum is 1, the maximum is " + << PerfCounterValues::kMaxCounters << "\n"; + return NoCounters(); + } + std::vector counter_ids(counter_names.size()); + + const int mode = PFM_PLM3; // user mode only + for (size_t i = 0; i < counter_names.size(); ++i) { + const bool is_first = i == 0; + struct perf_event_attr attr{}; + attr.size = sizeof(attr); + const int group_id = !is_first ? counter_ids[0] : -1; + const auto& name = counter_names[i]; + if (name.empty()) { + GetErrorLogInstance() << "A counter name was the empty string\n"; + return NoCounters(); + } + pfm_perf_encode_arg_t arg{}; + arg.attr = &attr; + + const int pfm_get = + pfm_get_os_event_encoding(name.c_str(), mode, PFM_OS_PERF_EVENT, &arg); + if (pfm_get != PFM_SUCCESS) { + GetErrorLogInstance() << "Unknown counter name: " << name << "\n"; + return NoCounters(); + } + attr.disabled = is_first; + // Note: the man page for perf_event_create suggests inerit = true and + // read_format = PERF_FORMAT_GROUP don't work together, but that's not the + // case. + attr.inherit = true; + attr.pinned = is_first; + attr.exclude_kernel = true; + attr.exclude_user = false; + attr.exclude_hv = true; + // Read all counters in one read. + attr.read_format = PERF_FORMAT_GROUP; + + int id = -1; + static constexpr size_t kNrOfSyscallRetries = 5; + // Retry syscall as it was interrupted often (b/64774091). + for (size_t num_retries = 0; num_retries < kNrOfSyscallRetries; + ++num_retries) { + id = perf_event_open(&attr, 0, -1, group_id, 0); + if (id >= 0 || errno != EINTR) { + break; + } + } + if (id < 0) { + GetErrorLogInstance() + << "Failed to get a file descriptor for " << name << "\n"; + return NoCounters(); + } + + counter_ids[i] = id; + } + if (ioctl(counter_ids[0], PERF_EVENT_IOC_ENABLE) != 0) { + GetErrorLogInstance() << "Failed to start counters\n"; + return NoCounters(); + } + + return PerfCounters(counter_names, std::move(counter_ids)); +} + +PerfCounters::~PerfCounters() { + if (counter_ids_.empty()) { + return; + } + ioctl(counter_ids_[0], PERF_EVENT_IOC_DISABLE); + for (int fd : counter_ids_) { + close(fd); + } +} +#else // defined HAVE_LIBPFM +const bool PerfCounters::kSupported = false; + +bool PerfCounters::Initialize() { return false; } + +PerfCounters PerfCounters::Create( + const std::vector& counter_names) { + if (!counter_names.empty()) { + GetErrorLogInstance() << "Performance counters not supported."; + } + return NoCounters(); +} + +PerfCounters::~PerfCounters() = default; +#endif // defined HAVE_LIBPFM +} // namespace internal +} // namespace benchmark diff --git a/libcxx/utils/google-benchmark/src/perf_counters.h b/libcxx/utils/google-benchmark/src/perf_counters.h new file mode 100644 index 0000000000000..b6629b99070b0 --- /dev/null +++ b/libcxx/utils/google-benchmark/src/perf_counters.h @@ -0,0 +1,172 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BENCHMARK_PERF_COUNTERS_H +#define BENCHMARK_PERF_COUNTERS_H + +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "check.h" +#include "log.h" + +#ifndef BENCHMARK_OS_WINDOWS +#include +#endif + +namespace benchmark { +namespace internal { + +// Typically, we can only read a small number of counters. There is also a +// padding preceding counter values, when reading multiple counters with one +// syscall (which is desirable). PerfCounterValues abstracts these details. +// The implementation ensures the storage is inlined, and allows 0-based +// indexing into the counter values. +// The object is used in conjunction with a PerfCounters object, by passing it +// to Snapshot(). The values are populated such that +// perfCounters->names()[i]'s value is obtained at position i (as given by +// operator[]) of this object. +class PerfCounterValues { + public: + explicit PerfCounterValues(size_t nr_counters) : nr_counters_(nr_counters) { + CHECK_LE(nr_counters_, kMaxCounters); + } + + uint64_t operator[](size_t pos) const { return values_[kPadding + pos]; } + + static constexpr size_t kMaxCounters = 3; + + private: + friend class PerfCounters; + // Get the byte buffer in which perf counters can be captured. + // This is used by PerfCounters::Read + std::pair get_data_buffer() { + return {reinterpret_cast(values_.data()), + sizeof(uint64_t) * (kPadding + nr_counters_)}; + } + + static constexpr size_t kPadding = 1; + std::array values_; + const size_t nr_counters_; +}; + +// Collect PMU counters. The object, once constructed, is ready to be used by +// calling read(). PMU counter collection is enabled from the time create() is +// called, to obtain the object, until the object's destructor is called. +class PerfCounters final { + public: + // True iff this platform supports performance counters. + static const bool kSupported; + + bool IsValid() const { return is_valid_; } + static PerfCounters NoCounters() { return PerfCounters(); } + + ~PerfCounters(); + PerfCounters(PerfCounters&&) = default; + PerfCounters(const PerfCounters&) = delete; + + // Platform-specific implementations may choose to do some library + // initialization here. + static bool Initialize(); + + // Return a PerfCounters object ready to read the counters with the names + // specified. The values are user-mode only. The counter name format is + // implementation and OS specific. + // TODO: once we move to C++-17, this should be a std::optional, and then the + // IsValid() boolean can be dropped. + static PerfCounters Create(const std::vector& counter_names); + + // Take a snapshot of the current value of the counters into the provided + // valid PerfCounterValues storage. The values are populated such that: + // names()[i]'s value is (*values)[i] + BENCHMARK_ALWAYS_INLINE bool Snapshot(PerfCounterValues* values) const { +#ifndef BENCHMARK_OS_WINDOWS + assert(values != nullptr); + assert(IsValid()); + auto buffer = values->get_data_buffer(); + auto read_bytes = ::read(counter_ids_[0], buffer.first, buffer.second); + return static_cast(read_bytes) == buffer.second; +#else + (void)values; + return false; +#endif + } + + const std::vector& names() const { return counter_names_; } + size_t num_counters() const { return counter_names_.size(); } + + private: + PerfCounters(const std::vector& counter_names, + std::vector&& counter_ids) + : counter_ids_(std::move(counter_ids)), + counter_names_(counter_names), + is_valid_(true) {} + PerfCounters() : is_valid_(false) {} + + std::vector counter_ids_; + const std::vector counter_names_; + const bool is_valid_; +}; + +// Typical usage of the above primitives. +class PerfCountersMeasurement final { + public: + PerfCountersMeasurement(PerfCounters&& c) + : counters_(std::move(c)), + start_values_(counters_.IsValid() ? counters_.names().size() : 0), + end_values_(counters_.IsValid() ? counters_.names().size() : 0) {} + + bool IsValid() const { return counters_.IsValid(); } + + BENCHMARK_ALWAYS_INLINE void Start() { + assert(IsValid()); + // Tell the compiler to not move instructions above/below where we take + // the snapshot. + ClobberMemory(); + counters_.Snapshot(&start_values_); + ClobberMemory(); + } + + BENCHMARK_ALWAYS_INLINE std::vector> + StopAndGetMeasurements() { + assert(IsValid()); + // Tell the compiler to not move instructions above/below where we take + // the snapshot. + ClobberMemory(); + counters_.Snapshot(&end_values_); + ClobberMemory(); + + std::vector> ret; + for (size_t i = 0; i < counters_.names().size(); ++i) { + double measurement = static_cast(end_values_[i]) - + static_cast(start_values_[i]); + ret.push_back({counters_.names()[i], measurement}); + } + return ret; + } + + private: + PerfCounters counters_; + PerfCounterValues start_values_; + PerfCounterValues end_values_; +}; + +BENCHMARK_UNUSED static bool perf_init_anchor = PerfCounters::Initialize(); + +} // namespace internal +} // namespace benchmark + +#endif // BENCHMARK_PERF_COUNTERS_H diff --git a/libcxx/utils/google-benchmark/src/reporter.cc b/libcxx/utils/google-benchmark/src/reporter.cc index 59bc5f7102319..14dd40dc72f46 100644 --- a/libcxx/utils/google-benchmark/src/reporter.cc +++ b/libcxx/utils/google-benchmark/src/reporter.cc @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -25,6 +27,9 @@ #include "string_util.h" namespace benchmark { +namespace internal { +extern std::map* global_context; +} BenchmarkReporter::BenchmarkReporter() : output_stream_(&std::cout), error_stream_(&std::cerr) {} @@ -49,7 +54,7 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, Out << "CPU Caches:\n"; for (auto &CInfo : info.caches) { Out << " L" << CInfo.level << " " << CInfo.type << " " - << (CInfo.size / 1000) << "K"; + << (CInfo.size / 1024) << " KiB"; if (CInfo.num_sharing != 0) Out << " (x" << (info.num_cpus / CInfo.num_sharing) << ")"; Out << "\n"; @@ -64,7 +69,13 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, Out << "\n"; } - if (info.scaling_enabled) { + if (internal::global_context != nullptr) { + for (const auto& kv: *internal::global_context) { + Out << kv.first << ": " << kv.second << "\n"; + } + } + + if (CPUInfo::Scaling::ENABLED == info.scaling) { Out << "***WARNING*** CPU scaling is enabled, the benchmark " "real time measurements may be noisy and will incur extra " "overhead.\n"; @@ -83,7 +94,7 @@ BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {} std::string BenchmarkReporter::Run::benchmark_name() const { - std::string name = run_name; + std::string name = run_name.str(); if (run_type == RT_Aggregate) { name += "_" + aggregate_name; } diff --git a/libcxx/utils/google-benchmark/src/sleep.cc b/libcxx/utils/google-benchmark/src/sleep.cc index 1512ac90f7ead..4609d540eade8 100644 --- a/libcxx/utils/google-benchmark/src/sleep.cc +++ b/libcxx/utils/google-benchmark/src/sleep.cc @@ -24,6 +24,10 @@ #include #endif +#ifdef BENCHMARK_OS_ZOS +#include +#endif + namespace benchmark { #ifdef BENCHMARK_OS_WINDOWS // Window's Sleep takes milliseconds argument. @@ -33,11 +37,23 @@ void SleepForSeconds(double seconds) { } #else // BENCHMARK_OS_WINDOWS void SleepForMicroseconds(int microseconds) { +#ifdef BENCHMARK_OS_ZOS + // z/OS does not support nanosleep. Instead call sleep() and then usleep() to + // sleep for the remaining microseconds because usleep() will fail if its + // argument is greater than 1000000. + div_t sleepTime = div(microseconds, kNumMicrosPerSecond); + int seconds = sleepTime.quot; + while (seconds != 0) + seconds = sleep(seconds); + while (usleep(sleepTime.rem) == -1 && errno == EINTR) + ; +#else struct timespec sleep_time; sleep_time.tv_sec = microseconds / kNumMicrosPerSecond; sleep_time.tv_nsec = (microseconds % kNumMicrosPerSecond) * kNumNanosPerMicro; while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) ; // Ignore signals and wait for the full interval to elapse. +#endif } void SleepForMilliseconds(int milliseconds) { diff --git a/libcxx/utils/google-benchmark/src/statistics.cc b/libcxx/utils/google-benchmark/src/statistics.cc index e821aec18b7c3..57472b9ff99bd 100644 --- a/libcxx/utils/google-benchmark/src/statistics.cc +++ b/libcxx/utils/google-benchmark/src/statistics.cc @@ -97,7 +97,7 @@ std::vector ComputeStats( // All repetitions should be run with the same number of iterations so we // can take this information from the first benchmark. - int64_t const run_iterations = reports.front().iterations; + const IterationCount run_iterations = reports.front().iterations; // create stats for user counters struct CounterStat { Counter c; @@ -147,8 +147,13 @@ std::vector ComputeStats( for (const auto& Stat : *reports[0].statistics) { // Get the data from the accumulator to BenchmarkReporter::Run's. Run data; - data.run_name = reports[0].benchmark_name(); + data.run_name = reports[0].run_name; + data.family_index = reports[0].family_index; + data.per_family_instance_index = reports[0].per_family_instance_index; data.run_type = BenchmarkReporter::Run::RT_Aggregate; + data.threads = reports[0].threads; + data.repetitions = reports[0].repetitions; + data.repetition_index = Run::no_repetition_index; data.aggregate_name = Stat.name_; data.report_label = report_label; diff --git a/libcxx/utils/google-benchmark/src/string_util.cc b/libcxx/utils/google-benchmark/src/string_util.cc index 05ac5b4ea367e..3551418174fd0 100644 --- a/libcxx/utils/google-benchmark/src/string_util.cc +++ b/libcxx/utils/google-benchmark/src/string_util.cc @@ -1,6 +1,9 @@ #include "string_util.h" #include +#ifdef BENCHMARK_STL_ANDROID_GNUSTL +#include +#endif #include #include #include @@ -160,13 +163,17 @@ std::string StrFormat(const char* format, ...) { return tmp; } -void ReplaceAll(std::string* str, const std::string& from, - const std::string& to) { - std::size_t start = 0; - while ((start = str->find(from, start)) != std::string::npos) { - str->replace(start, from.length(), to); - start += to.length(); +std::vector StrSplit(const std::string& str, char delim) { + if (str.empty()) return {}; + std::vector ret; + size_t first = 0; + size_t next = str.find(delim); + for (; next != std::string::npos; + first = next + 1, next = str.find(delim, first)) { + ret.push_back(str.substr(first, next - first)); } + ret.push_back(str.substr(first)); + return ret; } #ifdef BENCHMARK_STL_ANDROID_GNUSTL diff --git a/libcxx/utils/google-benchmark/src/string_util.h b/libcxx/utils/google-benchmark/src/string_util.h index fc5f8b0304b04..6bc28b6912a84 100644 --- a/libcxx/utils/google-benchmark/src/string_util.h +++ b/libcxx/utils/google-benchmark/src/string_util.h @@ -12,7 +12,9 @@ void AppendHumanReadable(int n, std::string* str); std::string HumanReadableNumber(double n, double one_k = 1024.0); -#ifdef __GNUC__ +#if defined(__MINGW32__) +__attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2))) +#elif defined(__GNUC__) __attribute__((format(printf, 1, 2))) #endif std::string @@ -35,8 +37,7 @@ inline std::string StrCat(Args&&... args) { return ss.str(); } -void ReplaceAll(std::string* str, const std::string& from, - const std::string& to); +std::vector StrSplit(const std::string& str, char delim); #ifdef BENCHMARK_STL_ANDROID_GNUSTL /* diff --git a/libcxx/utils/google-benchmark/src/sysinfo.cc b/libcxx/utils/google-benchmark/src/sysinfo.cc index c0c07e5e62afe..c1969ea2d3fe8 100644 --- a/libcxx/utils/google-benchmark/src/sysinfo.cc +++ b/libcxx/utils/google-benchmark/src/sysinfo.cc @@ -29,7 +29,8 @@ #include // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD #include #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \ - defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD + defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD || \ + defined BENCHMARK_OS_DRAGONFLY #define BENCHMARK_HAS_SYSCTL #include #endif @@ -37,6 +38,9 @@ #if defined(BENCHMARK_OS_SOLARIS) #include #endif +#if defined(BENCHMARK_OS_QNX) +#include +#endif #include #include @@ -54,6 +58,7 @@ #include #include #include +#include #include "check.h" #include "cycleclock.h" @@ -206,9 +211,12 @@ bool ReadFromFile(std::string const& fname, ArgT* arg) { return f.good(); } -bool CpuScalingEnabled(int num_cpus) { +CPUInfo::Scaling CpuScaling(int num_cpus) { // We don't have a valid CPU count, so don't even bother. - if (num_cpus <= 0) return false; + if (num_cpus <= 0) return CPUInfo::Scaling::UNKNOWN; +#ifdef BENCHMARK_OS_QNX + return CPUInfo::Scaling::UNKNOWN; +#endif #ifndef BENCHMARK_OS_WINDOWS // On Linux, the CPUfreq subsystem exposes CPU information as files on the // local file system. If reading the exported files fails, then we may not be @@ -217,10 +225,11 @@ bool CpuScalingEnabled(int num_cpus) { for (int cpu = 0; cpu < num_cpus; ++cpu) { std::string governor_file = StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor"); - if (ReadFromFile(governor_file, &res) && res != "performance") return true; + if (ReadFromFile(governor_file, &res) && res != "performance") return CPUInfo::Scaling::ENABLED; } + return CPUInfo::Scaling::DISABLED; #endif - return false; + return CPUInfo::Scaling::UNKNOWN; } int CountSetBitsInCPUMap(std::string Val) { @@ -264,7 +273,7 @@ std::vector GetCacheSizesFromKVFS() { else if (f && suffix != "K") PrintErrorAndDie("Invalid cache size format: Expected bytes ", suffix); else if (suffix == "K") - info.size *= 1000; + info.size *= 1024; } if (!ReadFromFile(StrCat(FPath, "type"), &info.type)) PrintErrorAndDie("Failed to read from file ", FPath, "type"); @@ -356,6 +365,42 @@ std::vector GetCacheSizesWindows() { } return res; } +#elif BENCHMARK_OS_QNX +std::vector GetCacheSizesQNX() { + std::vector res; + struct cacheattr_entry *cache = SYSPAGE_ENTRY(cacheattr); + uint32_t const elsize = SYSPAGE_ELEMENT_SIZE(cacheattr); + int num = SYSPAGE_ENTRY_SIZE(cacheattr) / elsize ; + for(int i = 0; i < num; ++i ) { + CPUInfo::CacheInfo info; + switch (cache->flags){ + case CACHE_FLAG_INSTR : + info.type = "Instruction"; + info.level = 1; + break; + case CACHE_FLAG_DATA : + info.type = "Data"; + info.level = 1; + break; + case CACHE_FLAG_UNIFIED : + info.type = "Unified"; + info.level = 2; + break; + case CACHE_FLAG_SHARED : + info.type = "Shared"; + info.level = 3; + break; + default : + continue; + break; + } + info.size = cache->line_size * cache->num_lines; + info.num_sharing = 0; + res.push_back(std::move(info)); + cache = SYSPAGE_ARRAY_ADJ_OFFSET(cacheattr, cache, elsize); + } + return res; +} #endif std::vector GetCacheSizes() { @@ -363,6 +408,8 @@ std::vector GetCacheSizes() { return GetCacheSizesMacOSX(); #elif defined(BENCHMARK_OS_WINDOWS) return GetCacheSizesWindows(); +#elif defined(BENCHMARK_OS_QNX) + return GetCacheSizesQNX(); #else return GetCacheSizesFromKVFS(); #endif @@ -387,9 +434,20 @@ std::string GetSystemName() { #endif return str; #else // defined(BENCHMARK_OS_WINDOWS) -#ifdef BENCHMARK_OS_MACOSX //Mac Doesnt have HOST_NAME_MAX defined +#ifndef HOST_NAME_MAX +#ifdef BENCHMARK_HAS_SYSCTL // BSD/Mac Doesnt have HOST_NAME_MAX defined +#define HOST_NAME_MAX 64 +#elif defined(BENCHMARK_OS_NACL) +#define HOST_NAME_MAX 64 +#elif defined(BENCHMARK_OS_QNX) +#define HOST_NAME_MAX 154 +#elif defined(BENCHMARK_OS_RTEMS) +#define HOST_NAME_MAX 256 +#else +#warning "HOST_NAME_MAX not defined. using 64" #define HOST_NAME_MAX 64 #endif +#endif // def HOST_NAME_MAX char hostname[HOST_NAME_MAX]; int retVal = gethostname(hostname, HOST_NAME_MAX); if (retVal != 0) return std::string(""); @@ -421,6 +479,8 @@ int GetNumCPUs() { strerror(errno)); } return NumCPU; +#elif defined(BENCHMARK_OS_QNX) + return static_cast(_syspage_ptr->num_cpu); #else int NumCPUs = 0; int MaxID = -1; @@ -470,7 +530,11 @@ int GetNumCPUs() { BENCHMARK_UNREACHABLE(); } -double GetCPUCyclesPerSecond() { +double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) { + // Currently, scaling is only used on linux path here, + // suppress diagnostics about it being unused on other paths. + (void)scaling; + #if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN long freq; @@ -481,8 +545,15 @@ double GetCPUCyclesPerSecond() { // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as // well. if (ReadFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq) - // If CPU scaling is in effect, we want to use the *maximum* frequency, - // not whatever CPU speed some random processor happens to be using now. + // If CPU scaling is disabled, use the the *current* frequency. + // Note that we specifically don't want to read cpuinfo_cur_freq, + // because it is only readable by root. + || (scaling == CPUInfo::Scaling::DISABLED && + ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", + &freq)) + // Otherwise, if CPU scaling may be in effect, we want to use + // the *maximum* frequency, not whatever CPU speed some random processor + // happens to be using now. || ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", &freq)) { // The value is in kHz (as the file name suggests). For example, on a @@ -548,6 +619,8 @@ double GetCPUCyclesPerSecond() { "machdep.tsc_freq"; #elif defined BENCHMARK_OS_OPENBSD "hw.cpuspeed"; +#elif defined BENCHMARK_OS_DRAGONFLY + "hw.tsc_frequency"; #else "hw.cpufrequency"; #endif @@ -600,6 +673,9 @@ double GetCPUCyclesPerSecond() { double clock_hz = knp->value.ui64; kstat_close(kc); return clock_hz; +#elif defined (BENCHMARK_OS_QNX) + return static_cast((int64_t)(SYSPAGE_ENTRY(cpuinfo)->speed) * + (int64_t)(1000 * 1000)); #endif // If we've fallen through, attempt to roughly estimate the CPU clock rate. const int estimate_time_ms = 1000; @@ -609,9 +685,10 @@ double GetCPUCyclesPerSecond() { } std::vector GetLoadAvg() { -#if defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \ - defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \ - defined BENCHMARK_OS_OPENBSD +#if (defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \ + defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \ + defined BENCHMARK_OS_OPENBSD || defined BENCHMARK_OS_DRAGONFLY) && \ + !defined(__ANDROID__) constexpr int kMaxSamples = 3; std::vector res(kMaxSamples, 0.0); const int nelem = getloadavg(res.data(), kMaxSamples); @@ -635,12 +712,11 @@ const CPUInfo& CPUInfo::Get() { CPUInfo::CPUInfo() : num_cpus(GetNumCPUs()), - cycles_per_second(GetCPUCyclesPerSecond()), + scaling(CpuScaling(num_cpus)), + cycles_per_second(GetCPUCyclesPerSecond(scaling)), caches(GetCacheSizes()), - scaling_enabled(CpuScalingEnabled(num_cpus)), load_avg(GetLoadAvg()) {} - const SystemInfo& SystemInfo::Get() { static const SystemInfo* info = new SystemInfo(); return *info; diff --git a/libcxx/utils/google-benchmark/src/thread_manager.h b/libcxx/utils/google-benchmark/src/thread_manager.h index 6e274c7ea6bce..28e2dd53aff2c 100644 --- a/libcxx/utils/google-benchmark/src/thread_manager.h +++ b/libcxx/utils/google-benchmark/src/thread_manager.h @@ -11,7 +11,7 @@ namespace internal { class ThreadManager { public: - ThreadManager(int num_threads) + explicit ThreadManager(int num_threads) : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { @@ -38,7 +38,7 @@ class ThreadManager { public: struct Result { - int64_t iterations = 0; + IterationCount iterations = 0; double real_time_used = 0; double cpu_time_used = 0; double manual_time_used = 0; diff --git a/libcxx/utils/google-benchmark/src/thread_timer.h b/libcxx/utils/google-benchmark/src/thread_timer.h index eaf108e017dc5..1703ca0d6f877 100644 --- a/libcxx/utils/google-benchmark/src/thread_timer.h +++ b/libcxx/utils/google-benchmark/src/thread_timer.h @@ -8,14 +8,22 @@ namespace benchmark { namespace internal { class ThreadTimer { + explicit ThreadTimer(bool measure_process_cpu_time_) + : measure_process_cpu_time(measure_process_cpu_time_) {} + public: - ThreadTimer() = default; + static ThreadTimer Create() { + return ThreadTimer(/*measure_process_cpu_time_=*/false); + } + static ThreadTimer CreateProcessCpuTime() { + return ThreadTimer(/*measure_process_cpu_time_=*/true); + } // Called by each thread void StartTimer() { running_ = true; start_real_time_ = ChronoClockNow(); - start_cpu_time_ = ThreadCPUUsage(); + start_cpu_time_ = ReadCpuTimerOfChoice(); } // Called by each thread @@ -25,7 +33,8 @@ class ThreadTimer { real_time_used_ += ChronoClockNow() - start_real_time_; // Floating point error can result in the subtraction producing a negative // time. Guard against that. - cpu_time_used_ += std::max(ThreadCPUUsage() - start_cpu_time_, 0); + cpu_time_used_ += + std::max(ReadCpuTimerOfChoice() - start_cpu_time_, 0); } // Called by each thread @@ -34,24 +43,32 @@ class ThreadTimer { bool running() const { return running_; } // REQUIRES: timer is not running - double real_time_used() { + double real_time_used() const { CHECK(!running_); return real_time_used_; } // REQUIRES: timer is not running - double cpu_time_used() { + double cpu_time_used() const { CHECK(!running_); return cpu_time_used_; } // REQUIRES: timer is not running - double manual_time_used() { + double manual_time_used() const { CHECK(!running_); return manual_time_used_; } private: + double ReadCpuTimerOfChoice() const { + if (measure_process_cpu_time) return ProcessCPUUsage(); + return ThreadCPUUsage(); + } + + // should the thread, or the process, time be measured? + const bool measure_process_cpu_time; + bool running_ = false; // Is the timer running double start_real_time_ = 0; // If running_ double start_cpu_time_ = 0; // If running_ diff --git a/libcxx/utils/google-benchmark/src/timers.cc b/libcxx/utils/google-benchmark/src/timers.cc index 7613ff92c6ef0..af4767dff944f 100644 --- a/libcxx/utils/google-benchmark/src/timers.cc +++ b/libcxx/utils/google-benchmark/src/timers.cc @@ -28,7 +28,8 @@ #include #include // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD #include -#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX +#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_DRAGONFLY || \ + defined BENCHMARK_OS_MACOSX #include #endif #if defined(BENCHMARK_OS_MACOSX) @@ -178,40 +179,75 @@ double ThreadCPUUsage() { #endif } -namespace { - -std::string DateTimeString(bool local) { +std::string LocalDateTimeString() { + // Write the local time in RFC3339 format yyyy-mm-ddTHH:MM:SS+/-HH:MM. typedef std::chrono::system_clock Clock; std::time_t now = Clock::to_time_t(Clock::now()); - const std::size_t kStorageSize = 128; - char storage[kStorageSize]; - std::size_t written; + const std::size_t kTzOffsetLen = 6; + const std::size_t kTimestampLen = 19; + + std::size_t tz_len; + std::size_t timestamp_len; + long int offset_minutes; + char tz_offset_sign = '+'; + // tz_offset is set in one of three ways: + // * strftime with %z - This either returns empty or the ISO 8601 time. The maximum length an + // ISO 8601 string can be is 7 (e.g. -03:30, plus trailing zero). + // * snprintf with %c%02li:%02li - The maximum length is 41 (one for %c, up to 19 for %02li, + // one for :, up to 19 %02li, plus trailing zero). + // * A fixed string of "-00:00". The maximum length is 7 (-00:00, plus trailing zero). + // + // Thus, the maximum size this needs to be is 41. + char tz_offset[41]; + // Long enough buffer to avoid format-overflow warnings + char storage[128]; - if (local) { #if defined(BENCHMARK_OS_WINDOWS) - written = - std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now)); + std::tm *timeinfo_p = ::localtime(&now); #else - std::tm timeinfo; - ::localtime_r(&now, &timeinfo); - written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); + std::tm timeinfo; + std::tm *timeinfo_p = &timeinfo; + ::localtime_r(&now, &timeinfo); #endif + + tz_len = std::strftime(tz_offset, sizeof(tz_offset), "%z", timeinfo_p); + + if (tz_len < kTzOffsetLen && tz_len > 1) { + // Timezone offset was written. strftime writes offset as +HHMM or -HHMM, + // RFC3339 specifies an offset as +HH:MM or -HH:MM. To convert, we parse + // the offset as an integer, then reprint it to a string. + + offset_minutes = ::strtol(tz_offset, NULL, 10); + if (offset_minutes < 0) { + offset_minutes *= -1; + tz_offset_sign = '-'; + } + + tz_len = ::snprintf(tz_offset, sizeof(tz_offset), "%c%02li:%02li", + tz_offset_sign, offset_minutes / 100, offset_minutes % 100); + CHECK(tz_len == kTzOffsetLen); + ((void)tz_len); // Prevent unused variable warning in optimized build. } else { + // Unknown offset. RFC3339 specifies that unknown local offsets should be + // written as UTC time with -00:00 timezone. #if defined(BENCHMARK_OS_WINDOWS) - written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now)); + // Potential race condition if another thread calls localtime or gmtime. + timeinfo_p = ::gmtime(&now); #else - std::tm timeinfo; ::gmtime_r(&now, &timeinfo); - written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); #endif + + strncpy(tz_offset, "-00:00", kTzOffsetLen + 1); } - CHECK(written < kStorageSize); - ((void)written); // prevent unused variable in optimized mode. - return std::string(storage); -} -} // end namespace + timestamp_len = std::strftime(storage, sizeof(storage), "%Y-%m-%dT%H:%M:%S", + timeinfo_p); + CHECK(timestamp_len == kTimestampLen); + // Prevent unused variable warning in optimized build. + ((void)kTimestampLen); -std::string LocalDateTimeString() { return DateTimeString(true); } + std::strncat(storage, tz_offset, sizeof(storage) - timestamp_len - 1); + return std::string(storage); +} } // end namespace benchmark diff --git a/libcxx/utils/google-benchmark/test/AssemblyTests.cmake b/libcxx/utils/google-benchmark/test/AssemblyTests.cmake index 8605221ff7107..3d078586f1de1 100644 --- a/libcxx/utils/google-benchmark/test/AssemblyTests.cmake +++ b/libcxx/utils/google-benchmark/test/AssemblyTests.cmake @@ -43,3 +43,4 @@ macro(add_filecheck_test name) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endforeach() endmacro() + diff --git a/libcxx/utils/google-benchmark/test/BUILD b/libcxx/utils/google-benchmark/test/BUILD new file mode 100644 index 0000000000000..1f27f99ede9f3 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/BUILD @@ -0,0 +1,74 @@ +TEST_COPTS = [ + "-pedantic", + "-pedantic-errors", + "-std=c++11", + "-Wall", + "-Wextra", + "-Wshadow", + # "-Wshorten-64-to-32", + "-Wfloat-equal", + "-fstrict-aliasing", +] + +PER_SRC_COPTS = ({ + "cxx03_test.cc": ["-std=c++03"], + # Some of the issues with DoNotOptimize only occur when optimization is enabled + "donotoptimize_test.cc": ["-O3"], +}) + +TEST_ARGS = ["--benchmark_min_time=0.01"] + +PER_SRC_TEST_ARGS = ({ + "user_counters_tabular_test.cc": ["--benchmark_counters_tabular=true"], + "repetitions_test.cc": [" --benchmark_repetitions=3"], +}) + +load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") + +cc_library( + name = "output_test_helper", + testonly = 1, + srcs = ["output_test_helper.cc"], + hdrs = ["output_test.h"], + copts = TEST_COPTS, + deps = [ + "//:benchmark", + "//:benchmark_internal_headers", + ], +) + +[ + cc_test( + name = test_src[:-len(".cc")], + size = "small", + srcs = [test_src], + args = TEST_ARGS + PER_SRC_TEST_ARGS.get(test_src, []), + copts = TEST_COPTS + PER_SRC_COPTS.get(test_src, []), + deps = [ + ":output_test_helper", + "//:benchmark", + "//:benchmark_internal_headers", + "@com_google_googletest//:gtest", + ] + ( + ["@com_google_googletest//:gtest_main"] if (test_src[-len("gtest.cc"):] == "gtest.cc") else [] + ), + # FIXME: Add support for assembly tests to bazel. + # See Issue #556 + # https://github.com/google/benchmark/issues/556 + ) + for test_src in glob( + ["*test.cc"], + exclude = [ + "*_assembly_test.cc", + "link_main_test.cc", + ], + ) +] + +cc_test( + name = "link_main_test", + size = "small", + srcs = ["link_main_test.cc"], + copts = TEST_COPTS, + deps = ["//:benchmark_main"], +) diff --git a/libcxx/utils/google-benchmark/test/CMakeLists.txt b/libcxx/utils/google-benchmark/test/CMakeLists.txt index f15ce20818993..79cdf53b402c8 100644 --- a/libcxx/utils/google-benchmark/test/CMakeLists.txt +++ b/libcxx/utils/google-benchmark/test/CMakeLists.txt @@ -38,28 +38,28 @@ add_library(output_test_helper STATIC output_test_helper.cc output_test.h) macro(compile_benchmark_test name) add_executable(${name} "${name}.cc") - target_link_libraries(${name} benchmark ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(${name} benchmark::benchmark ${CMAKE_THREAD_LIBS_INIT}) endmacro(compile_benchmark_test) macro(compile_benchmark_test_with_main name) add_executable(${name} "${name}.cc") - target_link_libraries(${name} benchmark_main) + target_link_libraries(${name} benchmark::benchmark_main) endmacro(compile_benchmark_test_with_main) macro(compile_output_test name) add_executable(${name} "${name}.cc" output_test.h) - target_link_libraries(${name} output_test_helper benchmark + target_link_libraries(${name} output_test_helper benchmark::benchmark ${BENCHMARK_CXX_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) endmacro(compile_output_test) # Demonstration executable compile_benchmark_test(benchmark_test) -add_test(benchmark benchmark_test --benchmark_min_time=0.01) +add_test(NAME benchmark COMMAND benchmark_test --benchmark_min_time=0.01) compile_benchmark_test(filter_test) macro(add_filter_test name filter expect) - add_test(${name} filter_test --benchmark_min_time=0.01 --benchmark_filter=${filter} ${expect}) - add_test(${name}_list_only filter_test --benchmark_list_tests --benchmark_filter=${filter} ${expect}) + add_test(NAME ${name} COMMAND filter_test --benchmark_min_time=0.01 --benchmark_filter=${filter} ${expect}) + add_test(NAME ${name}_list_only COMMAND filter_test --benchmark_list_tests --benchmark_filter=${filter} ${expect}) endmacro(add_filter_test) add_filter_test(filter_simple "Foo" 3) @@ -82,16 +82,19 @@ add_filter_test(filter_regex_end ".*Ba$" 1) add_filter_test(filter_regex_end_negative "-.*Ba$" 4) compile_benchmark_test(options_test) -add_test(options_benchmarks options_test --benchmark_min_time=0.01) +add_test(NAME options_benchmarks COMMAND options_test --benchmark_min_time=0.01) compile_benchmark_test(basic_test) -add_test(basic_benchmark basic_test --benchmark_min_time=0.01) +add_test(NAME basic_benchmark COMMAND basic_test --benchmark_min_time=0.01) + +compile_output_test(repetitions_test) +add_test(NAME repetitions_benchmark COMMAND repetitions_test --benchmark_min_time=0.01 --benchmark_repetitions=3) compile_benchmark_test(diagnostics_test) -add_test(diagnostics_test diagnostics_test --benchmark_min_time=0.01) +add_test(NAME diagnostics_test COMMAND diagnostics_test --benchmark_min_time=0.01) compile_benchmark_test(skip_with_error_test) -add_test(skip_with_error_test skip_with_error_test --benchmark_min_time=0.01) +add_test(NAME skip_with_error_test COMMAND skip_with_error_test --benchmark_min_time=0.01) compile_benchmark_test(donotoptimize_test) # Some of the issues with DoNotOptimize only occur when optimization is enabled @@ -99,53 +102,63 @@ check_cxx_compiler_flag(-O3 BENCHMARK_HAS_O3_FLAG) if (BENCHMARK_HAS_O3_FLAG) set_target_properties(donotoptimize_test PROPERTIES COMPILE_FLAGS "-O3") endif() -add_test(donotoptimize_test donotoptimize_test --benchmark_min_time=0.01) +add_test(NAME donotoptimize_test COMMAND donotoptimize_test --benchmark_min_time=0.01) compile_benchmark_test(fixture_test) -add_test(fixture_test fixture_test --benchmark_min_time=0.01) +add_test(NAME fixture_test COMMAND fixture_test --benchmark_min_time=0.01) compile_benchmark_test(register_benchmark_test) -add_test(register_benchmark_test register_benchmark_test --benchmark_min_time=0.01) +add_test(NAME register_benchmark_test COMMAND register_benchmark_test --benchmark_min_time=0.01) compile_benchmark_test(map_test) -add_test(map_test map_test --benchmark_min_time=0.01) +add_test(NAME map_test COMMAND map_test --benchmark_min_time=0.01) compile_benchmark_test(multiple_ranges_test) -add_test(multiple_ranges_test multiple_ranges_test --benchmark_min_time=0.01) +add_test(NAME multiple_ranges_test COMMAND multiple_ranges_test --benchmark_min_time=0.01) + +compile_benchmark_test(args_product_test) +add_test(NAME args_product_test COMMAND args_product_test --benchmark_min_time=0.01) compile_benchmark_test_with_main(link_main_test) -add_test(link_main_test link_main_test --benchmark_min_time=0.01) +add_test(NAME link_main_test COMMAND link_main_test --benchmark_min_time=0.01) compile_output_test(reporter_output_test) -add_test(reporter_output_test reporter_output_test --benchmark_min_time=0.01) +add_test(NAME reporter_output_test COMMAND reporter_output_test --benchmark_min_time=0.01) compile_output_test(templated_fixture_test) -add_test(templated_fixture_test templated_fixture_test --benchmark_min_time=0.01) +add_test(NAME templated_fixture_test COMMAND templated_fixture_test --benchmark_min_time=0.01) compile_output_test(user_counters_test) -add_test(user_counters_test user_counters_test --benchmark_min_time=0.01) +add_test(NAME user_counters_test COMMAND user_counters_test --benchmark_min_time=0.01) + +compile_output_test(perf_counters_test) +add_test(NAME perf_counters_test COMMAND perf_counters_test --benchmark_min_time=0.01 --benchmark_perf_counters=CYCLES,BRANCHES) + +compile_output_test(internal_threading_test) +add_test(NAME internal_threading_test COMMAND internal_threading_test --benchmark_min_time=0.01) compile_output_test(report_aggregates_only_test) -add_test(report_aggregates_only_test report_aggregates_only_test --benchmark_min_time=0.01) +add_test(NAME report_aggregates_only_test COMMAND report_aggregates_only_test --benchmark_min_time=0.01) compile_output_test(display_aggregates_only_test) -add_test(display_aggregates_only_test display_aggregates_only_test --benchmark_min_time=0.01) +add_test(NAME display_aggregates_only_test COMMAND display_aggregates_only_test --benchmark_min_time=0.01) compile_output_test(user_counters_tabular_test) -add_test(user_counters_tabular_test user_counters_tabular_test --benchmark_counters_tabular=true --benchmark_min_time=0.01) +add_test(NAME user_counters_tabular_test COMMAND user_counters_tabular_test --benchmark_counters_tabular=true --benchmark_min_time=0.01) compile_output_test(user_counters_thousands_test) -add_test(user_counters_thousands_test user_counters_thousands_test --benchmark_min_time=0.01) +add_test(NAME user_counters_thousands_test COMMAND user_counters_thousands_test --benchmark_min_time=0.01) compile_output_test(memory_manager_test) -add_test(memory_manager_test memory_manager_test --benchmark_min_time=0.01) +add_test(NAME memory_manager_test COMMAND memory_manager_test --benchmark_min_time=0.01) check_cxx_compiler_flag(-std=c++03 BENCHMARK_HAS_CXX03_FLAG) if (BENCHMARK_HAS_CXX03_FLAG) compile_benchmark_test(cxx03_test) set_target_properties(cxx03_test PROPERTIES - COMPILE_FLAGS "-std=c++03") + CXX_STANDARD 98 + CXX_STANDARD_REQUIRED YES) # libstdc++ provides different definitions within between dialects. When # LTO is enabled and -Werror is specified GCC diagnoses this ODR violation # causing the test to fail to compile. To prevent this we explicitly disable @@ -156,7 +169,7 @@ if (BENCHMARK_HAS_CXX03_FLAG) PROPERTIES LINK_FLAGS "-Wno-odr") endif() - add_test(cxx03 cxx03_test --benchmark_min_time=0.01) + add_test(NAME cxx03 COMMAND cxx03_test --benchmark_min_time=0.01) endif() # Attempt to work around flaky test failures when running on Appveyor servers. @@ -166,7 +179,7 @@ else() set(COMPLEXITY_MIN_TIME "0.01") endif() compile_output_test(complexity_test) -add_test(complexity_benchmark complexity_test --benchmark_min_time=${COMPLEXITY_MIN_TIME}) +add_test(NAME complexity_benchmark COMMAND complexity_test --benchmark_min_time=${COMPLEXITY_MIN_TIME}) ############################################################################### # GoogleTest Unit Tests @@ -175,24 +188,22 @@ add_test(complexity_benchmark complexity_test --benchmark_min_time=${COMPLEXITY_ if (BENCHMARK_ENABLE_GTEST_TESTS) macro(compile_gtest name) add_executable(${name} "${name}.cc") - if (TARGET googletest) - add_dependencies(${name} googletest) - endif() - if (GTEST_INCLUDE_DIRS) - target_include_directories(${name} PRIVATE ${GTEST_INCLUDE_DIRS}) - endif() - target_link_libraries(${name} benchmark - ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(${name} benchmark::benchmark + gmock_main ${CMAKE_THREAD_LIBS_INIT}) endmacro(compile_gtest) macro(add_gtest name) compile_gtest(${name}) - add_test(${name} ${name}) + add_test(NAME ${name} COMMAND ${name}) endmacro() add_gtest(benchmark_gtest) + add_gtest(benchmark_name_gtest) + add_gtest(benchmark_random_interleaving_gtest) + add_gtest(commandlineflags_gtest) add_gtest(statistics_gtest) add_gtest(string_util_gtest) + add_gtest(perf_counters_gtest) endif(BENCHMARK_ENABLE_GTEST_TESTS) ############################################################################### diff --git a/libcxx/utils/google-benchmark/test/args_product_test.cc b/libcxx/utils/google-benchmark/test/args_product_test.cc new file mode 100644 index 0000000000000..32a75d50dd9e2 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/args_product_test.cc @@ -0,0 +1,77 @@ +#include "benchmark/benchmark.h" + +#include +#include +#include +#include + +class ArgsProductFixture : public ::benchmark::Fixture { + public: + ArgsProductFixture() + : expectedValues({{0, 100, 2000, 30000}, + {1, 15, 3, 8}, + {1, 15, 3, 9}, + {1, 15, 7, 8}, + {1, 15, 7, 9}, + {1, 15, 10, 8}, + {1, 15, 10, 9}, + {2, 15, 3, 8}, + {2, 15, 3, 9}, + {2, 15, 7, 8}, + {2, 15, 7, 9}, + {2, 15, 10, 8}, + {2, 15, 10, 9}, + {4, 5, 6, 11}}) {} + + void SetUp(const ::benchmark::State& state) BENCHMARK_OVERRIDE { + std::vector ranges = {state.range(0), state.range(1), + state.range(2), state.range(3)}; + + assert(expectedValues.find(ranges) != expectedValues.end()); + + actualValues.insert(ranges); + } + + // NOTE: This is not TearDown as we want to check after _all_ runs are + // complete. + virtual ~ArgsProductFixture() { + if (actualValues != expectedValues) { + std::cout << "EXPECTED\n"; + for (auto v : expectedValues) { + std::cout << "{"; + for (int64_t iv : v) { + std::cout << iv << ", "; + } + std::cout << "}\n"; + } + std::cout << "ACTUAL\n"; + for (auto v : actualValues) { + std::cout << "{"; + for (int64_t iv : v) { + std::cout << iv << ", "; + } + std::cout << "}\n"; + } + } + } + + std::set> expectedValues; + std::set> actualValues; +}; + +BENCHMARK_DEFINE_F(ArgsProductFixture, Empty)(benchmark::State& state) { + for (auto _ : state) { + int64_t product = + state.range(0) * state.range(1) * state.range(2) * state.range(3); + for (int64_t x = 0; x < product; x++) { + benchmark::DoNotOptimize(x); + } + } +} + +BENCHMARK_REGISTER_F(ArgsProductFixture, Empty) + ->Args({0, 100, 2000, 30000}) + ->ArgsProduct({{1, 2}, {15}, {3, 7, 10}, {8, 9}}) + ->Args({4, 5, 6, 11}); + +BENCHMARK_MAIN(); diff --git a/libcxx/utils/google-benchmark/test/basic_test.cc b/libcxx/utils/google-benchmark/test/basic_test.cc index d07fbc00b1516..33642211e2058 100644 --- a/libcxx/utils/google-benchmark/test/basic_test.cc +++ b/libcxx/utils/google-benchmark/test/basic_test.cc @@ -98,7 +98,7 @@ BENCHMARK(BM_empty_stop_start)->ThreadPerCpu(); void BM_KeepRunning(benchmark::State& state) { - size_t iter_count = 0; + benchmark::IterationCount iter_count = 0; assert(iter_count == state.iterations()); while (state.KeepRunning()) { ++iter_count; @@ -108,18 +108,33 @@ void BM_KeepRunning(benchmark::State& state) { BENCHMARK(BM_KeepRunning); void BM_KeepRunningBatch(benchmark::State& state) { - // Choose a prime batch size to avoid evenly dividing max_iterations. - const size_t batch_size = 101; - size_t iter_count = 0; + // Choose a batch size >1000 to skip the typical runs with iteration + // targets of 10, 100 and 1000. If these are not actually skipped the + // bug would be detectable as consecutive runs with the same iteration + // count. Below we assert that this does not happen. + const benchmark::IterationCount batch_size = 1009; + + static benchmark::IterationCount prior_iter_count = 0; + benchmark::IterationCount iter_count = 0; while (state.KeepRunningBatch(batch_size)) { iter_count += batch_size; } assert(state.iterations() == iter_count); + + // Verify that the iteration count always increases across runs (see + // comment above). + assert(iter_count == batch_size // max_iterations == 1 + || iter_count > prior_iter_count); // max_iterations > batch_size + prior_iter_count = iter_count; } -BENCHMARK(BM_KeepRunningBatch); +// Register with a fixed repetition count to establish the invariant that +// the iteration count should always change across runs. This overrides +// the --benchmark_repetitions command line flag, which would otherwise +// cause this test to fail if set > 1. +BENCHMARK(BM_KeepRunningBatch)->Repetitions(1); void BM_RangedFor(benchmark::State& state) { - size_t iter_count = 0; + benchmark::IterationCount iter_count = 0; for (auto _ : state) { ++iter_count; } diff --git a/libcxx/utils/google-benchmark/test/benchmark_gtest.cc b/libcxx/utils/google-benchmark/test/benchmark_gtest.cc index 10683b433ab54..14a885ba46da4 100644 --- a/libcxx/utils/google-benchmark/test/benchmark_gtest.cc +++ b/libcxx/utils/google-benchmark/test/benchmark_gtest.cc @@ -1,9 +1,15 @@ +#include +#include #include #include "../src/benchmark_register.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +namespace benchmark { +namespace internal { +extern std::map* global_context; + namespace { TEST(AddRangeTest, Simple) { @@ -30,4 +36,130 @@ TEST(AddRangeTest, Advanced64) { EXPECT_THAT(dst, testing::ElementsAre(5, 8, 15)); } -} // end namespace +TEST(AddRangeTest, FullRange8) { + std::vector dst; + AddRange(&dst, int8_t{1}, std::numeric_limits::max(), 8); + EXPECT_THAT(dst, testing::ElementsAre(1, 8, 64, 127)); +} + +TEST(AddRangeTest, FullRange64) { + std::vector dst; + AddRange(&dst, int64_t{1}, std::numeric_limits::max(), 1024); + EXPECT_THAT( + dst, testing::ElementsAre(1LL, 1024LL, 1048576LL, 1073741824LL, + 1099511627776LL, 1125899906842624LL, + 1152921504606846976LL, 9223372036854775807LL)); +} + +TEST(AddRangeTest, NegativeRanges) { + std::vector dst; + AddRange(&dst, -8, 0, 2); + EXPECT_THAT(dst, testing::ElementsAre(-8, -4, -2, -1, 0)); +} + +TEST(AddRangeTest, StrictlyNegative) { + std::vector dst; + AddRange(&dst, -8, -1, 2); + EXPECT_THAT(dst, testing::ElementsAre(-8, -4, -2, -1)); +} + +TEST(AddRangeTest, SymmetricNegativeRanges) { + std::vector dst; + AddRange(&dst, -8, 8, 2); + EXPECT_THAT(dst, testing::ElementsAre(-8, -4, -2, -1, 0, 1, 2, 4, 8)); +} + +TEST(AddRangeTest, SymmetricNegativeRangesOddMult) { + std::vector dst; + AddRange(&dst, -30, 32, 5); + EXPECT_THAT(dst, testing::ElementsAre(-30, -25, -5, -1, 0, 1, 5, 25, 32)); +} + +TEST(AddRangeTest, NegativeRangesAsymmetric) { + std::vector dst; + AddRange(&dst, -3, 5, 2); + EXPECT_THAT(dst, testing::ElementsAre(-3, -2, -1, 0, 1, 2, 4, 5)); +} + +TEST(AddRangeTest, NegativeRangesLargeStep) { + // Always include -1, 0, 1 when crossing zero. + std::vector dst; + AddRange(&dst, -8, 8, 10); + EXPECT_THAT(dst, testing::ElementsAre(-8, -1, 0, 1, 8)); +} + +TEST(AddRangeTest, ZeroOnlyRange) { + std::vector dst; + AddRange(&dst, 0, 0, 2); + EXPECT_THAT(dst, testing::ElementsAre(0)); +} + +TEST(AddRangeTest, ZeroStartingRange) { + std::vector dst; + AddRange(&dst, 0, 2, 2); + EXPECT_THAT(dst, testing::ElementsAre(0, 1, 2)); +} + +TEST(AddRangeTest, NegativeRange64) { + std::vector dst; + AddRange(&dst, -4, 4, 2); + EXPECT_THAT(dst, testing::ElementsAre(-4, -2, -1, 0, 1, 2, 4)); +} + +TEST(AddRangeTest, NegativeRangePreservesExistingOrder) { + // If elements already exist in the range, ensure we don't change + // their ordering by adding negative values. + std::vector dst = {1, 2, 3}; + AddRange(&dst, -2, 2, 2); + EXPECT_THAT(dst, testing::ElementsAre(1, 2, 3, -2, -1, 0, 1, 2)); +} + +TEST(AddRangeTest, FullNegativeRange64) { + std::vector dst; + const auto min = std::numeric_limits::min(); + const auto max = std::numeric_limits::max(); + AddRange(&dst, min, max, 1024); + EXPECT_THAT( + dst, testing::ElementsAreArray(std::vector{ + min, -1152921504606846976LL, -1125899906842624LL, + -1099511627776LL, -1073741824LL, -1048576LL, -1024LL, -1LL, 0LL, + 1LL, 1024LL, 1048576LL, 1073741824LL, 1099511627776LL, + 1125899906842624LL, 1152921504606846976LL, max})); +} + +TEST(AddRangeTest, Simple8) { + std::vector dst; + AddRange(&dst, 1, 8, 2); + EXPECT_THAT(dst, testing::ElementsAre(1, 2, 4, 8)); +} + +TEST(AddCustomContext, Simple) { + EXPECT_THAT(global_context, nullptr); + + AddCustomContext("foo", "bar"); + AddCustomContext("baz", "qux"); + + EXPECT_THAT(*global_context, + testing::UnorderedElementsAre(testing::Pair("foo", "bar"), + testing::Pair("baz", "qux"))); + + delete global_context; + global_context = nullptr; +} + +TEST(AddCustomContext, DuplicateKey) { + EXPECT_THAT(global_context, nullptr); + + AddCustomContext("foo", "bar"); + AddCustomContext("foo", "qux"); + + EXPECT_THAT(*global_context, + testing::UnorderedElementsAre(testing::Pair("foo", "bar"))); + + delete global_context; + global_context = nullptr; +} + +} // namespace +} // namespace internal +} // namespace benchmark diff --git a/libcxx/utils/google-benchmark/test/benchmark_name_gtest.cc b/libcxx/utils/google-benchmark/test/benchmark_name_gtest.cc new file mode 100644 index 0000000000000..afb401c1f5328 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/benchmark_name_gtest.cc @@ -0,0 +1,74 @@ +#include "benchmark/benchmark.h" +#include "gtest/gtest.h" + +namespace { + +using namespace benchmark; +using namespace benchmark::internal; + +TEST(BenchmarkNameTest, Empty) { + const auto name = BenchmarkName(); + EXPECT_EQ(name.str(), std::string()); +} + +TEST(BenchmarkNameTest, FunctionName) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + EXPECT_EQ(name.str(), "function_name"); +} + +TEST(BenchmarkNameTest, FunctionNameAndArgs) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + name.args = "some_args:3/4/5"; + EXPECT_EQ(name.str(), "function_name/some_args:3/4/5"); +} + +TEST(BenchmarkNameTest, MinTime) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + name.args = "some_args:3/4"; + name.min_time = "min_time:3.4s"; + EXPECT_EQ(name.str(), "function_name/some_args:3/4/min_time:3.4s"); +} + +TEST(BenchmarkNameTest, Iterations) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + name.min_time = "min_time:3.4s"; + name.iterations = "iterations:42"; + EXPECT_EQ(name.str(), "function_name/min_time:3.4s/iterations:42"); +} + +TEST(BenchmarkNameTest, Repetitions) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + name.min_time = "min_time:3.4s"; + name.repetitions = "repetitions:24"; + EXPECT_EQ(name.str(), "function_name/min_time:3.4s/repetitions:24"); +} + +TEST(BenchmarkNameTest, TimeType) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + name.min_time = "min_time:3.4s"; + name.time_type = "hammer_time"; + EXPECT_EQ(name.str(), "function_name/min_time:3.4s/hammer_time"); +} + +TEST(BenchmarkNameTest, Threads) { + auto name = BenchmarkName(); + name.function_name = "function_name"; + name.min_time = "min_time:3.4s"; + name.threads = "threads:256"; + EXPECT_EQ(name.str(), "function_name/min_time:3.4s/threads:256"); +} + +TEST(BenchmarkNameTest, TestEmptyFunctionName) { + auto name = BenchmarkName(); + name.args = "first:3/second:4"; + name.threads = "threads:22"; + EXPECT_EQ(name.str(), "first:3/second:4/threads:22"); +} + +} // end namespace diff --git a/libcxx/utils/google-benchmark/test/benchmark_random_interleaving_gtest.cc b/libcxx/utils/google-benchmark/test/benchmark_random_interleaving_gtest.cc new file mode 100644 index 0000000000000..8e28dab3f41d3 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/benchmark_random_interleaving_gtest.cc @@ -0,0 +1,126 @@ +#include +#include +#include + +#include "../src/commandlineflags.h" +#include "../src/string_util.h" +#include "benchmark/benchmark.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +DECLARE_bool(benchmark_enable_random_interleaving); +DECLARE_string(benchmark_filter); +DECLARE_int32(benchmark_repetitions); + +namespace benchmark { +namespace internal { +namespace { + +class EventQueue : public std::queue { + public: + void Put(const std::string& event) { push(event); } + + void Clear() { + while (!empty()) { + pop(); + } + } + + std::string Get() { + std::string event = front(); + pop(); + return event; + } +}; + +static EventQueue* queue = new EventQueue; + +class NullReporter : public BenchmarkReporter { + public: + bool ReportContext(const Context& /*context*/) override { return true; } + void ReportRuns(const std::vector& /* report */) override {} +}; + +class BenchmarkTest : public testing::Test { + public: + static void SetupHook(int /* num_threads */) { queue->push("Setup"); } + + static void TeardownHook(int /* num_threads */) { queue->push("Teardown"); } + + void Execute(const std::string& pattern) { + queue->Clear(); + + BenchmarkReporter* reporter = new NullReporter; + FLAGS_benchmark_filter = pattern; + RunSpecifiedBenchmarks(reporter); + delete reporter; + + queue->Put("DONE"); // End marker + } +}; + +static void BM_Match1(benchmark::State& state) { + const int64_t arg = state.range(0); + + for (auto _ : state) { + } + queue->Put(StrFormat("BM_Match1/%d", static_cast(arg))); +} +BENCHMARK(BM_Match1) + ->Iterations(100) + ->Arg(1) + ->Arg(2) + ->Arg(3) + ->Range(10, 80) + ->Args({90}) + ->Args({100}); + +TEST_F(BenchmarkTest, Match1) { + Execute("BM_Match1"); + ASSERT_EQ("BM_Match1/1", queue->Get()); + ASSERT_EQ("BM_Match1/2", queue->Get()); + ASSERT_EQ("BM_Match1/3", queue->Get()); + ASSERT_EQ("BM_Match1/10", queue->Get()); + ASSERT_EQ("BM_Match1/64", queue->Get()); + ASSERT_EQ("BM_Match1/80", queue->Get()); + ASSERT_EQ("BM_Match1/90", queue->Get()); + ASSERT_EQ("BM_Match1/100", queue->Get()); + ASSERT_EQ("DONE", queue->Get()); +} + +TEST_F(BenchmarkTest, Match1WithRepetition) { + FLAGS_benchmark_repetitions = 2; + + Execute("BM_Match1/(64|80)"); + ASSERT_EQ("BM_Match1/64", queue->Get()); + ASSERT_EQ("BM_Match1/64", queue->Get()); + ASSERT_EQ("BM_Match1/80", queue->Get()); + ASSERT_EQ("BM_Match1/80", queue->Get()); + ASSERT_EQ("DONE", queue->Get()); +} + +TEST_F(BenchmarkTest, Match1WithRandomInterleaving) { + FLAGS_benchmark_enable_random_interleaving = true; + FLAGS_benchmark_repetitions = 100; + + std::map element_count; + std::map interleaving_count; + Execute("BM_Match1/(64|80)"); + for (int i = 0; i < 100; ++i) { + std::vector interleaving; + interleaving.push_back(queue->Get()); + interleaving.push_back(queue->Get()); + element_count[interleaving[0].c_str()]++; + element_count[interleaving[1].c_str()]++; + interleaving_count[StrFormat("%s,%s", interleaving[0].c_str(), + interleaving[1].c_str())]++; + } + EXPECT_EQ(element_count["BM_Match1/64"], 100) << "Unexpected repetitions."; + EXPECT_EQ(element_count["BM_Match1/80"], 100) << "Unexpected repetitions."; + EXPECT_GE(interleaving_count.size(), 2) << "Interleaving was not randomized."; + ASSERT_EQ("DONE", queue->Get()); +} + +} // namespace +} // namespace internal +} // namespace benchmark diff --git a/libcxx/utils/google-benchmark/test/commandlineflags_gtest.cc b/libcxx/utils/google-benchmark/test/commandlineflags_gtest.cc new file mode 100644 index 0000000000000..8412008ffe359 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/commandlineflags_gtest.cc @@ -0,0 +1,228 @@ +#include + +#include "../src/commandlineflags.h" +#include "../src/internal_macros.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace benchmark { +namespace { + +#if defined(BENCHMARK_OS_WINDOWS) +int setenv(const char* name, const char* value, int overwrite) { + if (!overwrite) { + // NOTE: getenv_s is far superior but not available under mingw. + char* env_value = getenv(name); + if (env_value == nullptr) { + return -1; + } + } + return _putenv_s(name, value); +} + +int unsetenv(const char* name) { return _putenv_s(name, ""); } + +#endif // BENCHMARK_OS_WINDOWS + +TEST(BoolFromEnv, Default) { + ASSERT_EQ(unsetenv("NOT_IN_ENV"), 0); + EXPECT_EQ(BoolFromEnv("not_in_env", true), true); +} + +TEST(BoolFromEnv, False) { + ASSERT_EQ(setenv("IN_ENV", "0", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "N", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "n", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "NO", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "No", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "no", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "F", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "f", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "FALSE", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "False", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "false", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "OFF", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "Off", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "off", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", true), false); + unsetenv("IN_ENV"); +} + +TEST(BoolFromEnv, True) { + ASSERT_EQ(setenv("IN_ENV", "1", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "Y", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "y", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "YES", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "Yes", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "yes", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "T", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "t", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "TRUE", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "True", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "true", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "ON", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "On", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + + ASSERT_EQ(setenv("IN_ENV", "on", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); + +#ifndef BENCHMARK_OS_WINDOWS + ASSERT_EQ(setenv("IN_ENV", "", 1), 0); + EXPECT_EQ(BoolFromEnv("in_env", false), true); + unsetenv("IN_ENV"); +#endif +} + +TEST(Int32FromEnv, NotInEnv) { + ASSERT_EQ(unsetenv("NOT_IN_ENV"), 0); + EXPECT_EQ(Int32FromEnv("not_in_env", 42), 42); +} + +TEST(Int32FromEnv, InvalidInteger) { + ASSERT_EQ(setenv("IN_ENV", "foo", 1), 0); + EXPECT_EQ(Int32FromEnv("in_env", 42), 42); + unsetenv("IN_ENV"); +} + +TEST(Int32FromEnv, ValidInteger) { + ASSERT_EQ(setenv("IN_ENV", "42", 1), 0); + EXPECT_EQ(Int32FromEnv("in_env", 64), 42); + unsetenv("IN_ENV"); +} + +TEST(DoubleFromEnv, NotInEnv) { + ASSERT_EQ(unsetenv("NOT_IN_ENV"), 0); + EXPECT_EQ(DoubleFromEnv("not_in_env", 0.51), 0.51); +} + +TEST(DoubleFromEnv, InvalidReal) { + ASSERT_EQ(setenv("IN_ENV", "foo", 1), 0); + EXPECT_EQ(DoubleFromEnv("in_env", 0.51), 0.51); + unsetenv("IN_ENV"); +} + +TEST(DoubleFromEnv, ValidReal) { + ASSERT_EQ(setenv("IN_ENV", "0.51", 1), 0); + EXPECT_EQ(DoubleFromEnv("in_env", 0.71), 0.51); + unsetenv("IN_ENV"); +} + +TEST(StringFromEnv, Default) { + ASSERT_EQ(unsetenv("NOT_IN_ENV"), 0); + EXPECT_STREQ(StringFromEnv("not_in_env", "foo"), "foo"); +} + +TEST(StringFromEnv, Valid) { + ASSERT_EQ(setenv("IN_ENV", "foo", 1), 0); + EXPECT_STREQ(StringFromEnv("in_env", "bar"), "foo"); + unsetenv("IN_ENV"); +} + +TEST(KvPairsFromEnv, Default) { + ASSERT_EQ(unsetenv("NOT_IN_ENV"), 0); + EXPECT_THAT(KvPairsFromEnv("not_in_env", {{"foo", "bar"}}), + testing::ElementsAre(testing::Pair("foo", "bar"))); +} + +TEST(KvPairsFromEnv, MalformedReturnsDefault) { + ASSERT_EQ(setenv("IN_ENV", "foo", 1), 0); + EXPECT_THAT(KvPairsFromEnv("in_env", {{"foo", "bar"}}), + testing::ElementsAre(testing::Pair("foo", "bar"))); + unsetenv("IN_ENV"); +} + +TEST(KvPairsFromEnv, Single) { + ASSERT_EQ(setenv("IN_ENV", "foo=bar", 1), 0); + EXPECT_THAT(KvPairsFromEnv("in_env", {}), + testing::ElementsAre(testing::Pair("foo", "bar"))); + unsetenv("IN_ENV"); +} + +TEST(KvPairsFromEnv, Multiple) { + ASSERT_EQ(setenv("IN_ENV", "foo=bar,baz=qux", 1), 0); + EXPECT_THAT(KvPairsFromEnv("in_env", {}), + testing::UnorderedElementsAre(testing::Pair("foo", "bar"), + testing::Pair("baz", "qux"))); + unsetenv("IN_ENV"); +} + +} // namespace +} // namespace benchmark diff --git a/libcxx/utils/google-benchmark/test/complexity_test.cc b/libcxx/utils/google-benchmark/test/complexity_test.cc index 323ddfe7ac595..0de73c5722b51 100644 --- a/libcxx/utils/google-benchmark/test/complexity_test.cc +++ b/libcxx/utils/google-benchmark/test/complexity_test.cc @@ -13,7 +13,8 @@ namespace { int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__) int AddComplexityTest(std::string test_name, std::string big_o_test_name, - std::string rms_test_name, std::string big_o) { + std::string rms_test_name, std::string big_o, + int family_index) { SetSubstitutions({{"%name", test_name}, {"%bigo_name", big_o_test_name}, {"%rms_name", rms_test_name}, @@ -25,21 +26,31 @@ int AddComplexityTest(std::string test_name, std::string big_o_test_name, {{"^%bigo_name %bigo_str %bigo_str[ ]*$"}, {"^%bigo_name", MR_Not}, // Assert we we didn't only matched a name. {"^%rms_name %rms %rms[ ]*$", MR_Next}}); - AddCases(TC_JSONOut, {{"\"name\": \"%bigo_name\",$"}, - {"\"run_name\": \"%name\",$", MR_Next}, - {"\"run_type\": \"aggregate\",$", MR_Next}, - {"\"aggregate_name\": \"BigO\",$", MR_Next}, - {"\"cpu_coefficient\": %float,$", MR_Next}, - {"\"real_coefficient\": %float,$", MR_Next}, - {"\"big_o\": \"%bigo\",$", MR_Next}, - {"\"time_unit\": \"ns\"$", MR_Next}, - {"}", MR_Next}, - {"\"name\": \"%rms_name\",$"}, - {"\"run_name\": \"%name\",$", MR_Next}, - {"\"run_type\": \"aggregate\",$", MR_Next}, - {"\"aggregate_name\": \"RMS\",$", MR_Next}, - {"\"rms\": %float$", MR_Next}, - {"}", MR_Next}}); + AddCases( + TC_JSONOut, + {{"\"name\": \"%bigo_name\",$"}, + {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"%name\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": %int,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"BigO\",$", MR_Next}, + {"\"cpu_coefficient\": %float,$", MR_Next}, + {"\"real_coefficient\": %float,$", MR_Next}, + {"\"big_o\": \"%bigo\",$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}, + {"\"name\": \"%rms_name\",$"}, + {"\"family_index\": " + std::to_string(family_index) + ",$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"%name\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": %int,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"RMS\",$", MR_Next}, + {"\"rms\": %float$", MR_Next}, + {"}", MR_Next}}); AddCases(TC_CSVOut, {{"^\"%bigo_name\",,%float,%float,%bigo,,,,,$"}, {"^\"%bigo_name\"", MR_Not}, {"^\"%rms_name\",,%float,%float,,,,,,$", MR_Next}}); @@ -62,9 +73,9 @@ void BM_Complexity_O1(benchmark::State& state) { } BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(benchmark::o1); BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(); -BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity([](int64_t) { - return 1.0; -}); +BENCHMARK(BM_Complexity_O1) + ->Range(1, 1 << 18) + ->Complexity([](benchmark::IterationCount) { return 1.0; }); const char *one_test_name = "BM_Complexity_O1"; const char *big_o_1_test_name = "BM_Complexity_O1_BigO"; @@ -78,15 +89,15 @@ const char *lambda_big_o_1 = "f\\(N\\)"; // Add enum tests ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, - enum_big_o_1); + enum_big_o_1, /*family_index=*/0); // Add auto enum tests ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, - auto_big_o_1); + auto_big_o_1, /*family_index=*/1); // Add lambda tests ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name, - lambda_big_o_1); + lambda_big_o_1, /*family_index=*/2); // ========================================================================= // // --------------------------- Testing BigO O(N) --------------------------- // @@ -117,7 +128,9 @@ BENCHMARK(BM_Complexity_O_N) BENCHMARK(BM_Complexity_O_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) - ->Complexity([](int64_t n) -> double { return static_cast(n); }); + ->Complexity([](benchmark::IterationCount n) -> double { + return static_cast(n); + }); BENCHMARK(BM_Complexity_O_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) @@ -131,11 +144,11 @@ const char *lambda_big_o_n = "f\\(N\\)"; // Add enum tests ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name, - enum_auto_big_o_n); + enum_auto_big_o_n, /*family_index=*/3); // Add lambda tests ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name, - lambda_big_o_n); + lambda_big_o_n, /*family_index=*/4); // ========================================================================= // // ------------------------- Testing BigO O(N*lgN) ------------------------- // @@ -156,7 +169,9 @@ BENCHMARK(BM_Complexity_O_N_log_N) BENCHMARK(BM_Complexity_O_N_log_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) - ->Complexity([](int64_t n) { return kLog2E * n * log(static_cast(n)); }); + ->Complexity([](benchmark::IterationCount n) { + return kLog2E * n * log(static_cast(n)); + }); BENCHMARK(BM_Complexity_O_N_log_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) @@ -170,11 +185,35 @@ const char *lambda_big_o_n_lg_n = "f\\(N\\)"; // Add enum tests ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name, - rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n); + rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n, + /*family_index=*/6); // Add lambda tests ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name, - rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n); + rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n, + /*family_index=*/7); + +// ========================================================================= // +// -------- Testing formatting of Complexity with captured args ------------ // +// ========================================================================= // + +void BM_ComplexityCaptureArgs(benchmark::State& state, int n) { + for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); + } + state.SetComplexityN(n); +} + +BENCHMARK_CAPTURE(BM_ComplexityCaptureArgs, capture_test, 100) + ->Complexity(benchmark::oN) + ->Ranges({{1, 2}, {3, 4}}); + +const std::string complexity_capture_name = + "BM_ComplexityCaptureArgs/capture_test"; + +ADD_COMPLEXITY_CASES(complexity_capture_name, complexity_capture_name + "_BigO", + complexity_capture_name + "_RMS", "N", /*family_index=*/9); // ========================================================================= // // --------------------------- TEST CASES END ------------------------------ // diff --git a/libcxx/utils/google-benchmark/test/cxx03_test.cc b/libcxx/utils/google-benchmark/test/cxx03_test.cc index baa9ed9262baa..c4c9a52273e3a 100644 --- a/libcxx/utils/google-benchmark/test/cxx03_test.cc +++ b/libcxx/utils/google-benchmark/test/cxx03_test.cc @@ -14,7 +14,7 @@ void BM_empty(benchmark::State& state) { while (state.KeepRunning()) { - volatile std::size_t x = state.iterations(); + volatile benchmark::IterationCount x = state.iterations(); ((void)x); } } diff --git a/libcxx/utils/google-benchmark/test/filter_test.cc b/libcxx/utils/google-benchmark/test/filter_test.cc index 0e27065c1558e..1c198913b36a6 100644 --- a/libcxx/utils/google-benchmark/test/filter_test.cc +++ b/libcxx/utils/google-benchmark/test/filter_test.cc @@ -1,36 +1,41 @@ -#include "benchmark/benchmark.h" - +#include #include #include #include #include - #include #include #include #include +#include "benchmark/benchmark.h" + namespace { class TestReporter : public benchmark::ConsoleReporter { public: - virtual bool ReportContext(const Context& context) { + virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE { return ConsoleReporter::ReportContext(context); }; - virtual void ReportRuns(const std::vector& report) { + virtual void ReportRuns(const std::vector& report) BENCHMARK_OVERRIDE { ++count_; + max_family_index_ = + std::max(max_family_index_, report[0].family_index); ConsoleReporter::ReportRuns(report); }; - TestReporter() : count_(0) {} + TestReporter() : count_(0), max_family_index_(0) {} virtual ~TestReporter() {} size_t GetCount() const { return count_; } + size_t GetMaxFamilyIndex() const { return max_family_index_; } + private: mutable size_t count_; + mutable size_t max_family_index_; }; } // end namespace @@ -98,6 +103,15 @@ int main(int argc, char **argv) { << std::endl; return -1; } + + const size_t max_family_index = test_reporter.GetMaxFamilyIndex(); + const size_t num_families = reports_count == 0 ? 0 : 1 + max_family_index; + if (num_families != expected_reports) { + std::cerr << "ERROR: Expected " << expected_reports + << " test families to be run but num_families = " + << num_families << std::endl; + return -1; + } } return 0; diff --git a/libcxx/utils/google-benchmark/test/fixture_test.cc b/libcxx/utils/google-benchmark/test/fixture_test.cc index 1462b10f02f96..eba0a42d9cb04 100644 --- a/libcxx/utils/google-benchmark/test/fixture_test.cc +++ b/libcxx/utils/google-benchmark/test/fixture_test.cc @@ -4,35 +4,37 @@ #include #include -class MyFixture : public ::benchmark::Fixture { +#define FIXTURE_BECHMARK_NAME MyFixture + +class FIXTURE_BECHMARK_NAME : public ::benchmark::Fixture { public: - void SetUp(const ::benchmark::State& state) { + void SetUp(const ::benchmark::State& state) BENCHMARK_OVERRIDE { if (state.thread_index == 0) { assert(data.get() == nullptr); data.reset(new int(42)); } } - void TearDown(const ::benchmark::State& state) { + void TearDown(const ::benchmark::State& state) BENCHMARK_OVERRIDE { if (state.thread_index == 0) { assert(data.get() != nullptr); data.reset(); } } - ~MyFixture() { assert(data == nullptr); } + ~FIXTURE_BECHMARK_NAME() { assert(data == nullptr); } std::unique_ptr data; }; -BENCHMARK_F(MyFixture, Foo)(benchmark::State &st) { +BENCHMARK_F(FIXTURE_BECHMARK_NAME, Foo)(benchmark::State &st) { assert(data.get() != nullptr); assert(*data == 42); for (auto _ : st) { } } -BENCHMARK_DEFINE_F(MyFixture, Bar)(benchmark::State& st) { +BENCHMARK_DEFINE_F(FIXTURE_BECHMARK_NAME, Bar)(benchmark::State& st) { if (st.thread_index == 0) { assert(data.get() != nullptr); assert(*data == 42); @@ -43,7 +45,7 @@ BENCHMARK_DEFINE_F(MyFixture, Bar)(benchmark::State& st) { } st.SetItemsProcessed(st.range(0)); } -BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42); -BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42)->ThreadPerCpu(); +BENCHMARK_REGISTER_F(FIXTURE_BECHMARK_NAME, Bar)->Arg(42); +BENCHMARK_REGISTER_F(FIXTURE_BECHMARK_NAME, Bar)->Arg(42)->ThreadPerCpu(); BENCHMARK_MAIN(); diff --git a/libcxx/utils/google-benchmark/test/internal_threading_test.cc b/libcxx/utils/google-benchmark/test/internal_threading_test.cc new file mode 100644 index 0000000000000..039d7c14a8c48 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/internal_threading_test.cc @@ -0,0 +1,184 @@ + +#undef NDEBUG + +#include +#include +#include "../src/timers.h" +#include "benchmark/benchmark.h" +#include "output_test.h" + +static const std::chrono::duration time_frame(50); +static const double time_frame_in_sec( + std::chrono::duration_cast>>( + time_frame) + .count()); + +void MyBusySpinwait() { + const auto start = benchmark::ChronoClockNow(); + + while (true) { + const auto now = benchmark::ChronoClockNow(); + const auto elapsed = now - start; + + if (std::chrono::duration(elapsed) >= + time_frame) + return; + } +} + +// ========================================================================= // +// --------------------------- TEST CASES BEGIN ---------------------------- // +// ========================================================================= // + +// ========================================================================= // +// BM_MainThread + +void BM_MainThread(benchmark::State& state) { + for (auto _ : state) { + MyBusySpinwait(); + state.SetIterationTime(time_frame_in_sec); + } + state.counters["invtime"] = + benchmark::Counter{1, benchmark::Counter::kIsRate}; +} + +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1); +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1)->UseRealTime(); +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1)->UseManualTime(); +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1)->MeasureProcessCPUTime(); +BENCHMARK(BM_MainThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime() + ->UseRealTime(); +BENCHMARK(BM_MainThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime() + ->UseManualTime(); + +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2); +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2)->UseRealTime(); +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2)->UseManualTime(); +BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2)->MeasureProcessCPUTime(); +BENCHMARK(BM_MainThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime() + ->UseRealTime(); +BENCHMARK(BM_MainThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime() + ->UseManualTime(); + +// ========================================================================= // +// BM_WorkerThread + +void BM_WorkerThread(benchmark::State& state) { + for (auto _ : state) { + std::thread Worker(&MyBusySpinwait); + Worker.join(); + state.SetIterationTime(time_frame_in_sec); + } + state.counters["invtime"] = + benchmark::Counter{1, benchmark::Counter::kIsRate}; +} + +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1); +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1)->UseRealTime(); +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1)->UseManualTime(); +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1)->MeasureProcessCPUTime(); +BENCHMARK(BM_WorkerThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime() + ->UseRealTime(); +BENCHMARK(BM_WorkerThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime() + ->UseManualTime(); + +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2); +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2)->UseRealTime(); +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2)->UseManualTime(); +BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2)->MeasureProcessCPUTime(); +BENCHMARK(BM_WorkerThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime() + ->UseRealTime(); +BENCHMARK(BM_WorkerThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime() + ->UseManualTime(); + +// ========================================================================= // +// BM_MainThreadAndWorkerThread + +void BM_MainThreadAndWorkerThread(benchmark::State& state) { + for (auto _ : state) { + std::thread Worker(&MyBusySpinwait); + MyBusySpinwait(); + Worker.join(); + state.SetIterationTime(time_frame_in_sec); + } + state.counters["invtime"] = + benchmark::Counter{1, benchmark::Counter::kIsRate}; +} + +BENCHMARK(BM_MainThreadAndWorkerThread)->Iterations(1)->Threads(1); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(1) + ->UseRealTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(1) + ->UseManualTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime() + ->UseRealTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(1) + ->MeasureProcessCPUTime() + ->UseManualTime(); + +BENCHMARK(BM_MainThreadAndWorkerThread)->Iterations(1)->Threads(2); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(2) + ->UseRealTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(2) + ->UseManualTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime() + ->UseRealTime(); +BENCHMARK(BM_MainThreadAndWorkerThread) + ->Iterations(1) + ->Threads(2) + ->MeasureProcessCPUTime() + ->UseManualTime(); + +// ========================================================================= // +// ---------------------------- TEST CASES END ----------------------------- // +// ========================================================================= // + +int main(int argc, char* argv[]) { RunOutputTests(argc, argv); } diff --git a/libcxx/utils/google-benchmark/test/map_test.cc b/libcxx/utils/google-benchmark/test/map_test.cc index dbf7982a3686e..86391b36016fd 100644 --- a/libcxx/utils/google-benchmark/test/map_test.cc +++ b/libcxx/utils/google-benchmark/test/map_test.cc @@ -34,11 +34,11 @@ BENCHMARK(BM_MapLookup)->Range(1 << 3, 1 << 12); // Using fixtures. class MapFixture : public ::benchmark::Fixture { public: - void SetUp(const ::benchmark::State& st) { + void SetUp(const ::benchmark::State& st) BENCHMARK_OVERRIDE { m = ConstructRandomMap(static_cast(st.range(0))); } - void TearDown(const ::benchmark::State&) { m.clear(); } + void TearDown(const ::benchmark::State&) BENCHMARK_OVERRIDE { m.clear(); } std::map m; }; diff --git a/libcxx/utils/google-benchmark/test/memory_manager_test.cc b/libcxx/utils/google-benchmark/test/memory_manager_test.cc index 94be6083795e6..f0c192fcbd00d 100644 --- a/libcxx/utils/google-benchmark/test/memory_manager_test.cc +++ b/libcxx/utils/google-benchmark/test/memory_manager_test.cc @@ -5,8 +5,8 @@ #include "output_test.h" class TestMemoryManager : public benchmark::MemoryManager { - void Start() {} - void Stop(Result* result) { + void Start() BENCHMARK_OVERRIDE {} + void Stop(Result* result) BENCHMARK_OVERRIDE { result->num_allocs = 42; result->max_bytes_used = 42000; } @@ -21,8 +21,13 @@ BENCHMARK(BM_empty); ADD_CASES(TC_ConsoleOut, {{"^BM_empty %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_empty\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_empty\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -32,8 +37,7 @@ ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_empty\",$"}, {"}", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_empty\",%csv_report$"}}); - -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { std::unique_ptr mm(new TestMemoryManager()); benchmark::RegisterMemoryManager(mm.get()); diff --git a/libcxx/utils/google-benchmark/test/multiple_ranges_test.cc b/libcxx/utils/google-benchmark/test/multiple_ranges_test.cc index c64acabc25c98..6b61f3af47bb9 100644 --- a/libcxx/utils/google-benchmark/test/multiple_ranges_test.cc +++ b/libcxx/utils/google-benchmark/test/multiple_ranges_test.cc @@ -28,7 +28,7 @@ class MultipleRangesFixture : public ::benchmark::Fixture { {2, 7, 15}, {7, 6, 3}}) {} - void SetUp(const ::benchmark::State& state) { + void SetUp(const ::benchmark::State& state) BENCHMARK_OVERRIDE { std::vector ranges = {state.range(0), state.range(1), state.range(2)}; @@ -40,8 +40,7 @@ class MultipleRangesFixture : public ::benchmark::Fixture { // NOTE: This is not TearDown as we want to check after _all_ runs are // complete. virtual ~MultipleRangesFixture() { - assert(actualValues.size() == expectedValues.size()); - if (actualValues.size() != expectedValues.size()) { + if (actualValues != expectedValues) { std::cout << "EXPECTED\n"; for (auto v : expectedValues) { std::cout << "{"; diff --git a/libcxx/utils/google-benchmark/test/options_test.cc b/libcxx/utils/google-benchmark/test/options_test.cc index fdec69174eec0..9f9a78667c9ee 100644 --- a/libcxx/utils/google-benchmark/test/options_test.cc +++ b/libcxx/utils/google-benchmark/test/options_test.cc @@ -25,6 +25,7 @@ BENCHMARK(BM_basic)->Arg(42); BENCHMARK(BM_basic_slow)->Arg(10)->Unit(benchmark::kNanosecond); BENCHMARK(BM_basic_slow)->Arg(100)->Unit(benchmark::kMicrosecond); BENCHMARK(BM_basic_slow)->Arg(1000)->Unit(benchmark::kMillisecond); +BENCHMARK(BM_basic_slow)->Arg(1000)->Unit(benchmark::kSecond); BENCHMARK(BM_basic)->Range(1, 8); BENCHMARK(BM_basic)->RangeMultiplier(2)->Range(1, 8); BENCHMARK(BM_basic)->DenseRange(10, 15); @@ -35,6 +36,16 @@ BENCHMARK(BM_basic)->UseRealTime(); BENCHMARK(BM_basic)->ThreadRange(2, 4); BENCHMARK(BM_basic)->ThreadPerCpu(); BENCHMARK(BM_basic)->Repetitions(3); +BENCHMARK(BM_basic) + ->RangeMultiplier(std::numeric_limits::max()) + ->Range(std::numeric_limits::min(), + std::numeric_limits::max()); + +// Negative ranges +BENCHMARK(BM_basic)->Range(-64, -1); +BENCHMARK(BM_basic)->RangeMultiplier(4)->Range(-8, 8); +BENCHMARK(BM_basic)->DenseRange(-2, 2, 1); +BENCHMARK(BM_basic)->Ranges({{-64, 1}, {-8, -1}}); void CustomArgs(benchmark::internal::Benchmark* b) { for (int i = 0; i < 10; ++i) { diff --git a/libcxx/utils/google-benchmark/test/output_test.h b/libcxx/utils/google-benchmark/test/output_test.h index 9385761b214c7..15368f9b68309 100644 --- a/libcxx/utils/google-benchmark/test/output_test.h +++ b/libcxx/utils/google-benchmark/test/output_test.h @@ -158,7 +158,7 @@ T Results::GetAs(const char* entry_name) const { // clang-format off -#define _CHECK_RESULT_VALUE(entry, getfn, var_type, var_name, relationship, value) \ +#define CHECK_RESULT_VALUE_IMPL(entry, getfn, var_type, var_name, relationship, value) \ CONCAT(CHECK_, relationship) \ (entry.getfn< var_type >(var_name), (value)) << "\n" \ << __FILE__ << ":" << __LINE__ << ": " << (entry).name << ":\n" \ @@ -169,7 +169,7 @@ T Results::GetAs(const char* entry_name) const { // check with tolerance. eps_factor is the tolerance window, which is // interpreted relative to value (eg, 0.1 means 10% of value). -#define _CHECK_FLOAT_RESULT_VALUE(entry, getfn, var_type, var_name, relationship, value, eps_factor) \ +#define CHECK_FLOAT_RESULT_VALUE_IMPL(entry, getfn, var_type, var_name, relationship, value, eps_factor) \ CONCAT(CHECK_FLOAT_, relationship) \ (entry.getfn< var_type >(var_name), (value), (eps_factor) * (value)) << "\n" \ << __FILE__ << ":" << __LINE__ << ": " << (entry).name << ":\n" \ @@ -187,16 +187,16 @@ T Results::GetAs(const char* entry_name) const { << "%)" #define CHECK_RESULT_VALUE(entry, var_type, var_name, relationship, value) \ - _CHECK_RESULT_VALUE(entry, GetAs, var_type, var_name, relationship, value) + CHECK_RESULT_VALUE_IMPL(entry, GetAs, var_type, var_name, relationship, value) #define CHECK_COUNTER_VALUE(entry, var_type, var_name, relationship, value) \ - _CHECK_RESULT_VALUE(entry, GetCounterAs, var_type, var_name, relationship, value) + CHECK_RESULT_VALUE_IMPL(entry, GetCounterAs, var_type, var_name, relationship, value) #define CHECK_FLOAT_RESULT_VALUE(entry, var_name, relationship, value, eps_factor) \ - _CHECK_FLOAT_RESULT_VALUE(entry, GetAs, double, var_name, relationship, value, eps_factor) + CHECK_FLOAT_RESULT_VALUE_IMPL(entry, GetAs, double, var_name, relationship, value, eps_factor) #define CHECK_FLOAT_COUNTER_VALUE(entry, var_name, relationship, value, eps_factor) \ - _CHECK_FLOAT_RESULT_VALUE(entry, GetCounterAs, double, var_name, relationship, value, eps_factor) + CHECK_FLOAT_RESULT_VALUE_IMPL(entry, GetCounterAs, double, var_name, relationship, value, eps_factor) // clang-format on diff --git a/libcxx/utils/google-benchmark/test/output_test_helper.cc b/libcxx/utils/google-benchmark/test/output_test_helper.cc index 5dc951d2bca87..b8ef1205744ac 100644 --- a/libcxx/utils/google-benchmark/test/output_test_helper.cc +++ b/libcxx/utils/google-benchmark/test/output_test_helper.cc @@ -48,6 +48,9 @@ SubMap& GetSubstitutions() { {" %s ", "[ ]+"}, {"%time", "[ ]*" + time_re + "[ ]+ns"}, {"%console_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns [ ]*[0-9]+"}, + {"%console_us_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us [ ]*[0-9]+"}, + {"%console_ms_report", "[ ]*" + time_re + "[ ]+ms [ ]*" + time_re + "[ ]+ms [ ]*[0-9]+"}, + {"%console_s_report", "[ ]*" + time_re + "[ ]+s [ ]*" + time_re + "[ ]+s [ ]*[0-9]+"}, {"%console_time_only_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns"}, {"%console_us_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us [ ]*[0-9]+"}, {"%console_us_time_only_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us"}, @@ -56,6 +59,8 @@ SubMap& GetSubstitutions() { "items_per_second,label,error_occurred,error_message"}, {"%csv_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns,,,,,"}, {"%csv_us_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",us,,,,,"}, + {"%csv_ms_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ms,,,,,"}, + {"%csv_s_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",s,,,,,"}, {"%csv_bytes_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns," + safe_dec_re + ",,,,"}, {"%csv_items_report", @@ -134,7 +139,7 @@ class TestReporter : public benchmark::BenchmarkReporter { TestReporter(std::vector reps) : reporters_(reps) {} - virtual bool ReportContext(const Context& context) { + virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE { bool last_ret = false; bool first = true; for (auto rep : reporters_) { @@ -148,10 +153,10 @@ class TestReporter : public benchmark::BenchmarkReporter { return last_ret; } - void ReportRuns(const std::vector& report) { + void ReportRuns(const std::vector& report) BENCHMARK_OVERRIDE { for (auto rep : reporters_) rep->ReportRuns(report); } - void Finalize() { + void Finalize() BENCHMARK_OVERRIDE { for (auto rep : reporters_) rep->Finalize(); } @@ -373,6 +378,12 @@ int SetSubstitutions( return 0; } +// Disable deprecated warnings temporarily because we need to reference +// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif void RunOutputTests(int argc, char* argv[]) { using internal::GetTestCaseList; benchmark::Initialize(&argc, argv); @@ -431,6 +442,10 @@ void RunOutputTests(int argc, char* argv[]) { internal::GetResultsChecker().CheckResults(csv.out_stream); } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + int SubstrCnt(const std::string& haystack, const std::string& pat) { if (pat.length() == 0) return 0; int count = 0; diff --git a/libcxx/utils/google-benchmark/test/perf_counters_gtest.cc b/libcxx/utils/google-benchmark/test/perf_counters_gtest.cc new file mode 100644 index 0000000000000..2a2868a715362 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/perf_counters_gtest.cc @@ -0,0 +1,145 @@ +#include + +#include "../src/perf_counters.h" +#include "gtest/gtest.h" + +#ifndef GTEST_SKIP +struct MsgHandler { + void operator=(std::ostream&){} +}; +#define GTEST_SKIP() return MsgHandler() = std::cout +#endif + +using benchmark::internal::PerfCounters; +using benchmark::internal::PerfCounterValues; + +namespace { +const char kGenericPerfEvent1[] = "CYCLES"; +const char kGenericPerfEvent2[] = "BRANCHES"; +const char kGenericPerfEvent3[] = "INSTRUCTIONS"; + +TEST(PerfCountersTest, Init) { + EXPECT_EQ(PerfCounters::Initialize(), PerfCounters::kSupported); +} + +TEST(PerfCountersTest, OneCounter) { + if (!PerfCounters::kSupported) { + GTEST_SKIP() << "Performance counters not supported.\n"; + } + EXPECT_TRUE(PerfCounters::Initialize()); + EXPECT_TRUE(PerfCounters::Create({kGenericPerfEvent1}).IsValid()); +} + +TEST(PerfCountersTest, NegativeTest) { + if (!PerfCounters::kSupported) { + EXPECT_FALSE(PerfCounters::Initialize()); + return; + } + EXPECT_TRUE(PerfCounters::Initialize()); + EXPECT_FALSE(PerfCounters::Create({}).IsValid()); + EXPECT_FALSE(PerfCounters::Create({""}).IsValid()); + EXPECT_FALSE(PerfCounters::Create({"not a counter name"}).IsValid()); + { + EXPECT_TRUE(PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2, + kGenericPerfEvent3}) + .IsValid()); + } + EXPECT_FALSE( + PerfCounters::Create({kGenericPerfEvent2, "", kGenericPerfEvent1}) + .IsValid()); + EXPECT_FALSE(PerfCounters::Create({kGenericPerfEvent3, "not a counter name", + kGenericPerfEvent1}) + .IsValid()); + { + EXPECT_TRUE(PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2, + kGenericPerfEvent3}) + .IsValid()); + } + EXPECT_FALSE( + PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2, + kGenericPerfEvent3, "MISPREDICTED_BRANCH_RETIRED"}) + .IsValid()); +} + +TEST(PerfCountersTest, Read1Counter) { + if (!PerfCounters::kSupported) { + GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + } + EXPECT_TRUE(PerfCounters::Initialize()); + auto counters = PerfCounters::Create({kGenericPerfEvent1}); + EXPECT_TRUE(counters.IsValid()); + PerfCounterValues values1(1); + EXPECT_TRUE(counters.Snapshot(&values1)); + EXPECT_GT(values1[0], 0); + PerfCounterValues values2(1); + EXPECT_TRUE(counters.Snapshot(&values2)); + EXPECT_GT(values2[0], 0); + EXPECT_GT(values2[0], values1[0]); +} + +TEST(PerfCountersTest, Read2Counters) { + if (!PerfCounters::kSupported) { + GTEST_SKIP() << "Test skipped because libpfm is not supported.\n"; + } + EXPECT_TRUE(PerfCounters::Initialize()); + auto counters = + PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent2}); + EXPECT_TRUE(counters.IsValid()); + PerfCounterValues values1(2); + EXPECT_TRUE(counters.Snapshot(&values1)); + EXPECT_GT(values1[0], 0); + EXPECT_GT(values1[1], 0); + PerfCounterValues values2(2); + EXPECT_TRUE(counters.Snapshot(&values2)); + EXPECT_GT(values2[0], 0); + EXPECT_GT(values2[1], 0); +} + +size_t do_work() { + size_t res = 0; + for (size_t i = 0; i < 100000000; ++i) res += i * i; + return res; +} + +void measure(size_t threadcount, PerfCounterValues* values1, + PerfCounterValues* values2) { + CHECK_NE(values1, nullptr); + CHECK_NE(values2, nullptr); + std::vector threads(threadcount); + auto work = [&]() { CHECK(do_work() > 1000); }; + + // We need to first set up the counters, then start the threads, so the + // threads would inherit the counters. But later, we need to first destroy the + // thread pool (so all the work finishes), then measure the counters. So the + // scopes overlap, and we need to explicitly control the scope of the + // threadpool. + auto counters = + PerfCounters::Create({kGenericPerfEvent1, kGenericPerfEvent3}); + for (auto& t : threads) t = std::thread(work); + counters.Snapshot(values1); + for (auto& t : threads) t.join(); + counters.Snapshot(values2); +} + +TEST(PerfCountersTest, MultiThreaded) { + if (!PerfCounters::kSupported) { + GTEST_SKIP() << "Test skipped because libpfm is not supported."; + } + EXPECT_TRUE(PerfCounters::Initialize()); + PerfCounterValues values1(2); + PerfCounterValues values2(2); + + measure(2, &values1, &values2); + std::vector D1{static_cast(values2[0] - values1[0]), + static_cast(values2[1] - values1[1])}; + + measure(4, &values1, &values2); + std::vector D2{static_cast(values2[0] - values1[0]), + static_cast(values2[1] - values1[1])}; + + // Some extra work will happen on the main thread - like joining the threads + // - so the ratio won't be quite 2.0, but very close. + EXPECT_GE(D2[0], 1.9 * D1[0]); + EXPECT_GE(D2[1], 1.9 * D1[1]); +} +} // namespace diff --git a/libcxx/utils/google-benchmark/test/perf_counters_test.cc b/libcxx/utils/google-benchmark/test/perf_counters_test.cc new file mode 100644 index 0000000000000..d6e0284d4d4b5 --- /dev/null +++ b/libcxx/utils/google-benchmark/test/perf_counters_test.cc @@ -0,0 +1,27 @@ +#undef NDEBUG + +#include "../src/perf_counters.h" + +#include "benchmark/benchmark.h" +#include "output_test.h" + +void BM_Simple(benchmark::State& state) { + for (auto _ : state) { + benchmark::DoNotOptimize(state.iterations()); + } +} +BENCHMARK(BM_Simple); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Simple\",$"}}); + +void CheckSimple(Results const& e) { + CHECK_COUNTER_VALUE(e, double, "CYCLES", GT, 0); + CHECK_COUNTER_VALUE(e, double, "BRANCHES", GT, 0.0); +} +CHECK_BENCHMARK_RESULTS("BM_Simple", &CheckSimple); + +int main(int argc, char* argv[]) { + if (!benchmark::internal::PerfCounters::kSupported) { + return 0; + } + RunOutputTests(argc, argv); +} diff --git a/libcxx/utils/google-benchmark/test/register_benchmark_test.cc b/libcxx/utils/google-benchmark/test/register_benchmark_test.cc index 3ac5b21fb348b..c027eabacae07 100644 --- a/libcxx/utils/google-benchmark/test/register_benchmark_test.cc +++ b/libcxx/utils/google-benchmark/test/register_benchmark_test.cc @@ -10,7 +10,7 @@ namespace { class TestReporter : public benchmark::ConsoleReporter { public: - virtual void ReportRuns(const std::vector& report) { + virtual void ReportRuns(const std::vector& report) BENCHMARK_OVERRIDE { all_runs_.insert(all_runs_.end(), begin(report), end(report)); ConsoleReporter::ReportRuns(report); } diff --git a/libcxx/utils/google-benchmark/test/repetitions_test.cc b/libcxx/utils/google-benchmark/test/repetitions_test.cc new file mode 100644 index 0000000000000..f93de502a35ab --- /dev/null +++ b/libcxx/utils/google-benchmark/test/repetitions_test.cc @@ -0,0 +1,208 @@ + +#include "benchmark/benchmark.h" +#include "output_test.h" + +// ========================================================================= // +// ------------------------ Testing Basic Output --------------------------- // +// ========================================================================= // + +void BM_ExplicitRepetitions(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_ExplicitRepetitions)->Repetitions(2); + +ADD_CASES(TC_ConsoleOut, + {{"^BM_ExplicitRepetitions/repeats:2 %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_ExplicitRepetitions/repeats:2 %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_ExplicitRepetitions/repeats:2_mean %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_ExplicitRepetitions/repeats:2_median %console_report$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_ExplicitRepetitions/repeats:2_stddev %console_report$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_ExplicitRepetitions/repeats:2\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ExplicitRepetitions/repeats:2\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_ExplicitRepetitions/repeats:2\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ExplicitRepetitions/repeats:2\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_ExplicitRepetitions/repeats:2_mean\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ExplicitRepetitions/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_ExplicitRepetitions/repeats:2_median\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ExplicitRepetitions/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_ExplicitRepetitions/repeats:2_stddev\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ExplicitRepetitions/repeats:2\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ExplicitRepetitions/repeats:2\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ExplicitRepetitions/repeats:2\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_ExplicitRepetitions/repeats:2_mean\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_ExplicitRepetitions/repeats:2_median\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_ExplicitRepetitions/repeats:2_stddev\",%csv_report$"}}); + +// ========================================================================= // +// ------------------------ Testing Basic Output --------------------------- // +// ========================================================================= // + +void BM_ImplicitRepetitions(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_ImplicitRepetitions); + +ADD_CASES(TC_ConsoleOut, {{"^BM_ImplicitRepetitions %console_report$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_ImplicitRepetitions %console_report$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_ImplicitRepetitions %console_report$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_ImplicitRepetitions_mean %console_report$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_ImplicitRepetitions_median %console_report$"}}); +ADD_CASES(TC_ConsoleOut, {{"^BM_ImplicitRepetitions_stddev %console_report$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_ImplicitRepetitions\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ImplicitRepetitions\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_ImplicitRepetitions\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ImplicitRepetitions\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_ImplicitRepetitions\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ImplicitRepetitions\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_ImplicitRepetitions_mean\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ImplicitRepetitions\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_ImplicitRepetitions_median\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ImplicitRepetitions\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_ImplicitRepetitions_stddev\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_ImplicitRepetitions\",$", MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ImplicitRepetitions\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ImplicitRepetitions\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ImplicitRepetitions_mean\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ImplicitRepetitions_median\",%csv_report$"}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_ImplicitRepetitions_stddev\",%csv_report$"}}); + +// ========================================================================= // +// --------------------------- TEST CASES END ------------------------------ // +// ========================================================================= // + +int main(int argc, char* argv[]) { RunOutputTests(argc, argv); } diff --git a/libcxx/utils/google-benchmark/test/reporter_output_test.cc b/libcxx/utils/google-benchmark/test/reporter_output_test.cc index ec6d51b35917c..989eb48ecc81c 100644 --- a/libcxx/utils/google-benchmark/test/reporter_output_test.cc +++ b/libcxx/utils/google-benchmark/test/reporter_output_test.cc @@ -15,7 +15,7 @@ ADD_CASES(TC_ConsoleOut, {{"^[-]+$", MR_Next}, static int AddContextCases() { AddCases(TC_ConsoleErr, { - {"%int[-/]%int[-/]%int %int:%int:%int$", MR_Default}, + {"^%int-%int-%intT%int:%int:%int[-+]%int:%int$", MR_Default}, {"Running .*/reporter_output_test(\\.exe)?$", MR_Next}, {"Run on \\(%int X %float MHz CPU s?\\)", MR_Next}, }); @@ -28,8 +28,7 @@ static int AddContextCases() { MR_Next}, {"\"num_cpus\": %int,$", MR_Next}, {"\"mhz_per_cpu\": %float,$", MR_Next}, - {"\"cpu_scaling_enabled\": ", MR_Next}, - {"\"caches\": \\[$", MR_Next}}); + {"\"caches\": \\[$", MR_Default}}); auto const& Info = benchmark::CPUInfo::Get(); auto const& Caches = Info.caches; if (!Caches.empty()) { @@ -38,9 +37,9 @@ static int AddContextCases() { for (size_t I = 0; I < Caches.size(); ++I) { std::string num_caches_str = Caches[I].num_sharing != 0 ? " \\(x%int\\)$" : "$"; - AddCases( - TC_ConsoleErr, - {{"L%int (Data|Instruction|Unified) %intK" + num_caches_str, MR_Next}}); + AddCases(TC_ConsoleErr, + {{"L%int (Data|Instruction|Unified) %int KiB" + num_caches_str, + MR_Next}}); AddCases(TC_JSONOut, {{"\\{$", MR_Next}, {"\"type\": \"", MR_Next}, {"\"level\": %int,$", MR_Next}, @@ -72,8 +71,13 @@ BENCHMARK(BM_basic); ADD_CASES(TC_ConsoleOut, {{"^BM_basic %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_basic\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_basic\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -87,6 +91,8 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_basic\",%csv_report$"}}); void BM_bytes_per_second(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } state.SetBytesProcessed(1); } @@ -95,8 +101,13 @@ BENCHMARK(BM_bytes_per_second); ADD_CASES(TC_ConsoleOut, {{"^BM_bytes_per_second %console_report " "bytes_per_second=%float[kM]{0,1}/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_bytes_per_second\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_bytes_per_second\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -111,6 +122,8 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_bytes_per_second\",%csv_bytes_report$"}}); void BM_items_per_second(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } state.SetItemsProcessed(1); } @@ -119,8 +132,13 @@ BENCHMARK(BM_items_per_second); ADD_CASES(TC_ConsoleOut, {{"^BM_items_per_second %console_report " "items_per_second=%float[kM]{0,1}/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_items_per_second\",$"}, + {"\"family_index\": 2,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_items_per_second\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -142,8 +160,13 @@ BENCHMARK(BM_label); ADD_CASES(TC_ConsoleOut, {{"^BM_label %console_report some label$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_label\",$"}, + {"\"family_index\": 3,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_label\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -153,6 +176,101 @@ ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_label\",$"}, ADD_CASES(TC_CSVOut, {{"^\"BM_label\",%csv_label_report_begin\"some " "label\"%csv_label_report_end$"}}); +// ========================================================================= // +// ------------------------ Testing Time Label Output ---------------------- // +// ========================================================================= // + +void BM_time_label_nanosecond(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_time_label_nanosecond)->Unit(benchmark::kNanosecond); + +ADD_CASES(TC_ConsoleOut, {{"^BM_time_label_nanosecond %console_report$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_time_label_nanosecond\",$"}, + {"\"family_index\": 4,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_time_label_nanosecond\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_time_label_nanosecond\",%csv_report$"}}); + +void BM_time_label_microsecond(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_time_label_microsecond)->Unit(benchmark::kMicrosecond); + +ADD_CASES(TC_ConsoleOut, {{"^BM_time_label_microsecond %console_us_report$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_time_label_microsecond\",$"}, + {"\"family_index\": 5,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_time_label_microsecond\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"us\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_time_label_microsecond\",%csv_us_report$"}}); + +void BM_time_label_millisecond(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_time_label_millisecond)->Unit(benchmark::kMillisecond); + +ADD_CASES(TC_ConsoleOut, {{"^BM_time_label_millisecond %console_ms_report$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_time_label_millisecond\",$"}, + {"\"family_index\": 6,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_time_label_millisecond\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ms\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_time_label_millisecond\",%csv_ms_report$"}}); + +void BM_time_label_second(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_time_label_second)->Unit(benchmark::kSecond); + +ADD_CASES(TC_ConsoleOut, {{"^BM_time_label_second %console_s_report$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_time_label_second\",$"}, + {"\"family_index\": 7,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_time_label_second\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"s\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_time_label_second\",%csv_s_report$"}}); + // ========================================================================= // // ------------------------ Testing Error Output --------------------------- // // ========================================================================= // @@ -165,8 +283,13 @@ void BM_error(benchmark::State& state) { BENCHMARK(BM_error); ADD_CASES(TC_ConsoleOut, {{"^BM_error[ ]+ERROR OCCURRED: 'message'$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_error\",$"}, + {"\"family_index\": 8,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_error\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"error_occurred\": true,$", MR_Next}, {"\"error_message\": \"message\",$", MR_Next}}); @@ -184,8 +307,13 @@ void BM_no_arg_name(benchmark::State& state) { BENCHMARK(BM_no_arg_name)->Arg(3); ADD_CASES(TC_ConsoleOut, {{"^BM_no_arg_name/3 %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_no_arg_name/3\",$"}, + {"\"family_index\": 9,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_no_arg_name/3\",$", MR_Next}, - {"\"run_type\": \"iteration\",$", MR_Next}}); + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_no_arg_name/3\",%csv_report$"}}); // ========================================================================= // @@ -199,8 +327,13 @@ void BM_arg_name(benchmark::State& state) { BENCHMARK(BM_arg_name)->ArgName("first")->Arg(3); ADD_CASES(TC_ConsoleOut, {{"^BM_arg_name/first:3 %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_arg_name/first:3\",$"}, + {"\"family_index\": 10,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_arg_name/first:3\",$", MR_Next}, - {"\"run_type\": \"iteration\",$", MR_Next}}); + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_arg_name/first:3\",%csv_report$"}}); // ========================================================================= // @@ -216,10 +349,41 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_arg_names/first:2/5/third:4 %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_arg_names/first:2/5/third:4\",$"}, + {"\"family_index\": 11,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_arg_names/first:2/5/third:4\",$", MR_Next}, - {"\"run_type\": \"iteration\",$", MR_Next}}); + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_arg_names/first:2/5/third:4\",%csv_report$"}}); +// ========================================================================= // +// ------------------------ Testing Name Output ---------------------------- // +// ========================================================================= // + +void BM_name(benchmark::State& state) { + for (auto _ : state) { + } +} +BENCHMARK(BM_name)->Name("BM_custom_name"); + +ADD_CASES(TC_ConsoleOut, {{"^BM_custom_name %console_report$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_custom_name\",$"}, + {"\"family_index\": 12,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_custom_name\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\"$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_custom_name\",%csv_report$"}}); + // ========================================================================= // // ------------------------ Testing Big Args Output ------------------------ // // ========================================================================= // @@ -238,6 +402,8 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_BigArgs/1073741824 %console_report$"}, void BM_Complexity_O1(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } state.SetComplexityN(state.range(0)); } @@ -265,24 +431,46 @@ ADD_CASES(TC_ConsoleOut, {"^BM_Repeat/repeats:2_median %console_time_only_report [ ]*2$"}, {"^BM_Repeat/repeats:2_stddev %console_time_only_report [ ]*2$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:2\",$"}, + {"\"family_index\": 15,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:2\"", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2\",$"}, + {"\"family_index\": 15,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2_mean\",$"}, + {"\"family_index\": 15,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2_median\",$"}, + {"\"family_index\": 15,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:2_stddev\",$"}, + {"\"family_index\": 15,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:2\",%csv_report$"}, @@ -300,27 +488,54 @@ ADD_CASES(TC_ConsoleOut, {"^BM_Repeat/repeats:3_median %console_time_only_report [ ]*3$"}, {"^BM_Repeat/repeats:3_stddev %console_time_only_report [ ]*3$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:3\",$"}, + {"\"family_index\": 16,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3\",$"}, + {"\"family_index\": 16,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3\",$"}, + {"\"family_index\": 16,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3_mean\",$"}, + {"\"family_index\": 16,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3_median\",$"}, + {"\"family_index\": 16,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:3_stddev\",$"}, + {"\"family_index\": 16,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:3\",%csv_report$"}, @@ -340,30 +555,62 @@ ADD_CASES(TC_ConsoleOut, {"^BM_Repeat/repeats:4_median %console_time_only_report [ ]*4$"}, {"^BM_Repeat/repeats:4_stddev %console_time_only_report [ ]*4$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"repetition_index\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"repetition_index\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4_mean\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 4,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4_median\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 4,$", MR_Next}, {"\"name\": \"BM_Repeat/repeats:4_stddev\",$"}, + {"\"family_index\": 17,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 4,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 4,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:4\",%csv_report$"}, @@ -383,8 +630,13 @@ void BM_RepeatOnce(benchmark::State& state) { BENCHMARK(BM_RepeatOnce)->Repetitions(1)->ReportAggregatesOnly(); ADD_CASES(TC_ConsoleOut, {{"^BM_RepeatOnce/repeats:1 %console_report$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_RepeatOnce/repeats:1\",$"}, + {"\"family_index\": 18,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_RepeatOnce/repeats:1\",$", MR_Next}, - {"\"run_type\": \"iteration\",$", MR_Next}}); + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"^\"BM_RepeatOnce/repeats:1\",%csv_report$"}}); // Test that non-aggregate data is not reported @@ -402,18 +654,30 @@ ADD_CASES( ADD_CASES(TC_JSONOut, {{".*BM_SummaryRepeat/repeats:3 ", MR_Not}, {"\"name\": \"BM_SummaryRepeat/repeats:3_mean\",$"}, + {"\"family_index\": 19,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"name\": \"BM_SummaryRepeat/repeats:3_median\",$"}, + {"\"family_index\": 19,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"name\": \"BM_SummaryRepeat/repeats:3_stddev\",$"}, + {"\"family_index\": 19,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}}); ADD_CASES(TC_CSVOut, {{".*BM_SummaryRepeat/repeats:3 ", MR_Not}, @@ -438,18 +702,30 @@ ADD_CASES( ADD_CASES(TC_JSONOut, {{".*BM_SummaryDisplay/repeats:2 ", MR_Not}, {"\"name\": \"BM_SummaryDisplay/repeats:2_mean\",$"}, + {"\"family_index\": 20,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"name\": \"BM_SummaryDisplay/repeats:2_median\",$"}, + {"\"family_index\": 20,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"name\": \"BM_SummaryDisplay/repeats:2_stddev\",$"}, + {"\"family_index\": 20,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}}); ADD_CASES(TC_CSVOut, @@ -478,20 +754,32 @@ ADD_CASES( ADD_CASES(TC_JSONOut, {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not}, {"\"name\": \"BM_RepeatTimeUnit/repeats:3_mean\",$"}, + {"\"family_index\": 21,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"time_unit\": \"us\",?$"}, {"\"name\": \"BM_RepeatTimeUnit/repeats:3_median\",$"}, + {"\"family_index\": 21,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"time_unit\": \"us\",?$"}, {"\"name\": \"BM_RepeatTimeUnit/repeats:3_stddev\",$"}, + {"\"family_index\": 21,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"time_unit\": \"us\",?$"}}); @@ -540,48 +828,79 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_UserStats/iterations:5/repeats:3/manual_time [ " ADD_CASES( TC_JSONOut, {{"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": 5,$", MR_Next}, {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": 5,$", MR_Next}, {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"repetition_index\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": 5,$", MR_Next}, {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_mean\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_median\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}, {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_stddev\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_\",$"}, + {"\"family_index\": 22,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 3,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"\",$", MR_Next}, {"\"iterations\": 3,$", MR_Next}, {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}}); @@ -597,6 +916,39 @@ ADD_CASES( "manual_time_stddev\",%csv_report$"}, {"^\"BM_UserStats/iterations:5/repeats:3/manual_time_\",%csv_report$"}}); +// ========================================================================= // +// ------------------------- Testing StrEscape JSON ------------------------ // +// ========================================================================= // +#if 0 // enable when csv testing code correctly handles multi-line fields +void BM_JSON_Format(benchmark::State& state) { + state.SkipWithError("val\b\f\n\r\t\\\"with\"es,capes"); + for (auto _ : state) { + } +} +BENCHMARK(BM_JSON_Format); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_JSON_Format\",$"}, + {"\"family_index\": 23,$", MR_Next}, +{"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_JSON_Format\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"error_occurred\": true,$", MR_Next}, + {R"("error_message": "val\\b\\f\\n\\r\\t\\\\\\"with\\"es,capes",$)", MR_Next}}); +#endif +// ========================================================================= // +// -------------------------- Testing CsvEscape ---------------------------- // +// ========================================================================= // + +void BM_CSV_Format(benchmark::State& state) { + state.SkipWithError("\"freedom\""); + for (auto _ : state) { + } +} +BENCHMARK(BM_CSV_Format); +ADD_CASES(TC_CSVOut, {{"^\"BM_CSV_Format\",,,,,,,,true,\"\"\"freedom\"\"\"$"}}); + // ========================================================================= // // --------------------------- TEST CASES END ------------------------------ // // ========================================================================= // diff --git a/libcxx/utils/google-benchmark/test/skip_with_error_test.cc b/libcxx/utils/google-benchmark/test/skip_with_error_test.cc index 06579772ff773..827966e9dfe37 100644 --- a/libcxx/utils/google-benchmark/test/skip_with_error_test.cc +++ b/libcxx/utils/google-benchmark/test/skip_with_error_test.cc @@ -10,11 +10,11 @@ namespace { class TestReporter : public benchmark::ConsoleReporter { public: - virtual bool ReportContext(const Context& context) { + virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE { return ConsoleReporter::ReportContext(context); }; - virtual void ReportRuns(const std::vector& report) { + virtual void ReportRuns(const std::vector& report) BENCHMARK_OVERRIDE { all_runs_.insert(all_runs_.end(), begin(report), end(report)); ConsoleReporter::ReportRuns(report); } @@ -61,6 +61,12 @@ int AddCases(const char* base_name, std::initializer_list const& v) { } // end namespace +void BM_error_no_running(benchmark::State& state) { + state.SkipWithError("error message"); +} +BENCHMARK(BM_error_no_running); +ADD_CASES("BM_error_no_running", {{"", true, "error message"}}); + void BM_error_before_running(benchmark::State& state) { state.SkipWithError("error message"); while (state.KeepRunning()) { diff --git a/libcxx/utils/google-benchmark/test/state_assembly_test.cc b/libcxx/utils/google-benchmark/test/state_assembly_test.cc index abe9a4ddb56dd..7ddbb3b2a92c8 100644 --- a/libcxx/utils/google-benchmark/test/state_assembly_test.cc +++ b/libcxx/utils/google-benchmark/test/state_assembly_test.cc @@ -25,7 +25,7 @@ extern "C" int test_for_auto_loop() { for (auto _ : S) { // CHECK: .L[[LOOP_HEAD:[a-zA-Z0-9_]+]]: // CHECK-GNU-NEXT: subq $1, %rbx - // CHECK-CLANG-NEXT: {{(addq \$1,|incq)}} %rax + // CHECK-CLANG-NEXT: {{(addq \$1, %rax|incq %rax|addq \$-1, %rbx)}} // CHECK-NEXT: jne .L[[LOOP_HEAD]] benchmark::DoNotOptimize(x); } diff --git a/libcxx/utils/google-benchmark/test/statistics_gtest.cc b/libcxx/utils/google-benchmark/test/statistics_gtest.cc index 99e314920c55c..3ddc72dd7ac62 100644 --- a/libcxx/utils/google-benchmark/test/statistics_gtest.cc +++ b/libcxx/utils/google-benchmark/test/statistics_gtest.cc @@ -21,8 +21,8 @@ TEST(StatisticsTest, Median) { TEST(StatisticsTest, StdDev) { EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({101, 101, 101, 101}), 0.0); EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({1, 2, 3}), 1.0); - EXPECT_FLOAT_EQ(benchmark::StatisticsStdDev({1.5, 2.4, 3.3, 4.2, 5.1}), - 1.42302495); + EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({2.5, 2.4, 3.3, 4.2, 5.1}), + 1.151086443322134); } } // end namespace diff --git a/libcxx/utils/google-benchmark/test/string_util_gtest.cc b/libcxx/utils/google-benchmark/test/string_util_gtest.cc index 2c5d073f613b7..c7061b409e91c 100644 --- a/libcxx/utils/google-benchmark/test/string_util_gtest.cc +++ b/libcxx/utils/google-benchmark/test/string_util_gtest.cc @@ -3,6 +3,7 @@ //===---------------------------------------------------------------------===// #include "../src/string_util.h" +#include "../src/internal_macros.h" #include "gtest/gtest.h" namespace { @@ -60,9 +61,11 @@ TEST(StringUtilTest, stoul) { EXPECT_EQ(0xBEEFul, benchmark::stoul("BEEF", &pos, 16)); EXPECT_EQ(4ul, pos); } +#ifndef BENCHMARK_HAS_NO_EXCEPTIONS { ASSERT_THROW(benchmark::stoul("this is a test"), std::invalid_argument); } +#endif } TEST(StringUtilTest, stoi) { @@ -106,9 +109,11 @@ TEST(StringUtilTest, stoi) { EXPECT_EQ(0xBEEF, benchmark::stoi("BEEF", &pos, 16)); EXPECT_EQ(4ul, pos); } +#ifndef BENCHMARK_HAS_NO_EXCEPTIONS { ASSERT_THROW(benchmark::stoi("this is a test"), std::invalid_argument); } +#endif } TEST(StringUtilTest, stod) { @@ -138,9 +143,19 @@ TEST(StringUtilTest, stod) { EXPECT_EQ(-1.25e+9, benchmark::stod("-1.25e+9", &pos)); EXPECT_EQ(8ul, pos); } +#ifndef BENCHMARK_HAS_NO_EXCEPTIONS { ASSERT_THROW(benchmark::stod("this is a test"), std::invalid_argument); } +#endif +} + +TEST(StringUtilTest, StrSplit) { + EXPECT_EQ(benchmark::StrSplit("", ','), std::vector{}); + EXPECT_EQ(benchmark::StrSplit("hello", ','), + std::vector({"hello"})); + EXPECT_EQ(benchmark::StrSplit("hello,there,is,more", ','), + std::vector({"hello", "there", "is", "more"})); } } // end namespace diff --git a/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc b/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc index 030e98916c3d3..421f27b5cb8b0 100644 --- a/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc +++ b/libcxx/utils/google-benchmark/test/user_counters_tabular_test.cc @@ -7,19 +7,23 @@ // @todo: this checks the full output at once; the rule for // CounterSet1 was failing because it was not matching "^[-]+$". // @todo: check that the counters are vertically aligned. -ADD_CASES( - TC_ConsoleOut, - { - // keeping these lines long improves readability, so: - // clang-format off +ADD_CASES(TC_ConsoleOut, + { + // keeping these lines long improves readability, so: + // clang-format off {"^[-]+$", MR_Next}, {"^Benchmark %s Time %s CPU %s Iterations %s Bar %s Bat %s Baz %s Foo %s Frob %s Lob$", MR_Next}, {"^[-]+$", MR_Next}, - {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, - {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, - {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, - {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, - {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:1 %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:1 %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:1_mean %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:1_median %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:1_stddev %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:2 %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:2 %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:2_mean %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:2_median %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, + {"^BM_Counters_Tabular/repeats:2/threads:2_stddev %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next}, {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next}, {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next}, @@ -46,8 +50,8 @@ ADD_CASES( {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$"}, - // clang-format on - }); + // clang-format on + }); ADD_CASES(TC_CSVOut, {{"%csv_header," "\"Bar\",\"Bat\",\"Baz\",\"Foo\",\"Frob\",\"Lob\""}}); @@ -68,11 +72,17 @@ void BM_Counters_Tabular(benchmark::State& state) { {"Lob", {32, bm::Counter::kAvgThreads}}, }); } -BENCHMARK(BM_Counters_Tabular)->ThreadRange(1, 16); +BENCHMARK(BM_Counters_Tabular)->ThreadRange(1, 2)->Repetitions(2); ADD_CASES(TC_JSONOut, - {{"\"name\": \"BM_Counters_Tabular/threads:%int\",$"}, - {"\"run_name\": \"BM_Counters_Tabular/threads:%int\",$", MR_Next}, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$", + MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -84,8 +94,205 @@ ADD_CASES(TC_JSONOut, {"\"Frob\": %float,$", MR_Next}, {"\"Lob\": %float$", MR_Next}, {"}", MR_Next}}); -ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Tabular/threads:%int\",%csv_report," - "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:1_mean\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"mean\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:1_median\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:1_stddev\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:1\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); + +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:2\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 1,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:2\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 2,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:2\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 1,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:2\",$", + MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 2,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:2_median\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 1,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:2\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 2,$", MR_Next}, + {"\"aggregate_name\": \"median\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_Tabular/repeats:2/threads:2_stddev\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 1,$", MR_Next}, + {"\"run_name\": \"BM_Counters_Tabular/repeats:2/threads:2\",$", + MR_Next}, + {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 2,$", MR_Next}, + {"\"aggregate_name\": \"stddev\",$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"Bar\": %float,$", MR_Next}, + {"\"Bat\": %float,$", MR_Next}, + {"\"Baz\": %float,$", MR_Next}, + {"\"Foo\": %float,$", MR_Next}, + {"\"Frob\": %float,$", MR_Next}, + {"\"Lob\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:1\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:1\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:1_mean\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:1_median\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:1_stddev\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:2\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:2\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:2_mean\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:2_median\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_Tabular/repeats:2/threads:2_stddev\",%csv_report," + "%float,%float,%float,%float,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() void CheckTabular(Results const& e) { @@ -96,7 +303,10 @@ void CheckTabular(Results const& e) { CHECK_COUNTER_VALUE(e, int, "Frob", EQ, 16); CHECK_COUNTER_VALUE(e, int, "Lob", EQ, 32); } -CHECK_BENCHMARK_RESULTS("BM_Counters_Tabular/threads:%int", &CheckTabular); +CHECK_BENCHMARK_RESULTS("BM_Counters_Tabular/repeats:2/threads:1$", + &CheckTabular); +CHECK_BENCHMARK_RESULTS("BM_Counters_Tabular/repeats:2/threads:2$", + &CheckTabular); // ========================================================================= // // -------------------- Tabular+Rate Counters Output ----------------------- // @@ -104,6 +314,8 @@ CHECK_BENCHMARK_RESULTS("BM_Counters_Tabular/threads:%int", &CheckTabular); void BM_CounterRates_Tabular(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } namespace bm = benchmark; state.counters.insert({ @@ -118,9 +330,14 @@ void BM_CounterRates_Tabular(benchmark::State& state) { BENCHMARK(BM_CounterRates_Tabular)->ThreadRange(1, 16); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterRates_Tabular/threads:%int\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_CounterRates_Tabular/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -166,8 +383,13 @@ void BM_CounterSet0_Tabular(benchmark::State& state) { BENCHMARK(BM_CounterSet0_Tabular)->ThreadRange(1, 16); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterSet0_Tabular/threads:%int\",$"}, + {"\"family_index\": 2,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_CounterSet0_Tabular/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -201,8 +423,13 @@ void BM_CounterSet1_Tabular(benchmark::State& state) { BENCHMARK(BM_CounterSet1_Tabular)->ThreadRange(1, 16); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterSet1_Tabular/threads:%int\",$"}, + {"\"family_index\": 3,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_CounterSet1_Tabular/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -240,8 +467,13 @@ void BM_CounterSet2_Tabular(benchmark::State& state) { BENCHMARK(BM_CounterSet2_Tabular)->ThreadRange(1, 16); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_CounterSet2_Tabular/threads:%int\",$"}, + {"\"family_index\": 4,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_CounterSet2_Tabular/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, diff --git a/libcxx/utils/google-benchmark/test/user_counters_test.cc b/libcxx/utils/google-benchmark/test/user_counters_test.cc index bb0d6b4c5a91c..377bb32ca948c 100644 --- a/libcxx/utils/google-benchmark/test/user_counters_test.cc +++ b/libcxx/utils/google-benchmark/test/user_counters_test.cc @@ -32,8 +32,13 @@ BENCHMARK(BM_Counters_Simple); ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Simple %console_report bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Simple\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Simple\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -61,6 +66,8 @@ int num_calls1 = 0; } void BM_Counters_WithBytesAndItemsPSec(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } state.counters["foo"] = 1; state.counters["bar"] = ++num_calls1; @@ -73,8 +80,13 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_WithBytesAndItemsPSec %console_report " "foo=%hrfloat items_per_second=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_WithBytesAndItemsPSec\",$"}, + {"\"family_index\": 1,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_WithBytesAndItemsPSec\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -105,6 +117,8 @@ CHECK_BENCHMARK_RESULTS("BM_Counters_WithBytesAndItemsPSec", void BM_Counters_Rate(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } namespace bm = benchmark; state.counters["foo"] = bm::Counter{1, bm::Counter::kIsRate}; @@ -115,8 +129,13 @@ ADD_CASES( TC_ConsoleOut, {{"^BM_Counters_Rate %console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Rate\",$"}, + {"\"family_index\": 2,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Rate\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -135,6 +154,93 @@ void CheckRate(Results const& e) { } CHECK_BENCHMARK_RESULTS("BM_Counters_Rate", &CheckRate); +// ========================================================================= // +// ----------------------- Inverted Counters Output ------------------------ // +// ========================================================================= // + +void BM_Invert(benchmark::State& state) { + for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); + } + namespace bm = benchmark; + state.counters["foo"] = bm::Counter{0.0001, bm::Counter::kInvert}; + state.counters["bar"] = bm::Counter{10000, bm::Counter::kInvert}; +} +BENCHMARK(BM_Invert); +ADD_CASES(TC_ConsoleOut, + {{"^BM_Invert %console_report bar=%hrfloatu foo=%hrfloatk$"}}); +ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Invert\",$"}, + {"\"family_index\": 3,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Invert\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, {{"^\"BM_Invert\",%csv_report,%float,%float$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckInvert(Results const& e) { + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 10000, 0.0001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 0.0001, 0.0001); +} +CHECK_BENCHMARK_RESULTS("BM_Invert", &CheckInvert); + +// ========================================================================= // +// ------------------------- InvertedRate Counters Output +// -------------------------- // +// ========================================================================= // + +void BM_Counters_InvertedRate(benchmark::State& state) { + for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); + } + namespace bm = benchmark; + state.counters["foo"] = + bm::Counter{1, bm::Counter::kIsRate | bm::Counter::kInvert}; + state.counters["bar"] = + bm::Counter{8192, bm::Counter::kIsRate | bm::Counter::kInvert}; +} +BENCHMARK(BM_Counters_InvertedRate); +ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_InvertedRate %console_report " + "bar=%hrfloats foo=%hrfloats$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_InvertedRate\",$"}, + {"\"family_index\": 4,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, + {"\"run_name\": \"BM_Counters_InvertedRate\",$", MR_Next}, + {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, + {"\"iterations\": %int,$", MR_Next}, + {"\"real_time\": %float,$", MR_Next}, + {"\"cpu_time\": %float,$", MR_Next}, + {"\"time_unit\": \"ns\",$", MR_Next}, + {"\"bar\": %float,$", MR_Next}, + {"\"foo\": %float$", MR_Next}, + {"}", MR_Next}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_InvertedRate\",%csv_report,%float,%float$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckInvertedRate(Results const& e) { + double t = e.DurationCPUTime(); // this (and not real time) is the time used + // check that the values are within 0.1% of the expected values + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, t / 8192.0, 0.001); +} +CHECK_BENCHMARK_RESULTS("BM_Counters_InvertedRate", &CheckInvertedRate); + // ========================================================================= // // ------------------------- Thread Counters Output ------------------------ // // ========================================================================= // @@ -150,8 +256,13 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Threads/threads:%int %console_report " "bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Threads/threads:%int\",$"}, + {"\"family_index\": 5,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Threads/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -186,8 +297,13 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgThreads/threads:%int " "%console_report bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgThreads/threads:%int\",$"}, + {"\"family_index\": 6,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_AvgThreads/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -213,6 +329,8 @@ CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreads/threads:%int", void BM_Counters_AvgThreadsRate(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } namespace bm = benchmark; state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgThreadsRate}; @@ -223,9 +341,14 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgThreadsRate/threads:%int " "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$"}, + {"\"family_index\": 7,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -260,8 +383,13 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_IterationInvariant %console_report " "bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_IterationInvariant\",$"}, + {"\"family_index\": 8,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_IterationInvariant\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -288,6 +416,8 @@ CHECK_BENCHMARK_RESULTS("BM_Counters_IterationInvariant", void BM_Counters_kIsIterationInvariantRate(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } namespace bm = benchmark; state.counters["foo"] = @@ -300,9 +430,14 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kIsIterationInvariantRate " "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_kIsIterationInvariantRate\",$"}, + {"\"family_index\": 9,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_kIsIterationInvariantRate\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -340,8 +475,13 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgIterations %console_report " "bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgIterations\",$"}, + {"\"family_index\": 10,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_AvgIterations\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -367,6 +507,8 @@ CHECK_BENCHMARK_RESULTS("BM_Counters_AvgIterations", &CheckAvgIterations); void BM_Counters_kAvgIterationsRate(benchmark::State& state) { for (auto _ : state) { + // This test requires a non-zero CPU time to avoid divide-by-zero + benchmark::DoNotOptimize(state.iterations()); } namespace bm = benchmark; state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgIterationsRate}; @@ -378,8 +520,13 @@ ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kAvgIterationsRate " "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_kAvgIterationsRate\",$"}, + {"\"family_index\": 11,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_kAvgIterationsRate\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 1,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, diff --git a/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc b/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc index fa0ef97204704..bbe194264ed45 100644 --- a/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc +++ b/libcxx/utils/google-benchmark/test/user_counters_thousands_test.cc @@ -51,8 +51,13 @@ ADD_CASES( }); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Thousands/repeats:2\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 0,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -65,8 +70,13 @@ ADD_CASES(TC_JSONOut, {"}", MR_Next}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Thousands/repeats:2\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, {"\"run_type\": \"iteration\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"repetition_index\": 1,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, {"\"cpu_time\": %float,$", MR_Next}, @@ -79,8 +89,12 @@ ADD_CASES(TC_JSONOut, {"}", MR_Next}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Thousands/repeats:2_mean\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"mean\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, @@ -94,8 +108,12 @@ ADD_CASES(TC_JSONOut, {"}", MR_Next}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Thousands/repeats:2_median\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"median\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, @@ -109,8 +127,12 @@ ADD_CASES(TC_JSONOut, {"}", MR_Next}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Thousands/repeats:2_stddev\",$"}, + {"\"family_index\": 0,$", MR_Next}, + {"\"per_family_instance_index\": 0,$", MR_Next}, {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next}, {"\"run_type\": \"aggregate\",$", MR_Next}, + {"\"repetitions\": 2,$", MR_Next}, + {"\"threads\": 1,$", MR_Next}, {"\"aggregate_name\": \"stddev\",$", MR_Next}, {"\"iterations\": 2,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, diff --git a/libcxx/utils/google-benchmark/tools/BUILD.bazel b/libcxx/utils/google-benchmark/tools/BUILD.bazel new file mode 100644 index 0000000000000..5895883a2eb3c --- /dev/null +++ b/libcxx/utils/google-benchmark/tools/BUILD.bazel @@ -0,0 +1,19 @@ +load("@py_deps//:requirements.bzl", "requirement") + +py_library( + name = "gbench", + srcs = glob(["gbench/*.py"]), + deps = [ + requirement("numpy"), + requirement("scipy"), + ], +) + +py_binary( + name = "compare", + srcs = ["compare.py"], + python_version = "PY2", + deps = [ + ":gbench", + ], +) diff --git a/libcxx/utils/google-benchmark/tools/compare.py b/libcxx/utils/google-benchmark/tools/compare.py index 539ace6fb163b..01d2c89f50fbb 100755 --- a/libcxx/utils/google-benchmark/tools/compare.py +++ b/libcxx/utils/google-benchmark/tools/compare.py @@ -7,6 +7,7 @@ import argparse from argparse import ArgumentParser +import json import sys import gbench from gbench import util, report @@ -48,6 +49,20 @@ def create_parser(): "of repetitions. Do note that only the display is affected. " "Internally, all the actual runs are still used, e.g. for U test.") + parser.add_argument( + '--no-color', + dest='color', + default=True, + action="store_false", + help="Do not use colors in the terminal output" + ) + + parser.add_argument( + '-d', + '--dump_to_json', + dest='dump_to_json', + help="Additionally, dump benchmark comparison output to this file in JSON format.") + utest = parser.add_argument_group() utest.add_argument( '--no-utest', @@ -223,10 +238,10 @@ def main(): options_contender = ['--benchmark_filter=%s' % filter_contender] # Run the benchmarks and report the results - json1 = json1_orig = gbench.util.run_or_load_benchmark( - test_baseline, benchmark_options + options_baseline) - json2 = json2_orig = gbench.util.run_or_load_benchmark( - test_contender, benchmark_options + options_contender) + json1 = json1_orig = gbench.util.sort_benchmark_results(gbench.util.run_or_load_benchmark( + test_baseline, benchmark_options + options_baseline)) + json2 = json2_orig = gbench.util.sort_benchmark_results(gbench.util.run_or_load_benchmark( + test_contender, benchmark_options + options_contender)) # Now, filter the benchmarks so that the difference report can work if filter_baseline and filter_contender: @@ -236,14 +251,20 @@ def main(): json2 = gbench.report.filter_benchmark( json2_orig, filter_contender, replacement) - # Diff and output - output_lines = gbench.report.generate_difference_report( - json1, json2, args.display_aggregates_only, - args.utest, args.utest_alpha) + diff_report = gbench.report.get_difference_report( + json1, json2, args.utest) + output_lines = gbench.report.print_difference_report( + diff_report, + args.display_aggregates_only, + args.utest, args.utest_alpha, args.color) print(description) for ln in output_lines: print(ln) + # Optionally, diff and output to JSON + if args.dump_to_json is not None: + with open(args.dump_to_json, 'w') as f_json: + json.dump(diff_report, f_json) class TestParser(unittest.TestCase): def setUp(self): diff --git a/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json b/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json index d7ec6a9c8f61a..601e327aefb59 100644 --- a/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json +++ b/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run1.json @@ -85,7 +85,24 @@ "time_unit": "ns" }, { - "name": "BM_BadTimeUnit", + "name": "MyComplexityTest_BigO", + "run_name": "MyComplexityTest", + "run_type": "aggregate", + "aggregate_name": "BigO", + "cpu_coefficient": 4.2749856294592886e+00, + "real_coefficient": 6.4789275289789780e+00, + "big_o": "N", + "time_unit": "ns" + }, + { + "name": "MyComplexityTest_RMS", + "run_name": "MyComplexityTest", + "run_type": "aggregate", + "aggregate_name": "RMS", + "rms": 4.5097802512472874e-03 + }, + { + "name": "BM_NotBadTimeUnit", "iterations": 1000, "real_time": 0.4, "cpu_time": 0.5, diff --git a/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json b/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json index 59a5ffaca4d4d..3cbcf39b0c938 100644 --- a/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json +++ b/libcxx/utils/google-benchmark/tools/gbench/Inputs/test1_run2.json @@ -85,7 +85,24 @@ "time_unit": "ns" }, { - "name": "BM_BadTimeUnit", + "name": "MyComplexityTest_BigO", + "run_name": "MyComplexityTest", + "run_type": "aggregate", + "aggregate_name": "BigO", + "cpu_coefficient": 5.6215779594361486e+00, + "real_coefficient": 5.6288314793554610e+00, + "big_o": "N", + "time_unit": "ns" + }, + { + "name": "MyComplexityTest_RMS", + "run_name": "MyComplexityTest", + "run_type": "aggregate", + "aggregate_name": "RMS", + "rms": 3.3128901852342174e-03 + }, + { + "name": "BM_NotBadTimeUnit", "iterations": 1000, "real_time": 0.04, "cpu_time": 0.6, diff --git a/libcxx/utils/google-benchmark/tools/gbench/Inputs/test4_run.json b/libcxx/utils/google-benchmark/tools/gbench/Inputs/test4_run.json new file mode 100644 index 0000000000000..eaa005f3a9f47 --- /dev/null +++ b/libcxx/utils/google-benchmark/tools/gbench/Inputs/test4_run.json @@ -0,0 +1,96 @@ +{ + "benchmarks": [ + { + "name": "99 family 0 instance 0 repetition 0", + "run_type": "iteration", + "family_index": 0, + "per_family_instance_index": 0, + "repetition_index": 0 + }, + { + "name": "98 family 0 instance 0 repetition 1", + "run_type": "iteration", + "family_index": 0, + "per_family_instance_index": 0, + "repetition_index": 1 + }, + { + "name": "97 family 0 instance 0 aggregate", + "run_type": "aggregate", + "family_index": 0, + "per_family_instance_index": 0, + "aggregate_name": "9 aggregate" + }, + + + { + "name": "96 family 0 instance 1 repetition 0", + "run_type": "iteration", + "family_index": 0, + "per_family_instance_index": 1, + "repetition_index": 0 + }, + { + "name": "95 family 0 instance 1 repetition 1", + "run_type": "iteration", + "family_index": 0, + "per_family_instance_index": 1, + "repetition_index": 1 + }, + { + "name": "94 family 0 instance 1 aggregate", + "run_type": "aggregate", + "family_index": 0, + "per_family_instance_index": 1, + "aggregate_name": "9 aggregate" + }, + + + + + { + "name": "93 family 1 instance 0 repetition 0", + "run_type": "iteration", + "family_index": 1, + "per_family_instance_index": 0, + "repetition_index": 0 + }, + { + "name": "92 family 1 instance 0 repetition 1", + "run_type": "iteration", + "family_index": 1, + "per_family_instance_index": 0, + "repetition_index": 1 + }, + { + "name": "91 family 1 instance 0 aggregate", + "run_type": "aggregate", + "family_index": 1, + "per_family_instance_index": 0, + "aggregate_name": "9 aggregate" + }, + + + { + "name": "90 family 1 instance 1 repetition 0", + "run_type": "iteration", + "family_index": 1, + "per_family_instance_index": 1, + "repetition_index": 0 + }, + { + "name": "89 family 1 instance 1 repetition 1", + "run_type": "iteration", + "family_index": 1, + "per_family_instance_index": 1, + "repetition_index": 1 + }, + { + "name": "88 family 1 instance 1 aggregate", + "run_type": "aggregate", + "family_index": 1, + "per_family_instance_index": 1, + "aggregate_name": "9 aggregate" + } + ] +} diff --git a/libcxx/utils/google-benchmark/tools/gbench/report.py b/libcxx/utils/google-benchmark/tools/gbench/report.py index 5085b9319475b..6bea82f6bf7b4 100644 --- a/libcxx/utils/google-benchmark/tools/gbench/report.py +++ b/libcxx/utils/google-benchmark/tools/gbench/report.py @@ -1,9 +1,11 @@ -import unittest """report.py - Utilities for reporting statistics about benchmark results """ + +import unittest import os import re import copy +import random from scipy.stats import mannwhitneyu @@ -114,6 +116,10 @@ def intersect(list1, list2): return [x for x in list1 if x in list2] +def is_potentially_comparable_benchmark(x): + return ('time_unit' in x and 'real_time' in x and 'cpu_time' in x) + + def partition_benchmarks(json1, json2): """ While preserving the ordering, find benchmarks with the same names in @@ -125,10 +131,17 @@ def partition_benchmarks(json1, json2): names = intersect(json1_unique_names, json2_unique_names) partitions = [] for name in names: + time_unit = None # Pick the time unit from the first entry of the lhs benchmark. - time_unit = (x['time_unit'] - for x in json1['benchmarks'] if x['name'] == name).next() + # We should be careful not to crash with unexpected input. + for x in json1['benchmarks']: + if (x['name'] == name and is_potentially_comparable_benchmark(x)): + time_unit = x['time_unit'] + break + if time_unit is None: + continue # Filter by name and time unit. + # All the repetitions are assumed to be comparable. lhs = [x for x in json1['benchmarks'] if x['name'] == name and x['time_unit'] == time_unit] rhs = [x for x in json2['benchmarks'] if x['name'] == name and @@ -144,10 +157,7 @@ def extract_field(partition, field_name): return [lhs, rhs] -def print_utest(partition, utest_alpha, first_col_width, use_color=True): - timings_time = extract_field(partition, 'real_time') - timings_cpu = extract_field(partition, 'cpu_time') - +def calc_utest(timings_cpu, timings_time): min_rep_cnt = min(len(timings_time[0]), len(timings_time[1]), len(timings_cpu[0]), @@ -155,43 +165,115 @@ def print_utest(partition, utest_alpha, first_col_width, use_color=True): # Does *everything* has at least UTEST_MIN_REPETITIONS repetitions? if min_rep_cnt < UTEST_MIN_REPETITIONS: - return [] - - def get_utest_color(pval): - return BC_FAIL if pval >= utest_alpha else BC_OKGREEN + return False, None, None time_pvalue = mannwhitneyu( timings_time[0], timings_time[1], alternative='two-sided').pvalue cpu_pvalue = mannwhitneyu( timings_cpu[0], timings_cpu[1], alternative='two-sided').pvalue + return (min_rep_cnt >= UTEST_OPTIMAL_REPETITIONS), cpu_pvalue, time_pvalue + +def print_utest(bc_name, utest, utest_alpha, first_col_width, use_color=True): + def get_utest_color(pval): + return BC_FAIL if pval >= utest_alpha else BC_OKGREEN + + # Check if we failed miserably with minimum required repetitions for utest + if not utest['have_optimal_repetitions'] and utest['cpu_pvalue'] is None and utest['time_pvalue'] is None: + return [] + dsc = "U Test, Repetitions: {} vs {}".format( - len(timings_cpu[0]), len(timings_cpu[1])) + utest['nr_of_repetitions'], utest['nr_of_repetitions_other']) dsc_color = BC_OKGREEN - if min_rep_cnt < UTEST_OPTIMAL_REPETITIONS: + # We still got some results to show but issue a warning about it. + if not utest['have_optimal_repetitions']: dsc_color = BC_WARNING dsc += ". WARNING: Results unreliable! {}+ repetitions recommended.".format( UTEST_OPTIMAL_REPETITIONS) special_str = "{}{:<{}s}{endc}{}{:16.4f}{endc}{}{:16.4f}{endc}{} {}" - last_name = partition[0][0]['name'] return [color_format(use_color, special_str, BC_HEADER, - "{}{}".format(last_name, UTEST_COL_NAME), + "{}{}".format(bc_name, UTEST_COL_NAME), first_col_width, - get_utest_color(time_pvalue), time_pvalue, - get_utest_color(cpu_pvalue), cpu_pvalue, + get_utest_color( + utest['time_pvalue']), utest['time_pvalue'], + get_utest_color( + utest['cpu_pvalue']), utest['cpu_pvalue'], dsc_color, dsc, endc=BC_ENDC)] -def generate_difference_report( +def get_difference_report( json1, json2, - display_aggregates_only=False, + utest=False): + """ + Calculate and report the difference between each test of two benchmarks + runs specified as 'json1' and 'json2'. Output is another json containing + relevant details for each test run. + """ + assert utest is True or utest is False + + diff_report = [] + partitions = partition_benchmarks(json1, json2) + for partition in partitions: + benchmark_name = partition[0][0]['name'] + time_unit = partition[0][0]['time_unit'] + measurements = [] + utest_results = {} + # Careful, we may have different repetition count. + for i in range(min(len(partition[0]), len(partition[1]))): + bn = partition[0][i] + other_bench = partition[1][i] + measurements.append({ + 'real_time': bn['real_time'], + 'cpu_time': bn['cpu_time'], + 'real_time_other': other_bench['real_time'], + 'cpu_time_other': other_bench['cpu_time'], + 'time': calculate_change(bn['real_time'], other_bench['real_time']), + 'cpu': calculate_change(bn['cpu_time'], other_bench['cpu_time']) + }) + + # After processing the whole partition, if requested, do the U test. + if utest: + timings_cpu = extract_field(partition, 'cpu_time') + timings_time = extract_field(partition, 'real_time') + have_optimal_repetitions, cpu_pvalue, time_pvalue = calc_utest(timings_cpu, timings_time) + if cpu_pvalue and time_pvalue: + utest_results = { + 'have_optimal_repetitions': have_optimal_repetitions, + 'cpu_pvalue': cpu_pvalue, + 'time_pvalue': time_pvalue, + 'nr_of_repetitions': len(timings_cpu[0]), + 'nr_of_repetitions_other': len(timings_cpu[1]) + } + + # Store only if we had any measurements for given benchmark. + # E.g. partition_benchmarks will filter out the benchmarks having + # time units which are not compatible with other time units in the + # benchmark suite. + if measurements: + run_type = partition[0][0]['run_type'] if 'run_type' in partition[0][0] else '' + aggregate_name = partition[0][0]['aggregate_name'] if run_type == 'aggregate' and 'aggregate_name' in partition[0][0] else '' + diff_report.append({ + 'name': benchmark_name, + 'measurements': measurements, + 'time_unit': time_unit, + 'run_type': run_type, + 'aggregate_name': aggregate_name, + 'utest': utest_results + }) + + return diff_report + + +def print_difference_report( + json_diff_report, + include_aggregates_only=False, utest=False, utest_alpha=0.05, use_color=True): @@ -200,14 +282,16 @@ def generate_difference_report( runs specified as 'json1' and 'json2'. """ assert utest is True or utest is False - first_col_width = find_longest_name(json1['benchmarks']) - def find_test(name): - for b in json2['benchmarks']: - if b['name'] == name: - return b - return None + def get_color(res): + if res > 0.05: + return BC_FAIL + elif res > -0.07: + return BC_WHITE + else: + return BC_CYAN + first_col_width = find_longest_name(json_diff_report) first_col_width = max( first_col_width, len('Benchmark')) @@ -216,50 +300,33 @@ def find_test(name): 'Benchmark', 12 + first_col_width) output_strs = [first_line, '-' * len(first_line)] - partitions = partition_benchmarks(json1, json2) - for partition in partitions: - # Careful, we may have different repetition count. - for i in range(min(len(partition[0]), len(partition[1]))): - bn = partition[0][i] - other_bench = partition[1][i] - - # *If* we were asked to only display aggregates, - # and if it is non-aggregate, then skip it. - if display_aggregates_only and 'run_type' in bn and 'run_type' in other_bench: - assert bn['run_type'] == other_bench['run_type'] - if bn['run_type'] != 'aggregate': - continue - - fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}" - - def get_color(res): - if res > 0.05: - return BC_FAIL - elif res > -0.07: - return BC_WHITE - else: - return BC_CYAN - - tres = calculate_change(bn['real_time'], other_bench['real_time']) - cpures = calculate_change(bn['cpu_time'], other_bench['cpu_time']) - output_strs += [color_format(use_color, - fmt_str, - BC_HEADER, - bn['name'], - first_col_width, - get_color(tres), - tres, - get_color(cpures), - cpures, - bn['real_time'], - other_bench['real_time'], - bn['cpu_time'], - other_bench['cpu_time'], - endc=BC_ENDC)] - - # After processing the whole partition, if requested, do the U test. - if utest: - output_strs += print_utest(partition, + fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}" + for benchmark in json_diff_report: + # *If* we were asked to only include aggregates, + # and if it is non-aggregate, then don't print it. + if not include_aggregates_only or not 'run_type' in benchmark or benchmark['run_type'] == 'aggregate': + for measurement in benchmark['measurements']: + output_strs += [color_format(use_color, + fmt_str, + BC_HEADER, + benchmark['name'], + first_col_width, + get_color(measurement['time']), + measurement['time'], + get_color(measurement['cpu']), + measurement['cpu'], + measurement['real_time'], + measurement['real_time_other'], + measurement['cpu_time'], + measurement['cpu_time_other'], + endc=BC_ENDC)] + + # After processing the measurements, if requested and + # if applicable (e.g. u-test exists for given benchmark), + # print the U test. + if utest and benchmark['utest']: + output_strs += print_utest(benchmark['name'], + benchmark['utest'], utest_alpha=utest_alpha, first_col_width=first_col_width, use_color=use_color) @@ -300,21 +367,26 @@ def test_basic(self): class TestReportDifference(unittest.TestCase): - def load_results(self): - import json - testInputs = os.path.join( - os.path.dirname( - os.path.realpath(__file__)), - 'Inputs') - testOutput1 = os.path.join(testInputs, 'test1_run1.json') - testOutput2 = os.path.join(testInputs, 'test1_run2.json') - with open(testOutput1, 'r') as f: - json1 = json.load(f) - with open(testOutput2, 'r') as f: - json2 = json.load(f) - return json1, json2 - - def test_basic(self): + @classmethod + def setUpClass(cls): + def load_results(): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput1 = os.path.join(testInputs, 'test1_run1.json') + testOutput2 = os.path.join(testInputs, 'test1_run2.json') + with open(testOutput1, 'r') as f: + json1 = json.load(f) + with open(testOutput2, 'r') as f: + json2 = json.load(f) + return json1, json2 + + json1, json2 = load_results() + cls.json_diff_report = get_difference_report(json1, json2) + + def test_json_diff_report_pretty_printing(self): expect_lines = [ ['BM_SameTimes', '+0.0000', '+0.0000', '10', '10', '10', '10'], ['BM_2xFaster', '-0.5000', '-0.5000', '50', '25', '50', '25'], @@ -330,11 +402,10 @@ def test_basic(self): ['BM_10PercentCPUToTime', '+0.1000', '-0.1000', '100', '110', '100', '90'], ['BM_ThirdFaster', '-0.3333', '-0.3334', '100', '67', '100', '67'], - ['BM_BadTimeUnit', '-0.9000', '+0.2000', '0', '0', '0', '1'], + ['BM_NotBadTimeUnit', '-0.9000', '+0.2000', '0', '0', '0', '1'], ] - json1, json2 = self.load_results() - output_lines_with_header = generate_difference_report( - json1, json2, use_color=False) + output_lines_with_header = print_difference_report( + self.json_diff_report, use_color=False) output_lines = output_lines_with_header[2:] print("\n") print("\n".join(output_lines_with_header)) @@ -344,31 +415,118 @@ def test_basic(self): self.assertEqual(len(parts), 7) self.assertEqual(expect_lines[i], parts) + def test_json_diff_report_output(self): + expected_output = [ + { + 'name': 'BM_SameTimes', + 'measurements': [{'time': 0.0000, 'cpu': 0.0000, 'real_time': 10, 'real_time_other': 10, 'cpu_time': 10, 'cpu_time_other': 10}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_2xFaster', + 'measurements': [{'time': -0.5000, 'cpu': -0.5000, 'real_time': 50, 'real_time_other': 25, 'cpu_time': 50, 'cpu_time_other': 25}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_2xSlower', + 'measurements': [{'time': 1.0000, 'cpu': 1.0000, 'real_time': 50, 'real_time_other': 100, 'cpu_time': 50, 'cpu_time_other': 100}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_1PercentFaster', + 'measurements': [{'time': -0.0100, 'cpu': -0.0100, 'real_time': 100, 'real_time_other': 98.9999999, 'cpu_time': 100, 'cpu_time_other': 98.9999999}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_1PercentSlower', + 'measurements': [{'time': 0.0100, 'cpu': 0.0100, 'real_time': 100, 'real_time_other': 101, 'cpu_time': 100, 'cpu_time_other': 101}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_10PercentFaster', + 'measurements': [{'time': -0.1000, 'cpu': -0.1000, 'real_time': 100, 'real_time_other': 90, 'cpu_time': 100, 'cpu_time_other': 90}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_10PercentSlower', + 'measurements': [{'time': 0.1000, 'cpu': 0.1000, 'real_time': 100, 'real_time_other': 110, 'cpu_time': 100, 'cpu_time_other': 110}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_100xSlower', + 'measurements': [{'time': 99.0000, 'cpu': 99.0000, 'real_time': 100, 'real_time_other': 10000, 'cpu_time': 100, 'cpu_time_other': 10000}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_100xFaster', + 'measurements': [{'time': -0.9900, 'cpu': -0.9900, 'real_time': 10000, 'real_time_other': 100, 'cpu_time': 10000, 'cpu_time_other': 100}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_10PercentCPUToTime', + 'measurements': [{'time': 0.1000, 'cpu': -0.1000, 'real_time': 100, 'real_time_other': 110, 'cpu_time': 100, 'cpu_time_other': 90}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_ThirdFaster', + 'measurements': [{'time': -0.3333, 'cpu': -0.3334, 'real_time': 100, 'real_time_other': 67, 'cpu_time': 100, 'cpu_time_other': 67}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': 'BM_NotBadTimeUnit', + 'measurements': [{'time': -0.9000, 'cpu': 0.2000, 'real_time': 0.4, 'real_time_other': 0.04, 'cpu_time': 0.5, 'cpu_time_other': 0.6}], + 'time_unit': 's', + 'utest': {} + }, + ] + self.assertEqual(len(self.json_diff_report), len(expected_output)) + for out, expected in zip( + self.json_diff_report, expected_output): + self.assertEqual(out['name'], expected['name']) + self.assertEqual(out['time_unit'], expected['time_unit']) + assert_utest(self, out, expected) + assert_measurements(self, out, expected) + class TestReportDifferenceBetweenFamilies(unittest.TestCase): - def load_result(self): - import json - testInputs = os.path.join( - os.path.dirname( - os.path.realpath(__file__)), - 'Inputs') - testOutput = os.path.join(testInputs, 'test2_run.json') - with open(testOutput, 'r') as f: - json = json.load(f) - return json + @classmethod + def setUpClass(cls): + def load_result(): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput = os.path.join(testInputs, 'test2_run.json') + with open(testOutput, 'r') as f: + json = json.load(f) + return json + + json = load_result() + json1 = filter_benchmark(json, "BM_Z.ro", ".") + json2 = filter_benchmark(json, "BM_O.e", ".") + cls.json_diff_report = get_difference_report(json1, json2) - def test_basic(self): + def test_json_diff_report_pretty_printing(self): expect_lines = [ ['.', '-0.5000', '-0.5000', '10', '5', '10', '5'], ['./4', '-0.5000', '-0.5000', '40', '20', '40', '20'], ['Prefix/.', '-0.5000', '-0.5000', '20', '10', '20', '10'], ['Prefix/./3', '-0.5000', '-0.5000', '30', '15', '30', '15'], ] - json = self.load_result() - json1 = filter_benchmark(json, "BM_Z.ro", ".") - json2 = filter_benchmark(json, "BM_O.e", ".") - output_lines_with_header = generate_difference_report( - json1, json2, use_color=False) + output_lines_with_header = print_difference_report( + self.json_diff_report, use_color=False) output_lines = output_lines_with_header[2:] print("\n") print("\n".join(output_lines_with_header)) @@ -378,24 +536,64 @@ def test_basic(self): self.assertEqual(len(parts), 7) self.assertEqual(expect_lines[i], parts) + def test_json_diff_report(self): + expected_output = [ + { + 'name': u'.', + 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 10, 'real_time_other': 5, 'cpu_time': 10, 'cpu_time_other': 5}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': u'./4', + 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 40, 'real_time_other': 20, 'cpu_time': 40, 'cpu_time_other': 20}], + 'time_unit': 'ns', + 'utest': {}, + }, + { + 'name': u'Prefix/.', + 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 20, 'real_time_other': 10, 'cpu_time': 20, 'cpu_time_other': 10}], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': u'Prefix/./3', + 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 30, 'real_time_other': 15, 'cpu_time': 30, 'cpu_time_other': 15}], + 'time_unit': 'ns', + 'utest': {} + } + ] + self.assertEqual(len(self.json_diff_report), len(expected_output)) + for out, expected in zip( + self.json_diff_report, expected_output): + self.assertEqual(out['name'], expected['name']) + self.assertEqual(out['time_unit'], expected['time_unit']) + assert_utest(self, out, expected) + assert_measurements(self, out, expected) + class TestReportDifferenceWithUTest(unittest.TestCase): - def load_results(self): - import json - testInputs = os.path.join( - os.path.dirname( - os.path.realpath(__file__)), - 'Inputs') - testOutput1 = os.path.join(testInputs, 'test3_run0.json') - testOutput2 = os.path.join(testInputs, 'test3_run1.json') - with open(testOutput1, 'r') as f: - json1 = json.load(f) - with open(testOutput2, 'r') as f: - json2 = json.load(f) - return json1, json2 - - def test_utest(self): - expect_lines = [] + @classmethod + def setUpClass(cls): + def load_results(): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput1 = os.path.join(testInputs, 'test3_run0.json') + testOutput2 = os.path.join(testInputs, 'test3_run1.json') + with open(testOutput1, 'r') as f: + json1 = json.load(f) + with open(testOutput2, 'r') as f: + json2 = json.load(f) + return json1, json2 + + json1, json2 = load_results() + cls.json_diff_report = get_difference_report( + json1, json2, utest=True) + + def test_json_diff_report_pretty_printing(self): expect_lines = [ ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'], @@ -434,9 +632,8 @@ def test_utest(self): 'recommended.'], ['medium', '-0.3750', '-0.3375', '8', '5', '80', '53'], ] - json1, json2 = self.load_results() - output_lines_with_header = generate_difference_report( - json1, json2, utest=True, utest_alpha=0.05, use_color=False) + output_lines_with_header = print_difference_report( + self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False) output_lines = output_lines_with_header[2:] print("\n") print("\n".join(output_lines_with_header)) @@ -445,25 +642,151 @@ def test_utest(self): parts = [x for x in output_lines[i].split(' ') if x] self.assertEqual(expect_lines[i], parts) + def test_json_diff_report_pretty_printing_aggregates_only(self): + expect_lines = [ + ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], + ['BM_Two_pvalue', + '0.6985', + '0.6985', + 'U', + 'Test,', + 'Repetitions:', + '2', + 'vs', + '2.', + 'WARNING:', + 'Results', + 'unreliable!', + '9+', + 'repetitions', + 'recommended.'], + ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'], + ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'], + ['short_pvalue', + '0.7671', + '0.1489', + 'U', + 'Test,', + 'Repetitions:', + '2', + 'vs', + '3.', + 'WARNING:', + 'Results', + 'unreliable!', + '9+', + 'repetitions', + 'recommended.'], + ] + output_lines_with_header = print_difference_report( + self.json_diff_report, include_aggregates_only=True, utest=True, utest_alpha=0.05, use_color=False) + output_lines = output_lines_with_header[2:] + print("\n") + print("\n".join(output_lines_with_header)) + self.assertEqual(len(output_lines), len(expect_lines)) + for i in range(0, len(output_lines)): + parts = [x for x in output_lines[i].split(' ') if x] + self.assertEqual(expect_lines[i], parts) + + def test_json_diff_report(self): + expected_output = [ + { + 'name': u'BM_One', + 'measurements': [ + {'time': -0.1, + 'cpu': 0.1, + 'real_time': 10, + 'real_time_other': 9, + 'cpu_time': 100, + 'cpu_time_other': 110} + ], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': u'BM_Two', + 'measurements': [ + {'time': 0.1111111111111111, + 'cpu': -0.011111111111111112, + 'real_time': 9, + 'real_time_other': 10, + 'cpu_time': 90, + 'cpu_time_other': 89}, + {'time': -0.125, 'cpu': -0.16279069767441862, 'real_time': 8, + 'real_time_other': 7, 'cpu_time': 86, 'cpu_time_other': 72} + ], + 'time_unit': 'ns', + 'utest': { + 'have_optimal_repetitions': False, 'cpu_pvalue': 0.6985353583033387, 'time_pvalue': 0.6985353583033387 + } + }, + { + 'name': u'short', + 'measurements': [ + {'time': -0.125, + 'cpu': -0.0625, + 'real_time': 8, + 'real_time_other': 7, + 'cpu_time': 80, + 'cpu_time_other': 75}, + {'time': -0.4325, + 'cpu': -0.13506493506493514, + 'real_time': 8, + 'real_time_other': 4.54, + 'cpu_time': 77, + 'cpu_time_other': 66.6} + ], + 'time_unit': 'ns', + 'utest': { + 'have_optimal_repetitions': False, 'cpu_pvalue': 0.14891467317876572, 'time_pvalue': 0.7670968684102772 + } + }, + { + 'name': u'medium', + 'measurements': [ + {'time': -0.375, + 'cpu': -0.3375, + 'real_time': 8, + 'real_time_other': 5, + 'cpu_time': 80, + 'cpu_time_other': 53} + ], + 'time_unit': 'ns', + 'utest': {} + } + ] + self.assertEqual(len(self.json_diff_report), len(expected_output)) + for out, expected in zip( + self.json_diff_report, expected_output): + self.assertEqual(out['name'], expected['name']) + self.assertEqual(out['time_unit'], expected['time_unit']) + assert_utest(self, out, expected) + assert_measurements(self, out, expected) + class TestReportDifferenceWithUTestWhileDisplayingAggregatesOnly( unittest.TestCase): - def load_results(self): - import json - testInputs = os.path.join( - os.path.dirname( - os.path.realpath(__file__)), - 'Inputs') - testOutput1 = os.path.join(testInputs, 'test3_run0.json') - testOutput2 = os.path.join(testInputs, 'test3_run1.json') - with open(testOutput1, 'r') as f: - json1 = json.load(f) - with open(testOutput2, 'r') as f: - json2 = json.load(f) - return json1, json2 - - def test_utest(self): - expect_lines = [] + @classmethod + def setUpClass(cls): + def load_results(): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput1 = os.path.join(testInputs, 'test3_run0.json') + testOutput2 = os.path.join(testInputs, 'test3_run1.json') + with open(testOutput1, 'r') as f: + json1 = json.load(f) + with open(testOutput2, 'r') as f: + json2 = json.load(f) + return json1, json2 + + json1, json2 = load_results() + cls.json_diff_report = get_difference_report( + json1, json2, utest=True) + + def test_json_diff_report_pretty_printing(self): expect_lines = [ ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'], @@ -500,10 +823,10 @@ def test_utest(self): '9+', 'repetitions', 'recommended.'], + ['medium', '-0.3750', '-0.3375', '8', '5', '80', '53'] ] - json1, json2 = self.load_results() - output_lines_with_header = generate_difference_report( - json1, json2, display_aggregates_only=True, + output_lines_with_header = print_difference_report( + self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False) output_lines = output_lines_with_header[2:] print("\n") @@ -513,6 +836,152 @@ def test_utest(self): parts = [x for x in output_lines[i].split(' ') if x] self.assertEqual(expect_lines[i], parts) + def test_json_diff_report(self): + expected_output = [ + { + 'name': u'BM_One', + 'measurements': [ + {'time': -0.1, + 'cpu': 0.1, + 'real_time': 10, + 'real_time_other': 9, + 'cpu_time': 100, + 'cpu_time_other': 110} + ], + 'time_unit': 'ns', + 'utest': {} + }, + { + 'name': u'BM_Two', + 'measurements': [ + {'time': 0.1111111111111111, + 'cpu': -0.011111111111111112, + 'real_time': 9, + 'real_time_other': 10, + 'cpu_time': 90, + 'cpu_time_other': 89}, + {'time': -0.125, 'cpu': -0.16279069767441862, 'real_time': 8, + 'real_time_other': 7, 'cpu_time': 86, 'cpu_time_other': 72} + ], + 'time_unit': 'ns', + 'utest': { + 'have_optimal_repetitions': False, 'cpu_pvalue': 0.6985353583033387, 'time_pvalue': 0.6985353583033387 + } + }, + { + 'name': u'short', + 'measurements': [ + {'time': -0.125, + 'cpu': -0.0625, + 'real_time': 8, + 'real_time_other': 7, + 'cpu_time': 80, + 'cpu_time_other': 75}, + {'time': -0.4325, + 'cpu': -0.13506493506493514, + 'real_time': 8, + 'real_time_other': 4.54, + 'cpu_time': 77, + 'cpu_time_other': 66.6} + ], + 'time_unit': 'ns', + 'utest': { + 'have_optimal_repetitions': False, 'cpu_pvalue': 0.14891467317876572, 'time_pvalue': 0.7670968684102772 + } + }, + { + 'name': u'medium', + 'measurements': [ + {'real_time_other': 5, + 'cpu_time': 80, + 'time': -0.375, + 'real_time': 8, + 'cpu_time_other': 53, + 'cpu': -0.3375 + } + ], + 'utest': {}, + 'time_unit': u'ns', + 'aggregate_name': '' + } + ] + self.assertEqual(len(self.json_diff_report), len(expected_output)) + for out, expected in zip( + self.json_diff_report, expected_output): + self.assertEqual(out['name'], expected['name']) + self.assertEqual(out['time_unit'], expected['time_unit']) + assert_utest(self, out, expected) + assert_measurements(self, out, expected) + + +class TestReportSorting(unittest.TestCase): + @classmethod + def setUpClass(cls): + def load_result(): + import json + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') + testOutput = os.path.join(testInputs, 'test4_run.json') + with open(testOutput, 'r') as f: + json = json.load(f) + return json + + cls.json = load_result() + + def test_json_diff_report_pretty_printing(self): + import util + + expected_names = [ + "99 family 0 instance 0 repetition 0", + "98 family 0 instance 0 repetition 1", + "97 family 0 instance 0 aggregate", + "96 family 0 instance 1 repetition 0", + "95 family 0 instance 1 repetition 1", + "94 family 0 instance 1 aggregate", + "93 family 1 instance 0 repetition 0", + "92 family 1 instance 0 repetition 1", + "91 family 1 instance 0 aggregate", + "90 family 1 instance 1 repetition 0", + "89 family 1 instance 1 repetition 1", + "88 family 1 instance 1 aggregate" + ] + + for n in range(len(self.json['benchmarks']) ** 2): + random.shuffle(self.json['benchmarks']) + sorted_benchmarks = util.sort_benchmark_results(self.json)[ + 'benchmarks'] + self.assertEqual(len(expected_names), len(sorted_benchmarks)) + for out, expected in zip(sorted_benchmarks, expected_names): + self.assertEqual(out['name'], expected) + + +def assert_utest(unittest_instance, lhs, rhs): + if lhs['utest']: + unittest_instance.assertAlmostEqual( + lhs['utest']['cpu_pvalue'], + rhs['utest']['cpu_pvalue']) + unittest_instance.assertAlmostEqual( + lhs['utest']['time_pvalue'], + rhs['utest']['time_pvalue']) + unittest_instance.assertEqual( + lhs['utest']['have_optimal_repetitions'], + rhs['utest']['have_optimal_repetitions']) + else: + # lhs is empty. assert if rhs is not. + unittest_instance.assertEqual(lhs['utest'], rhs['utest']) + + +def assert_measurements(unittest_instance, lhs, rhs): + for m1, m2 in zip(lhs['measurements'], rhs['measurements']): + unittest_instance.assertEqual(m1['real_time'], m2['real_time']) + unittest_instance.assertEqual(m1['cpu_time'], m2['cpu_time']) + # m1['time'] and m1['cpu'] hold values which are being calculated, + # and therefore we must use almost-equal pattern. + unittest_instance.assertAlmostEqual(m1['time'], m2['time'], places=4) + unittest_instance.assertAlmostEqual(m1['cpu'], m2['cpu'], places=4) + if __name__ == '__main__': unittest.main() diff --git a/libcxx/utils/google-benchmark/tools/gbench/util.py b/libcxx/utils/google-benchmark/tools/gbench/util.py index 1f8e8e2c47968..5d0012c0cb1c3 100644 --- a/libcxx/utils/google-benchmark/tools/gbench/util.py +++ b/libcxx/utils/google-benchmark/tools/gbench/util.py @@ -5,6 +5,7 @@ import tempfile import subprocess import sys +import functools # Input file type enumeration IT_Invalid = 0 @@ -119,6 +120,23 @@ def load_benchmark_results(fname): return json.load(f) +def sort_benchmark_results(result): + benchmarks = result['benchmarks'] + + # From inner key to the outer key! + benchmarks = sorted( + benchmarks, key=lambda benchmark: benchmark['repetition_index'] if 'repetition_index' in benchmark else -1) + benchmarks = sorted( + benchmarks, key=lambda benchmark: 1 if 'run_type' in benchmark and benchmark['run_type'] == "aggregate" else 0) + benchmarks = sorted( + benchmarks, key=lambda benchmark: benchmark['per_family_instance_index'] if 'per_family_instance_index' in benchmark else -1) + benchmarks = sorted( + benchmarks, key=lambda benchmark: benchmark['family_index'] if 'family_index' in benchmark else -1) + + result['benchmarks'] = benchmarks + return result + + def run_benchmark(exe_name, benchmark_flags): """ Run a benchmark specified by 'exe_name' with the specified @@ -158,7 +176,6 @@ def run_or_load_benchmark(filename, benchmark_flags): ftype = check_input_file(filename) if ftype == IT_JSON: return load_benchmark_results(filename) - elif ftype == IT_Executable: + if ftype == IT_Executable: return run_benchmark(filename, benchmark_flags) - else: - assert False # This branch is unreachable + raise ValueError('Unknown file type %s' % ftype) diff --git a/libcxx/utils/google-benchmark/tools/requirements.txt b/libcxx/utils/google-benchmark/tools/requirements.txt new file mode 100644 index 0000000000000..3b3331b5af127 --- /dev/null +++ b/libcxx/utils/google-benchmark/tools/requirements.txt @@ -0,0 +1 @@ +scipy>=1.5.0 \ No newline at end of file diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index 43c9e4abf1cd3..77ba85e4611c5 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -42,6 +42,7 @@ Feature(name='has-fobjc-arc', when=lambda cfg: hasCompileFlag(cfg, '-xobjective-c++ -fobjc-arc') and sys.platform.lower().strip() == 'darwin'), # TODO: this doesn't handle cross-compiling to Apple platforms. Feature(name='objective-c++', when=lambda cfg: hasCompileFlag(cfg, '-xobjective-c++ -fobjc-arc')), + Feature(name='no-noexcept-function-type', when=lambda cfg: featureTestMacros(cfg).get('__cpp_noexcept_function_type', 0) < 201510), Feature(name='non-lockfree-atomics', when=lambda cfg: sourceBuilds(cfg, """ diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index 9bd81075dd14b..9fb35860d483a 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -111,7 +111,7 @@ option(LIBCXXABI_INCLUDE_TESTS "Generate build targets for the libc++abi unit te set(LIBCXXABI_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING "Define suffix of library directory name (32/64)") option(LIBCXXABI_INSTALL_LIBRARY "Install the libc++abi library." ON) -set(LIBCXXABI_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.") +set(LIBCXXABI_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" CACHE STRING "Target triple for cross compiling.") set(LIBCXXABI_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.") set(LIBCXXABI_SYSROOT "" CACHE PATH "Sysroot for cross compiling.") set(LIBCXXABI_LIBCXX_LIBRARY_PATH "" CACHE PATH "The path to libc++ library.") @@ -195,7 +195,8 @@ set(CMAKE_MODULE_PATH if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR}) set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + "Path where built libc++abi libraries should be installed.") if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR}) string(APPEND LIBCXXABI_INSTALL_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR}) @@ -203,11 +204,13 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR}) set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) - set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX}) + set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH + "Path where built libc++abi libraries should be installed.") else() set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR}) set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX}) - set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX}) + set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH + "Path where built libc++abi libraries should be installed.") endif() set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR}) @@ -255,25 +258,21 @@ include(HandleLibcxxabiFlags) add_target_flags_if(LIBCXXABI_BUILD_32_BITS "-m32") if(LIBCXXABI_TARGET_TRIPLE) - add_target_flags("--target=${LIBCXXABI_TARGET_TRIPLE}") + add_target_flags_if_supported("--target=${LIBCXXABI_TARGET_TRIPLE}") elseif(CMAKE_CXX_COMPILER_TARGET) set(LIBCXXABI_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}") endif() if(LIBCXX_GCC_TOOLCHAIN) - add_target_flags("--gcc-toolchain=${LIBCXXABI_GCC_TOOLCHAIN}") + add_target_flags_if_supported("--gcc-toolchain=${LIBCXXABI_GCC_TOOLCHAIN}") elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN) set(LIBCXXABI_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}") endif() if(LIBCXXABI_SYSROOT) - add_target_flags("--sysroot=${LIBCXXABI_SYSROOT}") + add_target_flags_if_supported("--sysroot=${LIBCXXABI_SYSROOT}") elseif(CMAKE_SYSROOT) set(LIBCXXABI_SYSROOT "${CMAKE_SYSROOT}") endif() -if (LIBCXXABI_TARGET_TRIPLE) - set(TARGET_TRIPLE "${LIBCXXABI_TARGET_TRIPLE}") -endif() - # Configure compiler. Must happen after setting the target flags. include(config-ix) diff --git a/libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake b/libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake index 19d6e93b20b02..512e71a6a7805 100644 --- a/libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake +++ b/libcxxabi/cmake/Modules/HandleLibcxxabiFlags.cmake @@ -123,6 +123,17 @@ macro(add_target_flags_if condition) endif() endmacro() +# Add all the flags supported by the compiler to all of +# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXXABI_COMPILE_FLAGS' +# and 'LIBCXXABI_LINK_FLAGS'. +macro(add_target_flags_if_supported) + foreach(flag ${ARGN}) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG") + add_target_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag}) + endforeach() +endmacro() + # Add a specified list of flags to both 'LIBCXXABI_COMPILE_FLAGS' and # 'LIBCXXABI_LINK_FLAGS'. macro(add_flags) diff --git a/libcxxabi/test/CMakeLists.txt b/libcxxabi/test/CMakeLists.txt index 788fd5a448bb2..a8a97aecba47a 100644 --- a/libcxxabi/test/CMakeLists.txt +++ b/libcxxabi/test/CMakeLists.txt @@ -86,14 +86,20 @@ if (LLVM_USE_SANITIZER) serialize_lit_param(use_sanitizer "\"${LLVM_USE_SANITIZER}\"") endif() -if (TARGET_TRIPLE) - serialize_lit_param(target_triple "\"${TARGET_TRIPLE}\"") +if (LIBCXXABI_TARGET_TRIPLE) + serialize_lit_param(target_triple "\"${LIBCXXABI_TARGET_TRIPLE}\"") endif() if (LIBCXXABI_BUILD_32_BITS) serialize_lit_param(enable_32bit True) endif() +foreach(param IN LISTS LIBCXXABI_TEST_PARAMS) + string(REGEX REPLACE "(.+)=(.+)" "\\1" name "${param}") + string(REGEX REPLACE "(.+)=(.+)" "\\2" value "${param}") + serialize_lit_param("${name}" "\"${value}\"") +endforeach() + configure_lit_site_cfg( "${LIBCXXABI_TEST_CONFIG}" ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg @@ -101,5 +107,4 @@ configure_lit_site_cfg( add_lit_testsuite(check-cxxabi "Running libcxxabi tests" ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${LIBCXXABI_TEST_DEPS} - PARAMS "${LIBCXXABI_TEST_PARAMS}") + DEPENDS ${LIBCXXABI_TEST_DEPS}) diff --git a/libcxxabi/test/catch_function_03.pass.cpp b/libcxxabi/test/catch_function_03.pass.cpp index b321ecf6ed6f8..d8b2dd8fe67c0 100644 --- a/libcxxabi/test/catch_function_03.pass.cpp +++ b/libcxxabi/test/catch_function_03.pass.cpp @@ -7,7 +7,10 @@ //===----------------------------------------------------------------------===// // Can a noexcept function pointer be caught by a non-noexcept catch clause? -// UNSUPPORTED: no-exceptions, libcxxabi-no-noexcept-function-type +// UNSUPPORTED: no-exceptions, no-noexcept-function-type + +// Support for catching a function pointer including noexcept was shipped in macOS 10.13 +// XFAIL: use_system_cxx_lib && {{.+}}-apple-macosx10.{{9|10|11|12}} #include diff --git a/libcxxabi/test/catch_member_function_pointer_02.pass.cpp b/libcxxabi/test/catch_member_function_pointer_02.pass.cpp index f92035b4ff8f9..d658f26793c10 100644 --- a/libcxxabi/test/catch_member_function_pointer_02.pass.cpp +++ b/libcxxabi/test/catch_member_function_pointer_02.pass.cpp @@ -6,9 +6,11 @@ // //===----------------------------------------------------------------------===// -// Can a noexcept member function pointer be caught by a non-noexcept catch -// clause? -// UNSUPPORTED: no-exceptions, libcxxabi-no-noexcept-function-type +// Can a noexcept member function pointer be caught by a non-noexcept catch clause? +// UNSUPPORTED: no-exceptions, no-noexcept-function-type + +// Support for catching a function pointer including noexcept was shipped in macOS 10.13 +// XFAIL: use_system_cxx_lib && {{.+}}-apple-macosx10.{{9|10|11|12}} // GCC 7 and 8 support noexcept function types but this test still fails. // This is likely a bug in their implementation. Investigation needed. diff --git a/libcxxabi/test/libcxxabi/test/config.py b/libcxxabi/test/libcxxabi/test/config.py index c59d203968b58..f44892be06f4b 100644 --- a/libcxxabi/test/libcxxabi/test/config.py +++ b/libcxxabi/test/libcxxabi/test/config.py @@ -37,13 +37,8 @@ def configure_obj_root(self): self.libcxxabi_obj_root = self.get_lit_conf('libcxxabi_obj_root') super(Configuration, self).configure_obj_root() - def has_cpp_feature(self, feature, required_value): - return intMacroValue(self.cxx.dumpMacros().get('__cpp_' + feature, '0')) >= required_value - def configure_features(self): super(Configuration, self).configure_features() - if not self.has_cpp_feature('noexcept_function_type', 201510): - self.config.available_features.add('libcxxabi-no-noexcept-function-type') if not self.get_lit_bool('llvm_unwinder', False): self.config.available_features.add('libcxxabi-has-system-unwinder') diff --git a/libcxxabi/test/thread_local_destruction_order.pass.cpp b/libcxxabi/test/thread_local_destruction_order.pass.cpp index 50836949bb7d9..2edbddc56df46 100644 --- a/libcxxabi/test/thread_local_destruction_order.pass.cpp +++ b/libcxxabi/test/thread_local_destruction_order.pass.cpp @@ -9,6 +9,9 @@ // UNSUPPORTED: c++03 // UNSUPPORTED: libcxxabi-no-threads +// TODO: Investigate this failure +// XFAIL: target=arm64-apple-{{.+}} + #include #include diff --git a/libcxxabi/test/unwind_02.pass.cpp b/libcxxabi/test/unwind_02.pass.cpp index 050e4afed446e..7c1dea2a1c1dc 100644 --- a/libcxxabi/test/unwind_02.pass.cpp +++ b/libcxxabi/test/unwind_02.pass.cpp @@ -13,6 +13,7 @@ #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunreachable-code" +#pragma GCC diagnostic ignored "-Wdeprecated" // dynamic exception specifications are deprecated #endif struct A diff --git a/libcxxabi/test/unwind_03.pass.cpp b/libcxxabi/test/unwind_03.pass.cpp index 154fb6e8ff7e3..0cd5a2bc9652b 100644 --- a/libcxxabi/test/unwind_03.pass.cpp +++ b/libcxxabi/test/unwind_03.pass.cpp @@ -15,6 +15,7 @@ #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunreachable-code" +#pragma GCC diagnostic ignored "-Wdeprecated" // dynamic exception specifications are deprecated #endif struct A diff --git a/libcxxabi/test/unwind_04.pass.cpp b/libcxxabi/test/unwind_04.pass.cpp index d85434dc8551c..fcde314768a6e 100644 --- a/libcxxabi/test/unwind_04.pass.cpp +++ b/libcxxabi/test/unwind_04.pass.cpp @@ -15,6 +15,7 @@ #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunreachable-code" +#pragma GCC diagnostic ignored "-Wdeprecated" // dynamic exception specifications are deprecated #endif struct A diff --git a/libcxxabi/test/unwind_05.pass.cpp b/libcxxabi/test/unwind_05.pass.cpp index 2f9f8da60325e..670a8eb99e43d 100644 --- a/libcxxabi/test/unwind_05.pass.cpp +++ b/libcxxabi/test/unwind_05.pass.cpp @@ -15,6 +15,7 @@ #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunreachable-code" +#pragma GCC diagnostic ignored "-Wdeprecated" // dynamic exception specifications are deprecated #endif struct A diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index a2c03fd3f8aad..81eddbc248792 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -77,7 +77,7 @@ cmake_dependent_option(LIBUNWIND_INSTALL_STATIC_LIBRARY cmake_dependent_option(LIBUNWIND_INSTALL_SHARED_LIBRARY "Install the shared libunwind library." ON "LIBUNWIND_ENABLE_SHARED;LIBUNWIND_INSTALL_LIBRARY" OFF) -set(LIBUNWIND_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.") +set(LIBUNWIND_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" CACHE STRING "Target triple for cross compiling.") set(LIBUNWIND_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.") set(LIBUNWIND_SYSROOT "" CACHE PATH "Sysroot for cross compiling.") set(LIBUNWIND_TEST_LINKER_FLAGS "" CACHE STRING @@ -116,17 +116,20 @@ set(CMAKE_MODULE_PATH if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + "Path where built libunwind libraries should be installed.") if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) string(APPEND LIBUNWIND_INSTALL_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) endif() elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX} CACHE PATH + "Path where built libunwind libraries should be installed.") else() set(LIBUNWIND_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBUNWIND_LIBDIR_SUFFIX}) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LIBUNWIND_LIBDIR_SUFFIX} CACHE PATH + "Path where built libunwind libraries should be installed.") endif() set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBUNWIND_LIBRARY_DIR}) @@ -149,25 +152,21 @@ include(HandleLibunwindFlags) add_target_flags_if(LIBUNWIND_BUILD_32_BITS "-m32") if(LIBUNWIND_TARGET_TRIPLE) - add_target_flags("--target=${LIBUNWIND_TARGET_TRIPLE}") + add_target_flags_if_supported("--target=${LIBUNWIND_TARGET_TRIPLE}") elseif(CMAKE_CXX_COMPILER_TARGET) set(LIBUNWIND_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}") endif() if(LIBUNWIND_GCC_TOOLCHAIN) - add_target_flags("--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}") + add_target_flags_if_supported("--gcc-toolchain=${LIBUNWIND_GCC_TOOLCHAIN}") elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN) set(LIBUNWIND_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}") endif() if(LIBUNWIND_SYSROOT) - add_target_flags("--sysroot=${LIBUNWIND_SYSROOT}") + add_target_flags_if_supported("--sysroot=${LIBUNWIND_SYSROOT}") elseif(CMAKE_SYSROOT) set(LIBUNWIND_SYSROOT "${CMAKE_SYSROOT}") endif() -if (LIBUNWIND_TARGET_TRIPLE) - set(TARGET_TRIPLE "${LIBUNWIND_TARGET_TRIPLE}") -endif() - # Configure compiler. include(config-ix) diff --git a/libunwind/cmake/Modules/HandleLibunwindFlags.cmake b/libunwind/cmake/Modules/HandleLibunwindFlags.cmake index 57ba0b8cf7cd9..675071f9433fe 100644 --- a/libunwind/cmake/Modules/HandleLibunwindFlags.cmake +++ b/libunwind/cmake/Modules/HandleLibunwindFlags.cmake @@ -124,6 +124,17 @@ macro(add_target_flags_if condition) endif() endmacro() +# Add all the flags supported by the compiler to all of +# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBUNWIND_COMPILE_FLAGS' +# and 'LIBUNWIND_LINK_FLAGS'. +macro(add_target_flags_if_supported) + foreach(flag ${ARGN}) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBUNWIND_SUPPORTS_${flagname}_FLAG") + add_target_flags_if(LIBUNWIND_SUPPORTS_${flagname}_FLAG ${flag}) + endforeach() +endmacro() + # Add a specified list of flags to both 'LIBUNWIND_COMPILE_FLAGS' and # 'LIBUNWIND_LINK_FLAGS'. macro(add_flags) diff --git a/libunwind/docs/BuildingLibunwind.rst b/libunwind/docs/BuildingLibunwind.rst index ad9dee0519a82..9b11042a65815 100644 --- a/libunwind/docs/BuildingLibunwind.rst +++ b/libunwind/docs/BuildingLibunwind.rst @@ -159,3 +159,10 @@ libunwind specific options .. option:: LIBUNWIND_SYSROOT Sysroot for cross compiling + +.. option:: LIBUNWIND_INSTALL_LIBRARY_DIR:PATH + + **Default**: ``lib${LIBUNWIND_LIBDIR_SUFFIX}`` + + Path where built libunwind libraries should be installed. If a relative path, + relative to ``CMAKE_INSTALL_PREFIX``. diff --git a/libunwind/test/CMakeLists.txt b/libunwind/test/CMakeLists.txt index 5be44e566b6c0..ae83ea90a8cee 100644 --- a/libunwind/test/CMakeLists.txt +++ b/libunwind/test/CMakeLists.txt @@ -36,14 +36,20 @@ if (LLVM_USE_SANITIZER) serialize_lit_param(use_sanitizer "\"${LLVM_USE_SANITIZER}\"") endif() -if (TARGET_TRIPLE) - serialize_lit_param(target_triple "\"${TARGET_TRIPLE}\"") +if (LIBUNWIND_TARGET_TRIPLE) + serialize_lit_param(target_triple "\"${LIBUNWIND_TARGET_TRIPLE}\"") endif() if (LIBUNWIND_BUILD_32_BITS) serialize_lit_param(enable_32bit True) endif() +foreach(param IN LISTS LIBUNWIND_TEST_PARAMS) + string(REGEX REPLACE "(.+)=(.+)" "\\1" name "${param}") + string(REGEX REPLACE "(.+)=(.+)" "\\2" value "${param}") + serialize_lit_param("${name}" "\"${value}\"") +endforeach() + configure_lit_site_cfg( "${LIBUNWIND_TEST_CONFIG}" ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg @@ -51,5 +57,4 @@ configure_lit_site_cfg( add_lit_testsuite(check-unwind "Running libunwind tests" ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS unwind ${LIBUNWIND_TEST_DEPS} - PARAMS "${LIBUNWIND_TEST_PARAMS}") + DEPENDS unwind ${LIBUNWIND_TEST_DEPS}) diff --git a/lld/ELF/Arch/AMDGPU.cpp b/lld/ELF/Arch/AMDGPU.cpp index c765d6e083002..466ad81922d0a 100644 --- a/lld/ELF/Arch/AMDGPU.cpp +++ b/lld/ELF/Arch/AMDGPU.cpp @@ -139,6 +139,12 @@ void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { case R_AMDGPU_REL32_HI: write32le(loc, val >> 32); break; + case R_AMDGPU_REL16: { + int64_t simm = (static_cast(val) - 4) / 4; + checkInt(loc, simm, 16, rel); + write16le(loc, simm); + break; + } default: llvm_unreachable("unknown relocation"); } @@ -154,6 +160,7 @@ RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s, case R_AMDGPU_REL32_LO: case R_AMDGPU_REL32_HI: case R_AMDGPU_REL64: + case R_AMDGPU_REL16: return R_PC; case R_AMDGPU_GOTPCREL: case R_AMDGPU_GOTPCREL32_LO: diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index ef486370ce786..a15959158653b 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -855,22 +855,64 @@ static void readCallGraph(MemoryBufferRef mb) { } } -template static void readCallGraphsFromObjectFiles() { - auto getIndex = [&](ObjFile *obj, uint32_t index) { - const Elf_Rel_Impl &rel = obj->cgProfileRel[index]; - return rel.getSymbol(config->isMips64EL); - }; +// If SHT_LLVM_CALL_GRAPH_PROFILE and its relocation section exist, returns +// true and populates cgProfile and symbolIndices. +template +static bool +processCallGraphRelocations(SmallVector &symbolIndices, + ArrayRef &cgProfile, + ObjFile *inputObj) { + symbolIndices.clear(); + const ELFFile &obj = inputObj->getObj(); + ArrayRef> objSections = + CHECK(obj.sections(), "could not retrieve object sections"); + + if (inputObj->cgProfileSectionIndex == SHN_UNDEF) + return false; + cgProfile = + check(obj.template getSectionContentsAsArray( + objSections[inputObj->cgProfileSectionIndex])); + + for (size_t i = 0, e = objSections.size(); i < e; ++i) { + const Elf_Shdr_Impl &sec = objSections[i]; + if (sec.sh_info == inputObj->cgProfileSectionIndex) { + if (sec.sh_type == SHT_RELA) { + ArrayRef relas = + CHECK(obj.relas(sec), "could not retrieve cg profile rela section"); + for (const typename ELFT::Rela &rel : relas) + symbolIndices.push_back(rel.getSymbol(config->isMips64EL)); + break; + } + if (sec.sh_type == SHT_REL) { + ArrayRef rels = + CHECK(obj.rels(sec), "could not retrieve cg profile rel section"); + for (const typename ELFT::Rel &rel : rels) + symbolIndices.push_back(rel.getSymbol(config->isMips64EL)); + break; + } + } + } + if (symbolIndices.empty()) + warn("SHT_LLVM_CALL_GRAPH_PROFILE exists, but relocation section doesn't"); + return !symbolIndices.empty(); +} + +template static void readCallGraphsFromObjectFiles() { + SmallVector symbolIndices; + ArrayRef cgProfile; for (auto file : objectFiles) { auto *obj = cast>(file); - if (obj->cgProfileRel.empty()) + if (!processCallGraphRelocations(symbolIndices, cgProfile, obj)) continue; - if (obj->cgProfileRel.size() != obj->cgProfile.size() * 2) + + if (symbolIndices.size() != cgProfile.size() * 2) fatal("number of relocations doesn't match Weights"); - for (uint32_t i = 0, size = obj->cgProfile.size(); i < size; ++i) { - const Elf_CGProfile_Impl &cgpe = obj->cgProfile[i]; - uint32_t fromIndex = getIndex(obj, i * 2); - uint32_t toIndex = getIndex(obj, i * 2 + 1); + + for (uint32_t i = 0, size = cgProfile.size(); i < size; ++i) { + const Elf_CGProfile_Impl &cgpe = cgProfile[i]; + uint32_t fromIndex = symbolIndices[i * 2]; + uint32_t toIndex = symbolIndices[i * 2 + 1]; auto *fromSym = dyn_cast(&obj->getSymbol(fromIndex)); auto *toSym = dyn_cast(&obj->getSymbol(toIndex)); if (!fromSym || !toSym) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 93ca1f1f265c8..8487210eb6e18 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -571,19 +571,14 @@ void ObjFile::initializeSections(bool ignoreComdats) { CHECK(obj.getSectionStringTable(objSections), this); std::vector> selectedGroups; - // SHT_LLVM_CALL_GRAPH_PROFILE Section Index. - size_t cgProfileSectionIndex = 0; for (size_t i = 0, e = objSections.size(); i < e; ++i) { if (this->sections[i] == &InputSection::discarded) continue; const Elf_Shdr &sec = objSections[i]; - if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) { - cgProfile = - check(obj.template getSectionContentsAsArray(sec)); + if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) cgProfileSectionIndex = i; - } // SHF_EXCLUDE'ed sections are discarded by the linker. However, // if -r is given, we'll let the final link discard such sections. @@ -669,13 +664,8 @@ void ObjFile::initializeSections(bool ignoreComdats) { continue; const Elf_Shdr &sec = objSections[i]; - if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) { + if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) this->sections[i] = createInputSection(sec); - if (cgProfileSectionIndex && sec.sh_info == cgProfileSectionIndex) { - if (sec.sh_type == SHT_REL) - cgProfileRel = CHECK(getObj().rels(sec), this); - } - } // A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have // the flag. @@ -1272,7 +1262,7 @@ void ArchiveFile::fetch(const Archive::Symbol &sym) { // // 2) Consider the tentative definition as still undefined (ie the promotion to // a real definition happens only after all symbol resolution is done). -// The linker searches archive members for global or weak definitions to +// The linker searches archive members for STB_GLOBAL definitions to // replace the tentative definition with. This is the behavior used by // GNU ld. // @@ -1288,7 +1278,7 @@ static bool isBitcodeNonCommonDef(MemoryBufferRef mb, StringRef symName, for (const irsymtab::Reader::SymbolRef &sym : symtabFile.TheReader.symbols()) { if (sym.isGlobal() && sym.getName() == symName) - return !sym.isUndefined() && !sym.isCommon(); + return !sym.isUndefined() && !sym.isWeak() && !sym.isCommon(); } return false; } @@ -1302,7 +1292,8 @@ static bool isNonCommonDef(MemoryBufferRef mb, StringRef symName, for (auto sym : obj->template getGlobalELFSyms()) { Expected name = sym.getName(stringtable); if (name && name.get() == symName) - return sym.isDefined() && !sym.isCommon(); + return sym.isDefined() && sym.getBinding() == STB_GLOBAL && + !sym.isCommon(); } return false; } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 7b35fd7ea98d1..bd72cfcdd0506 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -249,10 +249,8 @@ template class ObjFile : public ELFFileBase { // Pointer to this input file's .llvm_addrsig section, if it has one. const Elf_Shdr *addrsigSec = nullptr; - // SHT_LLVM_CALL_GRAPH_PROFILE table. - ArrayRef cgProfile; - // SHT_LLVM_CALL_GRAPH_PROFILE relocations, always in the REL format. - ArrayRef cgProfileRel; + // SHT_LLVM_CALL_GRAPH_PROFILE section index. + uint32_t cgProfileSectionIndex = 0; // Get cached DWARF information. DWARFCache *getDwarf(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e22568f53488b..f455d8575e2db 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1088,7 +1088,7 @@ void PhdrEntry::add(OutputSection *sec) { // need these symbols, since IRELATIVE relocs are resolved through GOT // and PLT. For details, see http://www.airs.com/blog/archives/403. template void Writer::addRelIpltSymbols() { - if (config->relocatable || needsInterpSection()) + if (config->relocatable || config->isPic) return; // By default, __rela_iplt_{start,end} belong to a dummy section 0 diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp index 87a6b3f18f481..b98af92a891b7 100644 --- a/lld/MachO/ConcatOutputSection.cpp +++ b/lld/MachO/ConcatOutputSection.cpp @@ -24,7 +24,10 @@ using namespace llvm::MachO; using namespace lld; using namespace lld::macho; +MapVector macho::concatOutputSections; + void ConcatOutputSection::addInput(ConcatInputSection *input) { + assert(input->parent == this); if (inputs.empty()) { align = input->align; flags = input->getFlags(); @@ -33,7 +36,6 @@ void ConcatOutputSection::addInput(ConcatInputSection *input) { finalizeFlags(input); } inputs.push_back(input); - input->parent = this; } // Branch-range extension can be implemented in two ways, either through ... @@ -357,3 +359,22 @@ void ConcatOutputSection::finalizeFlags(InputSection *input) { break; } } + +ConcatOutputSection * +ConcatOutputSection::getOrCreateForInput(const InputSection *isec) { + NamePair names = maybeRenameSection({isec->getSegName(), isec->getName()}); + ConcatOutputSection *&osec = concatOutputSections[names]; + if (!osec) + osec = make(names.second); + return osec; +} + +NamePair macho::maybeRenameSection(NamePair key) { + auto newNames = config->sectionRenameMap.find(key); + if (newNames != config->sectionRenameMap.end()) + return newNames->second; + auto newName = config->segmentRenameMap.find(key.first); + if (newName != config->segmentRenameMap.end()) + return std::make_pair(newName->second, key.second); + return key; +} diff --git a/lld/MachO/ConcatOutputSection.h b/lld/MachO/ConcatOutputSection.h index 531983cd9c13e..ec3d6bfbc344c 100644 --- a/lld/MachO/ConcatOutputSection.h +++ b/lld/MachO/ConcatOutputSection.h @@ -31,6 +31,7 @@ class ConcatOutputSection final : public OutputSection { const ConcatInputSection *firstSection() const { return inputs.front(); } const ConcatInputSection *lastSection() const { return inputs.back(); } + bool isNeeded() const override { return !inputs.empty(); } // These accessors will only be valid after finalizing the section uint64_t getSize() const override { return size; } @@ -50,6 +51,8 @@ class ConcatOutputSection final : public OutputSection { return sec->kind() == ConcatKind; } + static ConcatOutputSection *getOrCreateForInput(const InputSection *); + private: void finalizeFlags(InputSection *input); @@ -79,6 +82,12 @@ struct ThunkInfo { uint8_t sequence = 0; // how many thunks created so-far? }; +NamePair maybeRenameSection(NamePair key); + +// Output sections are added to output segments in iteration order +// of ConcatOutputSection, so must have deterministic iteration order. +extern llvm::MapVector concatOutputSections; + extern llvm::DenseMap thunkMap; } // namespace macho diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h index 654fd794b27a4..d8bff044187c2 100644 --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -14,6 +14,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/Support/CachePruning.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/VersionTuple.h" #include "llvm/TextAPI/Architecture.h" @@ -95,6 +96,7 @@ struct Configuration { Symbol *entry = nullptr; bool hasReexports = false; bool allLoad = false; + bool applicationExtension = false; bool archMultiple = false; bool exportDynamic = false; bool forceLoadObjC = false; @@ -122,6 +124,7 @@ struct Configuration { uint32_t dylibCompatibilityVersion = 0; uint32_t dylibCurrentVersion = 0; uint32_t timeTraceGranularity = 500; + unsigned optimize; std::string progName; // For `clang -arch arm64 -arch x86_64`, clang will: @@ -138,6 +141,8 @@ struct Configuration { llvm::StringRef thinLTOJobs; llvm::StringRef umbrella; uint32_t ltoo = 2; + llvm::CachePruningPolicy thinLTOCachePolicy; + llvm::StringRef thinLTOCacheDir; bool deadStripDylibs = false; bool demangle = false; bool deadStrip = false; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 98340088a120c..7fcaeac2112d3 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -195,6 +195,35 @@ getFrameworkSearchPaths(InputArgList &args, {"/Library/Frameworks", "/System/Library/Frameworks"}); } +static llvm::CachePruningPolicy getLTOCachePolicy(InputArgList &args) { + SmallString<128> ltoPolicy; + auto add = [<oPolicy](Twine val) { + if (!ltoPolicy.empty()) + ltoPolicy += ":"; + val.toVector(ltoPolicy); + }; + for (const Arg *arg : + args.filtered(OPT_thinlto_cache_policy, OPT_prune_interval_lto, + OPT_prune_after_lto, OPT_max_relative_cache_size_lto)) { + switch (arg->getOption().getID()) { + case OPT_thinlto_cache_policy: add(arg->getValue()); break; + case OPT_prune_interval_lto: + if (!strcmp("-1", arg->getValue())) + add("prune_interval=87600h"); // 10 years + else + add(Twine("prune_interval=") + arg->getValue() + "s"); + break; + case OPT_prune_after_lto: + add(Twine("prune_after=") + arg->getValue() + "s"); + break; + case OPT_max_relative_cache_size_lto: + add(Twine("cache_size=") + arg->getValue() + "%"); + break; + } + } + return CHECK(parseCachePruningPolicy(ltoPolicy), "invalid LTO cache policy"); +} + namespace { struct ArchiveMember { MemoryBufferRef mbref; @@ -548,6 +577,7 @@ static void compileBitcodeFiles() { // any CommonSymbols. static void replaceCommonSymbols() { TimeTraceScope timeScope("Replace common symbols"); + ConcatOutputSection *osec = nullptr; for (Symbol *sym : symtab->getSymbols()) { auto *common = dyn_cast(sym); if (common == nullptr) @@ -560,6 +590,9 @@ static void replaceCommonSymbols() { auto *isec = make( segment_names::data, section_names::common, common->getFile(), data, common->align, S_ZEROFILL); + if (!osec) + osec = ConcatOutputSection::getOrCreateForInput(isec); + isec->parent = osec; inputSections.push_back(isec); // FIXME: CommonSymbol should store isReferencedDynamically, noDeadStrip @@ -1008,6 +1041,7 @@ static void gatherInputSections() { int inputOrder = 0; for (const InputFile *file : inputFiles) { for (const SubsectionMap &map : file->subsections) { + ConcatOutputSection *osec = nullptr; for (const SubsectionEntry &entry : map) { if (auto *isec = dyn_cast(entry.isec)) { if (isec->isCoalescedWeak()) @@ -1018,6 +1052,9 @@ static void gatherInputSections() { continue; } isec->outSecOff = inputOrder++; + if (!osec) + osec = ConcatOutputSection::getOrCreateForInput(isec); + isec->parent = osec; inputSections.push_back(isec); } else if (auto *isec = dyn_cast(entry.isec)) { if (in.cStringSection->inputOrder == UnspecifiedInputOrder) @@ -1141,11 +1178,10 @@ bool macho::link(ArrayRef argsArr, bool canExitEarly, symtab->addDynamicLookup(arg->getValue()); config->mapFile = args.getLastArgValue(OPT_map); + config->optimize = args::getInteger(args, OPT_O, 1); config->outputFile = args.getLastArgValue(OPT_o, "a.out"); - if (const Arg *arg = args.getLastArg(OPT_final_output)) - config->finalOutput = arg->getValue(); - else - config->finalOutput = config->outputFile; + config->finalOutput = + args.getLastArgValue(OPT_final_output, config->outputFile); config->astPaths = args.getAllArgValues(OPT_add_ast_path); config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32); config->headerPadMaxInstallNames = @@ -1173,9 +1209,13 @@ bool macho::link(ArrayRef argsArr, bool canExitEarly, config->ltoo = args::getInteger(args, OPT_lto_O, 2); if (config->ltoo > 3) error("--lto-O: invalid optimization level: " + Twine(config->ltoo)); + config->thinLTOCacheDir = args.getLastArgValue(OPT_cache_path_lto); + config->thinLTOCachePolicy = getLTOCachePolicy(args); config->runtimePaths = args::getStrings(args, OPT_rpath); config->allLoad = args.hasArg(OPT_all_load); config->archMultiple = args.hasArg(OPT_arch_multiple); + config->applicationExtension = args.hasFlag( + OPT_application_extension, OPT_no_application_extension, false); config->exportDynamic = args.hasArg(OPT_export_dynamic); config->forceLoadObjC = args.hasArg(OPT_ObjC); config->forceLoadSwift = args.hasArg(OPT_force_load_swift_libs); diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp index a27a0f5accbd1..9a41bb2caedea 100644 --- a/lld/MachO/ICF.cpp +++ b/lld/MachO/ICF.cpp @@ -52,22 +52,18 @@ ICF::ICF(std::vector &inputs) { // // Summary of segments & sections: // -// Since folding never occurs across output-section boundaries, -// ConcatOutputSection is the natural input for ICF. -// // The __TEXT segment is readonly at the MMU. Some sections are already // deduplicated elsewhere (__TEXT,__cstring & __TEXT,__literal*) and some are // synthetic and inherently free of duplicates (__TEXT,__stubs & -// __TEXT,__unwind_info). We only run ICF on __TEXT,__text. One might hope ICF -// could work on __TEXT,__concat, but doing so induces many test failures. +// __TEXT,__unwind_info). Note that we don't yet run ICF on __TEXT,__const, +// because doing so induces many test failures. // // The __LINKEDIT segment is readonly at the MMU, yet entirely synthetic, and // thus ineligible for ICF. // // The __DATA_CONST segment is read/write at the MMU, but is logically const to -// the application after dyld applies fixups to pointer data. Some sections are -// deduplicated elsewhere (__DATA_CONST,__cfstring), and some are synthetic -// (__DATA_CONST,__got). There are no ICF opportunities here. +// the application after dyld applies fixups to pointer data. We currently +// fold only the __DATA_CONST,__cfstring section. // // The __DATA segment is read/write at the MMU, and as application-writeable // data, none of its sections are eligible for ICF. @@ -84,12 +80,13 @@ static std::atomic icfRepeat{false}; // Compare everything except the relocation referents static bool equalsConstant(const ConcatInputSection *ia, const ConcatInputSection *ib) { + // We can only fold within the same OutputSection. + if (ia->parent != ib->parent) + return false; if (ia->data.size() != ib->data.size()) return false; if (ia->data != ib->data) return false; - if (ia->getFlags() != ib->getFlags()) - return false; if (ia->relocs.size() != ib->relocs.size()) return false; auto f = [&](const Reloc &ra, const Reloc &rb) { @@ -323,8 +320,6 @@ void macho::foldIdenticalSections() { // relocs to find every referenced InputSection, but that precludes easy // parallelization. Therefore, we hash every InputSection here where we have // them all accessible as simple vectors. - std::vector codeSections; - std::vector cfStringSections; // ICF can't fold functions with unwind info DenseSet functionsWithUnwindInfo = @@ -338,32 +333,22 @@ void macho::foldIdenticalSections() { // coexist with equivalence-class IDs, this is not necessary, but might help // someone keep the numbers straight in case we ever need to debug the // ICF::segregate() + std::vector hashable; uint64_t icfUniqueID = inputSections.size(); for (ConcatInputSection *isec : inputSections) { + // FIXME: consider non-code __text sections as hashable? bool isHashable = (isCodeSection(isec) || isCfStringSection(isec)) && !isec->shouldOmitFromOutput() && !functionsWithUnwindInfo.contains(isec) && isec->isHashableForICF(); - if (isHashable) { - if (isCodeSection(isec)) - codeSections.push_back(isec); - else { - assert(isCfStringSection(isec)); - cfStringSections.push_back(isec); - } - } else { + if (isHashable) + hashable.push_back(isec); + else isec->icfEqClass[0] = ++icfUniqueID; - } } - std::vector hashable(codeSections); - hashable.insert(hashable.end(), cfStringSections.begin(), - cfStringSections.end()); parallelForEach(hashable, [](ConcatInputSection *isec) { isec->hashForICF(); }); // Now that every input section is either hashed or marked as unique, run the // segregation algorithm to detect foldable subsections. - // We dedup cfStringSections first since code sections may refer to them, but - // not vice-versa. - ICF(cfStringSections).run(); - ICF(codeSections).run(); + ICF(hashable).run(); } diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index 89f768a61e663..8f5df2529002a 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -954,6 +954,8 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella, if (!checkCompatibility(this)) return; + checkAppExtensionSafety(hdr->flags & MH_APP_EXTENSION_SAFE); + for (auto *cmd : findCommands(hdr, LC_RPATH)) { StringRef rpath{reinterpret_cast(cmd) + cmd->path}; rpaths.push_back(rpath); @@ -1043,6 +1045,8 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella, return; } + checkAppExtensionSafety(interface.isApplicationExtensionSafe()); + exportingFile = isImplicitlyLinked(installName) ? this : umbrella; auto addSymbol = [&](const Twine &name) -> void { symbols.push_back(symtab->addDylib(saver.save(name), exportingFile, @@ -1171,6 +1175,11 @@ void DylibFile::handleLDInstallNameSymbol(StringRef name, this->installName = saver.save(installName); } +void DylibFile::checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const { + if (config->applicationExtension && !dylibIsAppExtensionSafe) + warn("using '-application_extension' with unsafe dylib: " + toString(this)); +} + ArchiveFile::ArchiveFile(std::unique_ptr &&f) : InputFile(ArchiveKind, f->getMemoryBufferRef()), file(std::move(f)) { for (const object::Archive::Symbol &sym : file->symbols()) diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h index df8e006a5ccd0..3bf9e77cf95a4 100644 --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -177,6 +177,7 @@ class DylibFile final : public InputFile { bool handleLDSymbol(StringRef originalName); void handleLDPreviousSymbol(StringRef name, StringRef originalName); void handleLDInstallNameSymbol(StringRef name, StringRef originalName); + void checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const; }; // .a file diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp index 5762e4ef59f0e..b28bfc1fb4cfe 100644 --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "InputSection.h" +#include "ConcatOutputSection.h" #include "Config.h" #include "InputFiles.h" #include "OutputSegment.h" diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp index 061cda9c1054a..366193a27eba1 100644 --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -17,6 +17,8 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" #include "lld/Common/TargetOptionsCommandFlags.h" +#include "llvm/LTO/Caching.h" +#include "llvm/LTO/Config.h" #include "llvm/LTO/LTO.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -97,11 +99,28 @@ void BitcodeCompiler::add(BitcodeFile &f) { std::vector BitcodeCompiler::compile() { unsigned maxTasks = ltoObj->getMaxTasks(); buf.resize(maxTasks); - - checkError(ltoObj->run([&](size_t task) { - return std::make_unique( - std::make_unique(buf[task])); - })); + files.resize(maxTasks); + + // The -cache_path_lto option specifies the path to a directory in which + // to cache native object files for ThinLTO incremental builds. If a path was + // specified, configure LTO to use it as the cache directory. + lto::NativeObjectCache cache; + if (!config->thinLTOCacheDir.empty()) + cache = check( + lto::localCache(config->thinLTOCacheDir, + [&](size_t task, std::unique_ptr mb) { + files[task] = std::move(mb); + })); + + checkError(ltoObj->run( + [&](size_t task) { + return std::make_unique( + std::make_unique(buf[task])); + }, + cache)); + + if (!config->thinLTOCacheDir.empty()) + pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy); if (config->saveTemps) { if (!buf[0].empty()) @@ -130,6 +149,8 @@ std::vector BitcodeCompiler::compile() { ret.push_back(make( MemoryBufferRef(buf[i], saver.save(filePath.str())), modTime, "")); } - + for (std::unique_ptr &file : files) + if (file) + ret.push_back(make(*file, 0, "")); return ret; } diff --git a/lld/MachO/LTO.h b/lld/MachO/LTO.h index 2577374590b7f..d64016fb588c2 100644 --- a/lld/MachO/LTO.h +++ b/lld/MachO/LTO.h @@ -10,6 +10,7 @@ #define LLD_MACHO_LTO_H #include "llvm/ADT/SmallString.h" +#include "llvm/Support/MemoryBuffer.h" #include #include @@ -35,6 +36,7 @@ class BitcodeCompiler { private: std::unique_ptr ltoObj; std::vector> buf; + std::vector> files; }; } // namespace macho diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td index b351645cedd66..cda857d605bd4 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -68,6 +68,11 @@ def lto_O: Joined<["--"], "lto-O">, HelpText<"Set optimization level for LTO (default: 2)">, MetaVarName<"">, Group; +def thinlto_cache_policy: Joined<["--"], "thinlto-cache-policy=">, + HelpText<"Pruning policy for the ThinLTO cache">, + Group; +def O : JoinedOrSeparate<["-"], "O">, + HelpText<"Optimize output file size">; // This is a complete Options.td compiled from Apple's ld(1) manpage // dated 2018-03-07 and cross checked with ld64 source code in repo @@ -689,12 +694,10 @@ def allow_heap_execute : Flag<["-"], "allow_heap_execute">, Flags<[HelpHidden]>, Group; def application_extension : Flag<["-"], "application_extension">, - HelpText<"Designate the linker output as safe for use in an application extension">, - Flags<[HelpHidden]>, + HelpText<"Mark output as safe for use in an application extension, and validate that linked dylibs are safe">, Group; def no_application_extension : Flag<["-"], "no_application_extension">, - HelpText<"Designate the linker output as unsafe for use in an application extension">, - Flags<[HelpHidden]>, + HelpText<"Disable application extension functionality (default)">, Group; def fatal_warnings : Flag<["-"], "fatal_warnings">, HelpText<"Treat warnings as errors">, @@ -917,22 +920,18 @@ def object_path_lto : Separate<["-"], "object_path_lto">, def cache_path_lto : Separate<["-"], "cache_path_lto">, MetaVarName<"">, HelpText<"Use as a directory for the incremental LTO cache">, - Flags<[HelpHidden]>, Group; def prune_interval_lto : Separate<["-"], "prune_interval_lto">, MetaVarName<"">, HelpText<"Prune the incremental LTO cache after (-1 disables pruning)">, - Flags<[HelpHidden]>, Group; def prune_after_lto : Separate<["-"], "prune_after_lto">, MetaVarName<"">, HelpText<"Remove LTO cache entries after ">, - Flags<[HelpHidden]>, Group; def max_relative_cache_size_lto : Separate<["-"], "max_relative_cache_size_lto">, MetaVarName<"">, HelpText<"Limit the incremental LTO cache growth to of free disk, space">, - Flags<[HelpHidden]>, Group; def page_align_data_atoms : Flag<["-"], "page_align_data_atoms">, HelpText<"Distribute global variables on separate pages so page used/dirty status can guide creation of an order file to cluster commonly used/dirty globals">, diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 12c62554c2437..d65cc9c3ced2f 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -15,7 +15,6 @@ #include "OutputSegment.h" #include "SymbolTable.h" #include "Symbols.h" -#include "Writer.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" @@ -113,6 +112,9 @@ void MachHeaderSection::writeTo(uint8_t *buf) const { if (config->outputType == MH_EXECUTE && config->isPic) hdr->flags |= MH_PIE; + if (config->outputType == MH_DYLIB && config->applicationExtension) + hdr->flags |= MH_APP_EXTENSION_SAFE; + if (in.exports->hasWeakSymbol || in.weakBinding->hasNonWeakDefinition()) hdr->flags |= MH_WEAK_DEFINES; @@ -274,6 +276,13 @@ struct Binding { uint64_t offset = 0; int64_t addend = 0; }; +struct BindIR { + // Default value of 0xF0 is not valid opcode and should make the program + // scream instead of accidentally writing "valid" values. + uint8_t opcode = 0xF0; + uint64_t data = 0; + uint64_t consecutiveCount = 0; +}; } // namespace // Encode a sequence of opcodes that tell dyld to write the address of symbol + @@ -284,32 +293,101 @@ struct Binding { // lastBinding. static void encodeBinding(const OutputSection *osec, uint64_t outSecOff, int64_t addend, Binding &lastBinding, - raw_svector_ostream &os) { + std::vector &opcodes) { OutputSegment *seg = osec->parent; uint64_t offset = osec->getSegmentOffset() + outSecOff; if (lastBinding.segment != seg) { - os << static_cast(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | - seg->index); - encodeULEB128(offset, os); + opcodes.push_back( + {static_cast(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | + seg->index), + offset}); lastBinding.segment = seg; lastBinding.offset = offset; } else if (lastBinding.offset != offset) { - os << static_cast(BIND_OPCODE_ADD_ADDR_ULEB); - encodeULEB128(offset - lastBinding.offset, os); + opcodes.push_back({BIND_OPCODE_ADD_ADDR_ULEB, offset - lastBinding.offset}); lastBinding.offset = offset; } if (lastBinding.addend != addend) { - os << static_cast(BIND_OPCODE_SET_ADDEND_SLEB); - encodeSLEB128(addend, os); + opcodes.push_back( + {BIND_OPCODE_SET_ADDEND_SLEB, static_cast(addend)}); lastBinding.addend = addend; } - os << static_cast(BIND_OPCODE_DO_BIND); + opcodes.push_back({BIND_OPCODE_DO_BIND, 0}); // DO_BIND causes dyld to both perform the binding and increment the offset lastBinding.offset += target->wordSize; } +static void optimizeOpcodes(std::vector &opcodes) { + // Pass 1: Combine bind/add pairs + size_t i; + int pWrite = 0; + for (i = 1; i < opcodes.size(); ++i, ++pWrite) { + if ((opcodes[i].opcode == BIND_OPCODE_ADD_ADDR_ULEB) && + (opcodes[i - 1].opcode == BIND_OPCODE_DO_BIND)) { + opcodes[pWrite].opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB; + opcodes[pWrite].data = opcodes[i].data; + ++i; + } else { + opcodes[pWrite] = opcodes[i - 1]; + } + } + if (i == opcodes.size()) + opcodes[pWrite] = opcodes[i - 1]; + opcodes.resize(pWrite + 1); + + // Pass 2: Compress two or more bind_add opcodes + pWrite = 0; + for (i = 1; i < opcodes.size(); ++i, ++pWrite) { + if ((opcodes[i].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) && + (opcodes[i - 1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) && + (opcodes[i].data == opcodes[i - 1].data)) { + opcodes[pWrite].opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB; + opcodes[pWrite].consecutiveCount = 2; + opcodes[pWrite].data = opcodes[i].data; + ++i; + while (i < opcodes.size() && + (opcodes[i].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) && + (opcodes[i].data == opcodes[i - 1].data)) { + opcodes[pWrite].consecutiveCount++; + ++i; + } + } else { + opcodes[pWrite] = opcodes[i - 1]; + } + } + if (i == opcodes.size()) + opcodes[pWrite] = opcodes[i - 1]; + opcodes.resize(pWrite + 1); +} + +static void flushOpcodes(const BindIR &op, raw_svector_ostream &os) { + uint8_t opcode = op.opcode & BIND_OPCODE_MASK; + switch (opcode) { + case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + case BIND_OPCODE_ADD_ADDR_ULEB: + case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + os << op.opcode; + encodeULEB128(op.data, os); + break; + case BIND_OPCODE_SET_ADDEND_SLEB: + os << op.opcode; + encodeSLEB128(static_cast(op.data), os); + break; + case BIND_OPCODE_DO_BIND: + os << op.opcode; + break; + case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + os << op.opcode; + encodeULEB128(op.consecutiveCount, os); + encodeULEB128(op.data, os); + break; + default: + llvm_unreachable("cannot bind to an unrecognized symbol"); + } +} + // Non-weak bindings need to have their dylib ordinal encoded as well. static int16_t ordinalForDylibSymbol(const DylibSymbol &dysym) { if (config->namespaceKind == NamespaceKind::flat || dysym.isDynamicLookup()) @@ -389,9 +467,6 @@ void BindingSection::finalizeContents() { for (auto &p : sortBindings(bindingsMap)) { const DylibSymbol *sym = p.first; std::vector &bindings = p.second; - llvm::sort(bindings, [](const BindingEntry &a, const BindingEntry &b) { - return a.target.getVA() < b.target.getVA(); - }); uint8_t flags = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM; if (sym->isWeakRef()) flags |= BIND_SYMBOL_FLAGS_WEAK_IMPORT; @@ -402,10 +477,15 @@ void BindingSection::finalizeContents() { encodeDylibOrdinal(ordinal, os); lastOrdinal = ordinal; } + std::vector opcodes; for (const BindingEntry &b : bindings) encodeBinding(b.target.isec->parent, b.target.isec->getOffset(b.target.offset), b.addend, - lastBinding, os); + lastBinding, opcodes); + if (config->optimize > 1) + optimizeOpcodes(opcodes); + for (const auto &op : opcodes) + flushOpcodes(op, os); } if (!bindingsMap.empty()) os << static_cast(BIND_OPCODE_DONE); @@ -431,10 +511,15 @@ void WeakBindingSection::finalizeContents() { os << static_cast(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM) << sym->getName() << '\0' << static_cast(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER); + std::vector opcodes; for (const BindingEntry &b : bindings) encodeBinding(b.target.isec->parent, b.target.isec->getOffset(b.target.offset), b.addend, - lastBinding, os); + lastBinding, opcodes); + if (config->optimize > 1) + optimizeOpcodes(opcodes); + for (const auto &op : opcodes) + flushOpcodes(op, os); } if (!bindingsMap.empty() || !definitions.empty()) os << static_cast(BIND_OPCODE_DONE); @@ -510,6 +595,8 @@ void StubHelperSection::setup() { in.got->addEntry(stubBinder); + in.imageLoaderCache->parent = + ConcatOutputSection::getOrCreateForInput(in.imageLoaderCache); inputSections.push_back(in.imageLoaderCache); // Since this isn't in the symbol table or in any input file, the noDeadStrip // argument doesn't matter. It's kept alive by ImageLoaderCacheSection() diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index 162e69e6fe245..bbb7adc37cb35 100644 --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -15,6 +15,7 @@ #include "OutputSection.h" #include "OutputSegment.h" #include "Target.h" +#include "Writer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp index ea94c8dea9ac3..3efc646c2ad26 100644 --- a/lld/MachO/UnwindInfoSection.cpp +++ b/lld/MachO/UnwindInfoSection.cpp @@ -144,6 +144,7 @@ template void UnwindInfoSectionImpl::addInput(ConcatInputSection *isec) { assert(isec->getSegName() == segment_names::ld && isec->getName() == section_names::compactUnwind); + isec->parent = compactUnwindSection; compactUnwindSection->addInput(isec); } diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index f311a64bc1fa2..8686f111db27c 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -76,10 +76,6 @@ class Writer { LCUuid *uuidCommand = nullptr; OutputSegment *linkEditSegment = nullptr; - - // Output sections are added to output segments in iteration order - // of ConcatOutputSection, so must have deterministic iteration order. - MapVector concatOutputSections; }; // LC_DYLD_INFO_ONLY stores the offsets of symbol import/export information. @@ -879,16 +875,6 @@ static void sortSegmentsAndSections() { } } -NamePair macho::maybeRenameSection(NamePair key) { - auto newNames = config->sectionRenameMap.find(key); - if (newNames != config->sectionRenameMap.end()) - return newNames->second; - auto newName = config->segmentRenameMap.find(key.first); - if (newName != config->segmentRenameMap.end()) - return std::make_pair(newName->second, key.second); - return key; -} - template void Writer::createOutputSections() { TimeTraceScope timeScope("Create output sections"); // First, create hidden sections @@ -919,10 +905,7 @@ template void Writer::createOutputSections() { for (ConcatInputSection *isec : inputSections) { if (isec->shouldOmitFromOutput()) continue; - NamePair names = maybeRenameSection({isec->getSegName(), isec->getName()}); - ConcatOutputSection *&osec = concatOutputSections[names]; - if (!osec) - osec = make(names.second); + ConcatOutputSection *osec = cast(isec->parent); osec->addInput(isec); osec->inputOrder = std::min(osec->inputOrder, static_cast(isec->outSecOff)); @@ -934,7 +917,8 @@ template void Writer::createOutputSections() { StringRef segname = it.first.first; ConcatOutputSection *osec = it.second; assert(segname != segment_names::ld); - getOrCreateOutputSegment(segname)->addOutputSection(osec); + if (osec->isNeeded()) + getOrCreateOutputSegment(segname)->addOutputSection(osec); } for (SyntheticSection *ssec : syntheticSections) { diff --git a/lld/MachO/Writer.h b/lld/MachO/Writer.h index 2a6cc63d5b82d..56f6f7ae6fe76 100644 --- a/lld/MachO/Writer.h +++ b/lld/MachO/Writer.h @@ -9,8 +9,6 @@ #ifndef LLD_MACHO_WRITER_H #define LLD_MACHO_WRITER_H -#include "Config.h" - #include namespace lld { @@ -29,8 +27,6 @@ class LoadCommand { template void writeResult(); -NamePair maybeRenameSection(NamePair key); - void createSyntheticSections(); // Add bindings for symbols that need weak or non-lazy bindings. diff --git a/lld/test/COFF/resource-objs.test b/lld/test/COFF/resource-objs.test index d28cc14d81796..08fc503d3141a 100644 --- a/lld/test/COFF/resource-objs.test +++ b/lld/test/COFF/resource-objs.test @@ -1,5 +1,5 @@ # RUN: lld-link /out:%t.exe /dll /noentry %S/Inputs/id.res.o -# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s +# RUN: llvm-readobj --file-header %t.exe | FileCheck %s CHECK: ResourceTableRVA: 0x1000 CHECK: ResourceTableSize: 0x80 diff --git a/lld/test/COFF/secidx-absolute.s b/lld/test/COFF/secidx-absolute.s index 8befaf2f456c3..7d3b4b27fc4bb 100644 --- a/lld/test/COFF/secidx-absolute.s +++ b/lld/test/COFF/secidx-absolute.s @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj # RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -# RUN: llvm-readobj %t.exe -sections -section-data | FileCheck %s +# RUN: llvm-readobj %t.exe --sections --section-data | FileCheck %s # Section relocations against absolute symbols resolve to the last real output # section index plus one. diff --git a/lld/test/COFF/secrel-common.s b/lld/test/COFF/secrel-common.s index 0d3aafcad001e..6155634b32aa2 100644 --- a/lld/test/COFF/secrel-common.s +++ b/lld/test/COFF/secrel-common.s @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj # RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -# RUN: llvm-readobj %t.exe -sections -section-data | FileCheck %s +# RUN: llvm-readobj %t.exe --sections --section-data | FileCheck %s # Section relocations against common symbols resolve to .bss (merged into .data). diff --git a/lld/test/ELF/amdgpu-relocs2.s b/lld/test/ELF/amdgpu-relocs2.s new file mode 100644 index 0000000000000..12099b8eda3eb --- /dev/null +++ b/lld/test/ELF/amdgpu-relocs2.s @@ -0,0 +1,38 @@ +# REQUIRES: amdgpu +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=amdgcn--amdhsa -mcpu=fiji %t/asm -o %t.o +# RUN: ld.lld %t.o -o %t/out --script %t/script +# RUN: llvm-objdump -d %t/out | FileCheck %s + + +#--- script +SECTIONS { + . = 0x1000; + .text.likely : { *(.text.likely) } + . = 0x2000; + .text : { *(.text) } + . = 0x3000; + .text.unlikely : { *(.text.unlikely) } +} + + +#--- asm +.section .text.likely +hot1: + s_add_i32 s15, s15, 1 +hot2: + s_add_i32 s13, s13, 1 +.text +foo: + s_branch cold2 + s_branch hot2 +.section .text.unlikely +cold1: + s_add_i32 s15, s15, 1 + s_add_i32 s14, s14, 1 +cold2: + s_add_i32 s13, s13, 1 + +# CHECK: +# CHECK-NEXT: s_branch 1025 +# CHECK-NEXT: s_branch 64511 diff --git a/lld/test/ELF/arm-v4bx.test b/lld/test/ELF/arm-v4bx.test index 109f975c95d3c..ff46727245a48 100644 --- a/lld/test/ELF/arm-v4bx.test +++ b/lld/test/ELF/arm-v4bx.test @@ -1,9 +1,9 @@ # REQUIRES: arm # RUN: yaml2obj %s -o %t.o # RUN: ld.lld %t.o -o %t -# RUN: llvm-readelf -sections %t | FileCheck %s +# RUN: llvm-readelf -S %t | FileCheck %s # RUN: ld.lld -shared %t.o -o %t -# RUN: llvm-readelf -sections %t | FileCheck %s +# RUN: llvm-readelf -S %t | FileCheck %s # CHECK: .text diff --git a/lld/test/ELF/as-needed-weak.s b/lld/test/ELF/as-needed-weak.s index 1c38fd2abf2b9..b2ff374e345aa 100644 --- a/lld/test/ELF/as-needed-weak.s +++ b/lld/test/ELF/as-needed-weak.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o # RUN: ld.lld -o %t.exe %t2.o --as-needed %t1.so -# RUN: llvm-readelf -dynamic-table -dyn-symbols %t.exe | FileCheck %s +# RUN: llvm-readelf -d --dyn-syms %t.exe | FileCheck %s # CHECK-NOT: libfoo diff --git a/lld/test/ELF/cgprofile-rela.test b/lld/test/ELF/cgprofile-rela.test new file mode 100644 index 0000000000000..189f169e65481 --- /dev/null +++ b/lld/test/ELF/cgprofile-rela.test @@ -0,0 +1,117 @@ +## Under some circumstances, GNU tools strip/objcopy change REL to RELA. https://sourceware.org/bugzilla/show_bug.cgi?id=28035 +## Test that LLD can handle call graph profile data relocated with RELA relocations. +# REQUIRES: x86 + +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-nm --no-sort %t | FileCheck %s +# RUN: ld.lld --no-call-graph-profile-sort %t.o -o %t +# RUN: llvm-nm --no-sort %t | FileCheck %s --check-prefix=NO-CG + +# CHECK: 0000000000201124 t D +# CHECK: 0000000000201122 t C +# CHECK: 0000000000201128 t B +# CHECK: 0000000000201120 t A +# CHECK: 0000000000201126 T _start + +# NO-CG: 0000000000201120 t D +# NO-CG: 0000000000201122 t C +# NO-CG: 0000000000201124 t B +# NO-CG: 0000000000201126 t A +# NO-CG: 0000000000201128 T _start + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text.D + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 2 + - Name: .text.C + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 2 + - Name: .text.B + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 2 + - Name: .text.A + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 2 + - Name: .text._start + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 2 + - Name: .llvm.call-graph-profile + Type: SHT_LLVM_CALL_GRAPH_PROFILE + Flags: [ SHF_EXCLUDE ] + Link: .symtab + AddressAlign: 0x1 + Entries: + - Weight: 10 + - Weight: 10 + - Weight: 80 + - Weight: 40 + - Weight: 30 + - Weight: 90 + - Name: .rela.llvm.call-graph-profile + Type: SHT_RELA + Info: .llvm.call-graph-profile + Relocations: + - Offset: 0x0 + Symbol: A + Type: R_X86_64_NONE + - Offset: 0x0 + Symbol: B + Type: R_X86_64_NONE + - Offset: 0x8 + Symbol: A + Type: R_X86_64_NONE + - Offset: 0x8 + Symbol: B + Type: R_X86_64_NONE + - Offset: 0x10 + Symbol: _start + Type: R_X86_64_NONE + - Offset: 0x10 + Symbol: B + Type: R_X86_64_NONE + - Offset: 0x18 + Symbol: A + Type: R_X86_64_NONE + - Offset: 0x18 + Symbol: C + Type: R_X86_64_NONE + - Offset: 0x20 + Symbol: B + Type: R_X86_64_NONE + - Offset: 0x20 + Symbol: C + Type: R_X86_64_NONE + - Offset: 0x28 + Symbol: C + Type: R_X86_64_NONE + - Offset: 0x28 + Symbol: D + Type: R_X86_64_NONE +Symbols: + - Name: D + Type: STT_FUNC + Section: .text.D + - Name: C + Type: STT_FUNC + Section: .text.C + - Name: B + Type: STT_FUNC + Section: .text.B + - Name: A + Type: STT_FUNC + Section: .text.A + - Name: _start + Binding: STB_GLOBAL + Section: .text._start diff --git a/lld/test/ELF/common-archive-lookup.s b/lld/test/ELF/common-archive-lookup.s index efaad669b7243..bbfadb448f2d6 100644 --- a/lld/test/ELF/common-archive-lookup.s +++ b/lld/test/ELF/common-archive-lookup.s @@ -20,6 +20,7 @@ ## Bitcode files. # RUN: llvm-as -o 1.bc commonblock.ll # RUN: llvm-as -o 2.bc blockdata.ll +# RUN: llvm-as -o 3.bc weak.ll ## Bitcode archive. # RUN: llvm-ar crs 4.a 1.bc 2.bc @@ -31,10 +32,10 @@ # RUN: llvm-objdump -D -j .data 2 | FileCheck --check-prefix=TEST1 %s # RUN: ld.lld -o 3 main.o 2.a -# RUN: llvm-objdump -D -j .data 3 | FileCheck --check-prefix=TEST1 %s +# RUN: llvm-objdump -t 3 | FileCheck --check-prefix=BSS %s # RUN: ld.lld -o 4 main.o --start-lib 1.o weak_data_only.o --end-lib -# RUN: llvm-objdump -D -j .data 4 | FileCheck --check-prefix=TEST1 %s +# RUN: llvm-objdump -t 4 | FileCheck --check-prefix=BSS %s # RUN: ld.lld -o 5 main.o 3.a --print-map | FileCheck --check-prefix=MAP %s @@ -63,6 +64,9 @@ # RUN: ld.lld -o - main.o --start-lib 1.bc 2.bc --end-lib --lto-emit-asm | \ # RUN: FileCheck --check-prefix=ASM %s +## COMMON overrides weak. Don't extract 3.bc which provides a weak definition. +# RUN: ld.lld -o /dev/null main.o --start-lib 1.bc 3.bc --end-lib -y block | FileCheck --check-prefix=LTO_WEAK %s + ## Old FORTRAN that mixes use of COMMON blocks and BLOCK DATA requires that we ## search through archives for non-tentative definitions (from the BLOCK DATA) ## to replace the tentative definitions (from the COMMON block(s)). @@ -75,6 +79,7 @@ # TEST1-NEXT: fb 21 09 40 # TEST1-NEXT: ... +# BSS: [[#%x,]] g O .bss 0000000000000028 block # NFC: Name: block # NFC-NEXT: Value: @@ -100,6 +105,10 @@ # ASM-NEXT: .long 5 # ASM: .size block, 20 +# LTO_WEAK: 1.bc: common definition of block +# LTO_WEAK: : reference to block +# LTO_WEAK-NOT: {{.}} + #--- ref.s .text .abiversion 2 @@ -167,6 +176,12 @@ target triple = "powerpc64le-unknown-linux-gnu" @block = dso_local local_unnamed_addr global [5 x i32] [i32 5, i32 0, i32 0, i32 0, i32 0], align 4 +#--- weak.ll +target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" +target triple = "powerpc64le-unknown-linux-gnu" + +@block = weak dso_local global [5 x i32] [i32 5, i32 0, i32 0, i32 0, i32 0], align 4 + #--- commonblock.ll target datalayout = "e-m:e-i64:64-n32:64-S128-v256:256:256-v512:512:512" target triple = "powerpc64le-unknown-linux-gnu" diff --git a/lld/test/ELF/dynamic-list-archive.s b/lld/test/ELF/dynamic-list-archive.s index 5879bf1b0a575..f690dccb58699 100644 --- a/lld/test/ELF/dynamic-list-archive.s +++ b/lld/test/ELF/dynamic-list-archive.s @@ -9,7 +9,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o # RUN: ld.lld -shared -o %t.so --dynamic-list %t.list %t.a %t2.o -# RUN: llvm-readelf -dyn-symbols %t.so | FileCheck %s +# RUN: llvm-readelf --dyn-syms %t.so | FileCheck %s # CHECK-NOT: foo .global _start diff --git a/lld/test/ELF/gdb-index.s b/lld/test/ELF/gdb-index.s index 54a01a2c0d514..2b59956ed8b7a 100644 --- a/lld/test/ELF/gdb-index.s +++ b/lld/test/ELF/gdb-index.s @@ -20,7 +20,7 @@ # RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s --check-prefix=DWARF -# RUN: llvm-readelf -sections %t | FileCheck %s --check-prefix=SECTION +# RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SECTION # DISASM: Disassembly of section .text: # DISASM-EMPTY: diff --git a/lld/test/ELF/gnu-ifunc-dynsym.s b/lld/test/ELF/gnu-ifunc-dynsym.s deleted file mode 100644 index 3d98ac3a4cfc1..0000000000000 --- a/lld/test/ELF/gnu-ifunc-dynsym.s +++ /dev/null @@ -1,23 +0,0 @@ -// REQUIRES: x86 -// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o - -// RUN: ld.lld -static -export-dynamic %t.o -o %tout -// RUN: llvm-nm -U %tout | FileCheck %s - -// RUN: ld.lld -export-dynamic %t.o -o %tout -// RUN: llvm-nm -U %tout | FileCheck %s - -// CHECK: __rela_iplt_end -// CHECK: __rela_iplt_start - -.text -.type foo STT_GNU_IFUNC -.globl foo -foo: - ret - -.globl _start -_start: - call foo - movl $__rela_iplt_start,%edx - movl $__rela_iplt_end,%edx diff --git a/lld/test/ELF/gnu-ifunc-nonpreemptible.s b/lld/test/ELF/gnu-ifunc-nonpreemptible.s new file mode 100644 index 0000000000000..dcc4f5d8c7903 --- /dev/null +++ b/lld/test/ELF/gnu-ifunc-nonpreemptible.s @@ -0,0 +1,67 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM +# RUN: llvm-readelf -r -s %t | FileCheck %s + +# RUN: ld.lld --export-dynamic %t.o -o %t +# RUN: llvm-readelf -r -s %t | FileCheck %s + +# CHECK: Relocation section '.rela.dyn' at offset {{.*}} contains 2 entries: +# CHECK-NEXT: Type +# CHECK-NEXT: R_X86_64_IRELATIVE +# CHECK-NEXT: R_X86_64_IRELATIVE + +# CHECK: 0 NOTYPE LOCAL HIDDEN [[#]] __rela_iplt_start +# CHECK-NEXT: 0 NOTYPE LOCAL HIDDEN [[#]] __rela_iplt_end + +# RUN: ld.lld -pie %t.o -o %t1 +# RUN: llvm-readelf -s %t1 | FileCheck %s --check-prefix=PIC +# RUN: ld.lld -shared %t.o -o %t2 +# RUN: llvm-readelf -s %t2 | FileCheck %s --check-prefix=PIC + +# PIC: 0 NOTYPE WEAK DEFAULT UND __rela_iplt_start +# PIC-NEXT: 0 NOTYPE WEAK DEFAULT UND __rela_iplt_end + +# DISASM: Disassembly of section .text: +# DISASM-EMPTY: +# DISASM-NEXT: : +# DISASM-NEXT: 201188: {{.*}} retq +# DISASM: : +# DISASM-NEXT: 201189: {{.*}} retq +# DISASM: <_start>: +# DISASM-NEXT: 20118a: {{.*}} callq 0x2011a0 +# DISASM-NEXT: 20118f: {{.*}} callq 0x2011b0 +# DISASM-EMPTY: +# DISASM-NEXT: Disassembly of section .iplt: +# DISASM-EMPTY: +# DISASM-NEXT: <.iplt>: +# DISASM-NEXT: 2011a0: {{.*}} jmpq *{{.*}}(%rip) # 0x2021d0 +# DISASM-NEXT: 2011a6: {{.*}} pushq $0 +# DISASM-NEXT: 2011ab: {{.*}} jmp 0x0 +# DISASM-NEXT: 2011b0: {{.*}} jmpq *{{.*}}(%rip) # 0x2021d8 +# DISASM-NEXT: 2011b6: {{.*}} pushq $1 +# DISASM-NEXT: 2011bb: {{.*}} jmp 0x0 + +.text +.type foo STT_GNU_IFUNC +.globl foo +foo: + ret + +.type bar STT_GNU_IFUNC +.globl bar +bar: + ret + +.weak __rela_iplt_start +.weak __rela_iplt_end + +.globl _start +_start: + call foo + call bar + +.data + .quad __rela_iplt_start + .quad __rela_iplt_end diff --git a/lld/test/ELF/gnu-ifunc.s b/lld/test/ELF/gnu-ifunc.s deleted file mode 100644 index 49ba69a88be23..0000000000000 --- a/lld/test/ELF/gnu-ifunc.s +++ /dev/null @@ -1,133 +0,0 @@ -// REQUIRES: x86 -// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -// RUN: ld.lld -static %t.o -o %tout -// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM -// RUN: llvm-readobj -r --symbols --sections %tout | FileCheck %s - -// CHECK: Sections [ -// CHECK: Section { -// CHECK: Index: 1 -// CHECK-NEXT: Name: .rela.dyn -// CHECK-NEXT: Type: SHT_RELA -// CHECK-NEXT: Flags [ -// CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_INFO_LINK -// CHECK-NEXT: ] -// CHECK-NEXT: Address: [[RELA:.*]] -// CHECK-NEXT: Offset: 0x158 -// CHECK-NEXT: Size: 48 -// CHECK-NEXT: Link: 0 -// CHECK-NEXT: Info: [[GOTPLT:.*]] -// CHECK-NEXT: AddressAlignment: 8 -// CHECK-NEXT: EntrySize: 24 -// CHECK-NEXT: } -// CHECK: Index: [[GOTPLT]] -// CHECK-NEXT: Name: .got.plt -// CHECK: Relocations [ -// CHECK-NEXT: Section ({{.*}}) .rela.dyn { -// CHECK-NEXT: 0x2021D0 R_X86_64_IRELATIVE -// CHECK-NEXT: 0x2021D8 R_X86_64_IRELATIVE -// CHECK-NEXT: } -// CHECK-NEXT: ] -// CHECK: Symbols [ -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: -// CHECK-NEXT: Value: 0x0 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: Undefined -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: __rela_iplt_start -// CHECK-NEXT: Value: [[RELA]] -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other [ -// CHECK-NEXT: STV_HIDDEN -// CHECK-NEXT: ] -// CHECK-NEXT: Section: .rela.dyn -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: __rela_iplt_end -// CHECK-NEXT: Value: 0x200188 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other [ -// CHECK-NEXT: STV_HIDDEN -// CHECK-NEXT: ] -// CHECK-NEXT: Section: .rela.dyn -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: foo -// CHECK-NEXT: Value: 0x201188 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: GNU_IFunc -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .text -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: bar -// CHECK-NEXT: Value: 0x201189 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: GNU_IFunc -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .text -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: _start -// CHECK-NEXT: Value: 0x20118A -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .text -// CHECK-NEXT: } -// CHECK-NEXT: ] - -// DISASM: Disassembly of section .text: -// DISASM-EMPTY: -// DISASM-NEXT: : -// DISASM-NEXT: 201188: {{.*}} retq -// DISASM: : -// DISASM-NEXT: 201189: {{.*}} retq -// DISASM: <_start>: -// DISASM-NEXT: 20118a: {{.*}} callq 0x2011b0 -// DISASM-NEXT: 20118f: {{.*}} callq 0x2011c0 -// DISASM-NEXT: 201194: {{.*}} movl $2097496, %edx -// DISASM-NEXT: 201199: {{.*}} movl $2097544, %edx -// DISASM-NEXT: 20119e: {{.*}} movl $2097545, %edx -// DISASM-EMPTY: -// DISASM-NEXT: Disassembly of section .iplt: -// DISASM-EMPTY: -// DISASM-NEXT: <.iplt>: -// DISASM-NEXT: 2011b0: {{.*}} jmpq *4122(%rip) -// DISASM-NEXT: 2011b6: {{.*}} pushq $0 -// DISASM-NEXT: 2011bb: {{.*}} jmp 0x0 -// DISASM-NEXT: 2011c0: {{.*}} jmpq *4114(%rip) -// DISASM-NEXT: 2011c6: {{.*}} pushq $1 -// DISASM-NEXT: 2011cb: {{.*}} jmp 0x0 - -.text -.type foo STT_GNU_IFUNC -.globl foo -foo: - ret - -.type bar STT_GNU_IFUNC -.globl bar -bar: - ret - -.globl _start -_start: - call foo - call bar - movl $__rela_iplt_start,%edx - movl $__rela_iplt_end,%edx - movl $__rela_iplt_end + 1,%edx diff --git a/lld/test/ELF/just-symbols.s b/lld/test/ELF/just-symbols.s index 612243de29c0b..974358a00709c 100644 --- a/lld/test/ELF/just-symbols.s +++ b/lld/test/ELF/just-symbols.s @@ -4,7 +4,7 @@ # RUN: ld.lld %t.o -o %t1.exe -Ttext=0x10000 # RUN: ld.lld -just-symbols=%t1.exe -o %t2.exe -# RUN: llvm-readelf -symbols %t2.exe | FileCheck %s +# RUN: llvm-readelf -s %t2.exe | FileCheck %s # CHECK: 0000000000010000 0 NOTYPE GLOBAL DEFAULT ABS foo # CHECK: 0000000000011001 40 OBJECT GLOBAL DEFAULT ABS bar diff --git a/lld/test/ELF/linkerscript/at3.test b/lld/test/ELF/linkerscript/at3.test index 6344f38b304dc..1e7f970c63ef3 100644 --- a/lld/test/ELF/linkerscript/at3.test +++ b/lld/test/ELF/linkerscript/at3.test @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at3.s -o %t.o # RUN: ld.lld %t.o --script %s -o %t -# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s MEMORY { FOO (ax) : ORIGIN = 0x1000, LENGTH = 0x100 diff --git a/lld/test/ELF/linkerscript/at6.test b/lld/test/ELF/linkerscript/at6.test index 498c0ef14f34d..63ffbb8737e49 100644 --- a/lld/test/ELF/linkerscript/at6.test +++ b/lld/test/ELF/linkerscript/at6.test @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at6.s -o %t.o # RUN: ld.lld %t.o --script %s -o %t -# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s MEMORY { FLASH : ORIGIN = 0x08000000, LENGTH = 0x100 diff --git a/lld/test/ELF/linkerscript/at7.test b/lld/test/ELF/linkerscript/at7.test index 1f67df29fdcd4..6a1a43599e441 100644 --- a/lld/test/ELF/linkerscript/at7.test +++ b/lld/test/ELF/linkerscript/at7.test @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at7.s -o %t.o # RUN: ld.lld %t.o --script %s -o %t -# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s MEMORY { RAM : ORIGIN = 0x20000000, LENGTH = 0x200 diff --git a/lld/test/ELF/linkerscript/at8.test b/lld/test/ELF/linkerscript/at8.test index c611c2e244040..db2bc55187ae6 100644 --- a/lld/test/ELF/linkerscript/at8.test +++ b/lld/test/ELF/linkerscript/at8.test @@ -1,7 +1,7 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at8.s -o %t.o # RUN: ld.lld %t.o --script %s -o %t -# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s MEMORY { FLASH : ORIGIN = 0x08000000, LENGTH = 0x100 diff --git a/lld/test/ELF/linkerscript/memory-loc-counter.test b/lld/test/ELF/linkerscript/memory-loc-counter.test index 3ca9a2cf6caad..2aa712282e09f 100644 --- a/lld/test/ELF/linkerscript/memory-loc-counter.test +++ b/lld/test/ELF/linkerscript/memory-loc-counter.test @@ -7,7 +7,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o # RUN: ld.lld -o %t %t.o --script %s -# RUN: llvm-readelf -sections -program-headers %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s ## Check that we can produce output without errors, ## and .foo section has proper size. diff --git a/lld/test/ELF/linkerscript/merge-header-load.s b/lld/test/ELF/linkerscript/merge-header-load.s index d067c40d67ab3..2f22477c6538b 100644 --- a/lld/test/ELF/linkerscript/merge-header-load.s +++ b/lld/test/ELF/linkerscript/merge-header-load.s @@ -5,7 +5,7 @@ # RUN: .text : AT (0x4200) { *(.text) } \ # RUN: }" > %t.script # RUN: ld.lld %t.o --script %t.script -o %t -# RUN: llvm-readelf -program-headers %t | FileCheck %s +# RUN: llvm-readelf -l %t | FileCheck %s # Test that we put the header in the first PT_LOAD. We used to create a PT_LOAD # just for it and it would have a different virtual to physical address delta. diff --git a/lld/test/ELF/linkerscript/orphan-discard.s b/lld/test/ELF/linkerscript/orphan-discard.s index 4549c3bc2b9e4..2f1c427dda54a 100644 --- a/lld/test/ELF/linkerscript/orphan-discard.s +++ b/lld/test/ELF/linkerscript/orphan-discard.s @@ -10,7 +10,7 @@ # RUN: /DISCARD/ : { *(.comment) } \ # RUN: }" > %t.script # RUN: ld.lld -o %t --script %t.script %t.o -# RUN: llvm-readelf -S -symbols %t | FileCheck %s +# RUN: llvm-readelf -S -s %t | FileCheck %s # CHECK: .bss NOBITS ffffffff80002000 002008 000002 00 WA 0 0 4096 # CHECK: ffffffff80003000 0 NOTYPE GLOBAL DEFAULT 3 _end diff --git a/lld/test/ELF/linkerscript/target.s b/lld/test/ELF/linkerscript/target.s index 32db5b7866c2a..783bb8f90e701 100644 --- a/lld/test/ELF/linkerscript/target.s +++ b/lld/test/ELF/linkerscript/target.s @@ -3,7 +3,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: echo "TARGET(binary) INPUT(\"%t.o\") TARGET(elf64-x86-64) INPUT(\"%t.o\")" > %t.script # RUN: ld.lld --script %t.script -o %t.exe -# RUN: llvm-readelf -symbols %t.exe | FileCheck %s +# RUN: llvm-readelf -s %t.exe | FileCheck %s # CHECK: _binary_ # CHECK: foobar diff --git a/lld/test/ELF/ppc64-rel-so-local-calls.s b/lld/test/ELF/ppc64-rel-so-local-calls.s index 3d2e0673c3a74..0be0d294deec3 100644 --- a/lld/test/ELF/ppc64-rel-so-local-calls.s +++ b/lld/test/ELF/ppc64-rel-so-local-calls.s @@ -2,11 +2,11 @@ // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o // RUN: ld.lld -shared %t.o -o %t.so -// RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s -allow-empty --implicit-check-not={{.}} +// RUN: llvm-readelf --dyn-relocations %t.so | FileCheck %s -allow-empty --implicit-check-not={{.}} // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o // RUN: ld.lld -shared %t.o -o %t.so -// RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s -allow-empty --implicit-check-not={{.}} +// RUN: llvm-readelf --dyn-relocations %t.so | FileCheck %s -allow-empty --implicit-check-not={{.}} .text .abiversion 2 diff --git a/lld/test/ELF/ppc64-toc-addis-nop-lqsq.s b/lld/test/ELF/ppc64-toc-addis-nop-lqsq.s index 08ec5f47c9e78..b742296fb8d72 100644 --- a/lld/test/ELF/ppc64-toc-addis-nop-lqsq.s +++ b/lld/test/ELF/ppc64-toc-addis-nop-lqsq.s @@ -1,7 +1,7 @@ # REQUIRES: ppc # XFAIL: * -# RUN: llvm-readelf -relocations --wide %p/Inputs/ppc64le-quadword-ldst.o | FileCheck --check-prefix=QuadInputRelocs %s +# RUN: llvm-readelf -r --wide %p/Inputs/ppc64le-quadword-ldst.o | FileCheck --check-prefix=QuadInputRelocs %s # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o # RUN: ld.lld -shared %t2.o -o %t2.so diff --git a/lld/test/ELF/relocatable-many-sections.s b/lld/test/ELF/relocatable-many-sections.s index 9abefd47254b5..acbbf2a3b098d 100644 --- a/lld/test/ELF/relocatable-many-sections.s +++ b/lld/test/ELF/relocatable-many-sections.s @@ -19,7 +19,7 @@ ## 4) .symtab_shndx has size equal to ## (sizeof(.symtab) / entsize(.symtab)) * entsize(.symtab_shndx) = 0x4 * 0x180078 / 0x18 == 0x040014 -# RUN: llvm-readelf -sections -symbols %t | FileCheck %s +# RUN: llvm-readelf -S -s %t | FileCheck %s # [Nr] Name Type Address Off Size ES Flg Lk Inf Al # CHECK: [65539] .note.GNU-stack PROGBITS 0000000000000000 000040 000000 00 0 0 1 # CHECK: [65540] .symtab SYMTAB 0000000000000000 000040 180078 18 65543 65539 8 diff --git a/lld/test/ELF/weak-shared-gc.s b/lld/test/ELF/weak-shared-gc.s index 2cafbe8dbb088..833d7b7ab4095 100644 --- a/lld/test/ELF/weak-shared-gc.s +++ b/lld/test/ELF/weak-shared-gc.s @@ -4,7 +4,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t2.o # RUN: ld.lld %t2.o -o %t2.so -shared # RUN: ld.lld %t1.o --as-needed --gc-sections %t2.so -o %t -# RUN: llvm-readelf -dynamic-table -dyn-symbols %t | FileCheck %s +# RUN: llvm-readelf -d --dyn-syms %t | FileCheck %s # The crt files on linux have a weak reference to __cxa_finalize. It # is important that a weak undefined reference is produced. Like diff --git a/lld/test/MachO/application-extension.s b/lld/test/MachO/application-extension.s new file mode 100644 index 0000000000000..eb4c61965e98e --- /dev/null +++ b/lld/test/MachO/application-extension.s @@ -0,0 +1,115 @@ +# REQUIRES: aarch64 + +## --no-leading-lines is needed for .tbd files. +# RUN: rm -rf %t; split-file --no-leading-lines %s %t + +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o %t/foo.o %t/foo.s +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o %t/bar.o %t/bar.s + +## MH_APP_EXTENSION_SAFE is only set on dylibs, and only if requested. +# RUN: %lld -arch arm64 -dylib -o %t/foo.dylib %t/foo.o +# RUN: llvm-otool -hv %t/foo.dylib | FileCheck --check-prefix=NOAPPEXT %s +# RUN: %lld -arch arm64 -dylib -o %t/foo-appext.dylib %t/foo.o \ +# RUN: -application_extension +# RUN: llvm-otool -hv %t/foo-appext.dylib | FileCheck --check-prefix=APPEXT %s +# RUN: %lld -arch arm64 -dylib -o %t/foo-noappext.dylib %t/foo.o \ +# RUN: -application_extension -no_application_extension +# RUN: llvm-otool -hv %t/foo-noappext.dylib \ +# RUN: | FileCheck --check-prefix=NOAPPEXT %s +# RUN: %lld -arch arm64 -bundle -o %t/foo.so %t/foo.o \ +# RUN: -application_extension +# RUN: llvm-otool -hv %t/foo.so | FileCheck --check-prefix=NOAPPEXT %s + +# APPEXT: APP_EXTENSION_SAFE +# NOAPPEXT-NOT: APP_EXTENSION_SAFE + +## The warning is emitted for all target types. +# RUN: %lld -arch arm64 -dylib -o %t/bar.dylib %t/bar.o \ +# RUN: -application_extension %t/foo-appext.dylib +# RUN: %lld -arch arm64 -dylib -o %t/bar.dylib %t/bar.o \ +# RUN: -application_extension -L %t -ltbd-appext +# RUN: not %lld -arch arm64 -dylib -o %t/bar.dylib %t/bar.o \ +# RUN: -application_extension %t/foo-noappext.dylib \ +# RUN: 2>&1 | FileCheck --check-prefix=WARN %s +# RUN: not %lld -arch arm64 -dylib -o %t/bar.dylib %t/bar.o \ +# RUN: -application_extension -L %t -ltbd-noappext \ +# RUN: 2>&1 | FileCheck --check-prefix=WARN %s +# RUN: not %lld -arch arm64 -bundle -o %t/bar.so %t/bar.o \ +# RUN: -application_extension %t/foo-noappext.dylib \ +# RUN: 2>&1 | FileCheck --check-prefix=WARN %s +# RUN: not %lld -arch arm64 -bundle -o %t/bar.so %t/bar.o \ +# RUN: -application_extension -L %t -ltbd-noappext \ +# RUN: 2>&1 | FileCheck --check-prefix=WARN %s + +# WARN: using '-application_extension' with unsafe dylib: + +## Test we warn on dylibs loaded indirectly via reexports. +# RUN: not %lld -arch arm64 -dylib -o %t/bar.dylib %t/bar.o \ +# RUN: -application_extension -L %t -lbaz-noappext-reexport \ +# RUN: -u _baz 2>&1 | FileCheck --check-prefix=WARN %s + +#--- foo.s +.globl _foo +.p2align 2 +_foo: + ret + +#--- libtbd-appext.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +uuids: + - target: arm64-macos + value: 2E994C7F-3F03-3A07-879C-55690D22BEDA +install-name: '/usr/lib/libtbd-appext.dylib' +exports: + - targets: [ arm64-macos ] + symbols: [ _foo ] +... + +#--- libtbd-noappext.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +flags: [ not_app_extension_safe ] +uuids: + - target: arm64-macos + value: 2E994C7F-3F03-3A07-879C-55690D22BEDA +install-name: '/usr/lib/libtbd-noappext.dylib' +exports: + - targets: [ arm64-macos ] + symbols: [ _foo ] +... + +#--- bar.s +.globl _bar +.p2align 2 +_bar: + ret + +#--- libbaz-noappext-reexport.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +uuids: + - target: arm64-macos + value: 00000000-0000-0000-0000-000000000001 +install-name: '/usr/lib/libbaz.dylib' +reexported-libraries: + - targets: [ arm64-macos ] + libraries: [ '/usr/lib/libbaz-noappext-reexport.dylib'] +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +flags: [ not_app_extension_safe ] +uuids: + - target: arm64-macos + value: 00000000-0000-0000-0000-000000000003 +install-name: '/usr/lib/libbaz-noappext-reexport.dylib' +parent-umbrella: + - targets: [ arm64-macos ] + umbrella: baz +exports: + - targets: [ arm64-macos ] + symbols: [ _baz ] +... diff --git a/lld/test/MachO/bind-opcodes.s b/lld/test/MachO/bind-opcodes.s index b66bffbd8c41c..b313afbef8e68 100644 --- a/lld/test/MachO/bind-opcodes.s +++ b/lld/test/MachO/bind-opcodes.s @@ -2,28 +2,83 @@ # RUN: rm -rf %t; split-file %s %t # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o -# RUN: %lld -dylib %t/foo.o -o %t/libfoo.dylib -# RUN: %lld -lSystem %t/test.o %t/libfoo.dylib -o %t/test +# RUN: %lld -O2 -dylib %t/foo.o -o %t/libfoo.dylib +# RUN: %lld -O2 -lSystem %t/test.o %t/libfoo.dylib -o %t/test -## Make sure we emit exactly one BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM per -## symbol. -# RUN: obj2yaml %t/test | FileCheck %s --implicit-check-not BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM +## Test: +## 1/ We emit exactly one BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM per symbol. +## 2/ Combine BIND_OPCODE_DO_BIND and BIND_OPCODE_ADD_ADDR_ULEB pairs. +## 3/ Compact BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB +# RUN: obj2yaml %t/test | FileCheck %s -# CHECK: Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM -# CHECK-NEXT: Imm: 0 -# CHECK-NEXT: Symbol: _foo - -# CHECK: Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM -# CHECK-NEXT: Imm: 0 -# CHECK-NEXT: Symbol: _bar +# CHECK: BindOpcodes: +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: Symbol: _foo +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_TYPE_IMM +# CHECK-NEXT: Imm: 1 +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM +# CHECK-NEXT: Imm: 2 +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB +# CHECK-NEXT: Imm: 2 +# CHECK-NEXT: ULEBExtraData: [ 0x0 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: ULEBExtraData: [ 0x2, 0x8 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_ADDEND_SLEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: SLEBExtraData: [ 1 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: ULEBExtraData: [ 0x1008 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_ADDEND_SLEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: SLEBExtraData: [ 0 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: Symbol: _bar +# CHECK-NEXT: Opcode: BIND_OPCODE_SET_TYPE_IMM +# CHECK-NEXT: Imm: 1 +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_ADD_ADDR_ULEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: ULEBExtraData: [ 0xFFFFFFFFFFFFEFD0 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: ULEBExtraData: [ 0x8 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: ULEBExtraData: [ 0x1008 ] +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DO_BIND +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: Symbol: '' +# CHECK-NEXT: Opcode: BIND_OPCODE_DONE +# CHECK-NEXT: Imm: 0 +# CHECK-NEXT: Symbol: '' # RUN: llvm-objdump --macho --bind %t/test | FileCheck %s --check-prefix=BIND # BIND: Bind table: -# BIND-NEXT: segment section address type addend dylib symbol -# BIND-NEXT: __DATA __data {{.*}} pointer 0 libfoo _foo -# BIND-NEXT: __DATA __data {{.*}} pointer 0 libfoo _foo -# BIND-NEXT: __DATA __data {{.*}} pointer 0 libfoo _bar -# BIND-NEXT: __DATA __data {{.*}} pointer 0 libfoo _bar +# BIND-NEXT: segment section address type addend dylib symbol +# BIND-NEXT: __DATA __data 0x100001000 pointer 0 libfoo _foo +# BIND-NEXT: __DATA __data 0x100001010 pointer 0 libfoo _foo +# BIND-NEXT: __DATA __data 0x100001020 pointer 1 libfoo _foo +# BIND-NEXT: __DATA __data 0x100002030 pointer 0 libfoo _foo +# BIND-NEXT: __DATA __data 0x100001008 pointer 0 libfoo _bar +# BIND-NEXT: __DATA __data 0x100001018 pointer 0 libfoo _bar +# BIND-NEXT: __DATA __data 0x100002028 pointer 0 libfoo _bar # BIND-EMPTY: #--- foo.s @@ -39,6 +94,10 @@ _bar: .quad _bar .quad _foo .quad _bar +.quad _foo+1 +.zero 0x1000 +.quad _bar +.quad _foo .globl _main .text diff --git a/lld/test/MachO/dylink-ordinal.s b/lld/test/MachO/dylink-ordinal.s index 7edb218f7321c..c1474455260c6 100644 --- a/lld/test/MachO/dylink-ordinal.s +++ b/lld/test/MachO/dylink-ordinal.s @@ -39,6 +39,7 @@ current-version: 0001.001.1 exports: - targets: [ x86_64-macos ] symbols: [ _foo ] +... #--- libBar.tbd --- !tapi-tbd @@ -54,6 +55,7 @@ current-version: 0001.001.1 exports: - targets: [ x86_64-macos ] symbols: [ _bar ] +... #--- main.s .section __TEXT,__text diff --git a/lld/test/MachO/icf.s b/lld/test/MachO/icf.s index 4367646d520a8..04b56768d21af 100644 --- a/lld/test/MachO/icf.s +++ b/lld/test/MachO/icf.s @@ -25,15 +25,17 @@ # CHECK: [[#%x,SR]] g F __TEXT,__text _sr2 # CHECK: [[#%x,MR:]] g F __TEXT,__text _mr1 # CHECK: [[#%x,MR]] g F __TEXT,__text _mr2 +# CHECK: [[#%x,K1:]] g O __TEXT,__foo _k1 +# CHECK: [[#%x,A:]] g F __TEXT,__text _k2 ### FIXME: Mutually-recursive functions with identical bodies (see below) # COM: [[#%x,XR:]] g F __TEXT,__text _xr1 # COM: [[#%x,XR]] g F __TEXT,__text _xr2 # CHECK-LABEL: Disassembly of section __TEXT,__text: # CHECK: [[#%x,MAIN]] <_main>: -# CHECK-NEXT: callq 0x[[#%x,A]] <_a3> -# CHECK-NEXT: callq 0x[[#%x,A]] <_a3> -# CHECK-NEXT: callq 0x[[#%x,A]] <_a3> +# CHECK-NEXT: callq 0x[[#%x,A]] <_k2> +# CHECK-NEXT: callq 0x[[#%x,A]] <_k2> +# CHECK-NEXT: callq 0x[[#%x,A]] <_k2> # CHECK-NEXT: callq 0x[[#%x,B]] <_b> # CHECK-NEXT: callq 0x[[#%x,B2]] <_b2> # CHECK-NEXT: callq 0x[[#%x,C]] <_c> @@ -44,6 +46,8 @@ # CHECK-NEXT: callq 0x[[#%x,H]] <_h> # CHECK-NEXT: callq 0x[[#%x,I]] <_i> # CHECK-NEXT: callq 0x[[#%x,J]] <_j> +# CHECK-NEXT: callq 0x[[#%x,K1]] <_k1> +# CHECK-NEXT: callq 0x[[#%x,A]] <_k2> # CHECK-NEXT: callq 0x[[#%x,SR]] <_sr2> # CHECK-NEXT: callq 0x[[#%x,SR]] <_sr2> # CHECK-NEXT: callq 0x[[#%x,MR]] <_mr2> @@ -232,8 +236,38 @@ _j: ret .cfi_endproc +### No fold: _k1 is in a different section from _a1 +.section __TEXT,__foo +.globl _k1 +.p2align 2 +_k1: + callq _d + mov ___nan@GOTPCREL(%rip), %rax + callq ___isnan + movabs $_abs1a, %rdx + movl $0, %eax + ret + nopl (%rax) + +### Fold: _k2 is in a section that gets renamed and output as __text +.section __TEXT,__StaticInit +.globl _k2 +.p2align 2 +_k2: + callq _d + mov ___nan@GOTPCREL(%rip), %rax + callq ___isnan + movabs $_abs1a, %rdx + movl $0, %eax + ret +## For some reason, llvm-mc generates different nop encodings when adding +## padding for __StaticInit vs __text functions. So we explicitly specify the +## nop here to make sure this function can be folded with _a1. + nopl (%rax) + ### Fold: Simple recursion +.text .globl _sr1 .p2align 2 _sr1: @@ -311,6 +345,8 @@ _main: callq _h callq _i callq _j + callq _k1 + callq _k2 callq _sr1 callq _sr2 callq _mr1 diff --git a/lld/test/MachO/lto-cache.ll b/lld/test/MachO/lto-cache.ll new file mode 100644 index 0000000000000..8f14100a90bdb --- /dev/null +++ b/lld/test/MachO/lto-cache.ll @@ -0,0 +1,94 @@ +; REQUIRES: x86 +; NetBSD: noatime mounts currently inhibit 'touch' from updating atime +; UNSUPPORTED: system-netbsd + +; RUN: rm -rf %t; split-file %s %t +; RUN: opt -module-hash -module-summary %t/foo.ll -o %t/foo.o +; RUN: opt -module-hash -module-summary %t/bar.ll -o %t/bar.o + +; RUN: rm -Rf %t/cache && mkdir %t/cache +;; Create two files that would be removed by cache pruning due to age. +;; We should only remove files matching the pattern "llvmcache-*". +; RUN: touch -t 197001011200 %t/cache/llvmcache-baz %t/cache/baz +; RUN: %lld -cache_path_lto %t/cache \ +; RUN: --thinlto-cache-policy=prune_after=1h:prune_interval=0s \ +; RUN: -o %t/test %t/foo.o %t/bar.o + +;; Two cached objects, plus a timestamp file and "baz", minus the file we removed. +; RUN: ls %t/cache | count 4 + +;; Same thing, but with `-prune_after_lto` +; RUN: touch -t 197001011200 %t/cache/llvmcache-baz +; RUN: %lld -cache_path_lto %t/cache -prune_after_lto 3600 -prune_interval_lto 0 \ +; RUN: -o %t/test %t/foo.o %t/bar.o +; RUN: ls %t/cache | count 4 + +;; Create a file of size 64KB. +; RUN: %python -c "print(' ' * 65536)" > %t/cache/llvmcache-baz + +;; This should leave the file in place. +; RUN: %lld -cache_path_lto %t/cache \ +; RUN: --thinlto-cache-policy=cache_size_bytes=128k:prune_interval=0s \ +; RUN: -o %t/test %t/foo.o %t/bar.o +; RUN: ls %t/cache | count 5 + +;; Increase the age of llvmcache-baz, which will give it the oldest time stamp +;; so that it is processed and removed first. +; RUN: %python -c 'import os,sys,time; t=time.time()-120; os.utime(sys.argv[1],(t,t))' \ +; RUN: %t/cache/llvmcache-baz + +;; This should remove it. +; RUN: %lld -cache_path_lto %t/cache \ +; RUN: --thinlto-cache-policy=cache_size_bytes=32k:prune_interval=0s \ +; RUN: -o %t/test %t/foo.o %t/bar.o +; RUN: ls %t/cache | count 4 + +;; Delete everything except for the timestamp, "baz" and one cache file. +; RUN: %lld -cache_path_lto %t/cache \ +; RUN: --thinlto-cache-policy=prune_after=0s:cache_size=0%:cache_size_files=1:prune_interval=0s \ +; RUN: -o %t/test %t/foo.o %t/bar.o +; RUN: ls %t/cache | count 3 + +;; Check that we remove the least recently used file first. +; RUN: rm -fr %t/cache +; RUN: mkdir %t/cache +; RUN: echo xyz > %t/cache/llvmcache-old +; RUN: touch -t 198002011200 %t/cache/llvmcache-old +; RUN: echo xyz > %t/cache/llvmcache-newer +; RUN: touch -t 198002021200 %t/cache/llvmcache-newer +; RUN: %lld -cache_path_lto %t/cache \ +; RUN: --thinlto-cache-policy=prune_after=0s:cache_size=0%:cache_size_files=3:prune_interval=0s \ +; RUN: -o %t/test %t/foo.o %t/bar.o +; RUN: ls %t/cache | FileCheck %s + +;; Check that `-max_relative_cache_size_lto` is a legal argument. +; RUN: %lld -cache_path_lto %t/cache -max_relative_cache_size_lto 10 \ +; RUN: -o %t/test %t/foo.o %t/bar.o + +; CHECK-NOT: llvmcache-old +; CHECK: llvmcache-newer +; CHECK-NOT: llvmcache-old + +;--- foo.ll + +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define void @globalfunc() #0 { +entry: + ret void +} + + +;--- bar.ll + +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define i32 @main() { +entry: + call void (...) @globalfunc() + ret i32 0 +} + +declare void @globalfunc(...) diff --git a/lld/test/mach-o/debug-syms.yaml b/lld/test/mach-o/debug-syms.yaml index 54ea4ddd51143..901c2528fc72e 100644 --- a/lld/test/mach-o/debug-syms.yaml +++ b/lld/test/mach-o/debug-syms.yaml @@ -1,5 +1,5 @@ # RUN: ld64.lld.darwinold -arch x86_64 -o %t %s -dylib %p/Inputs/x86_64/libSystem.yaml && \ -# RUN: llvm-nm -no-sort -debug-syms %t | FileCheck %s +# RUN: llvm-nm --no-sort --debug-syms %t | FileCheck %s # CHECK: 0000000000000000 - 00 0000 SO /Users/lhames/Projects/lld/lld-svn-tot/scratch/ # CHECK-NEXT: 0000000000000000 - 00 0000 SO hw.c diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll index 72c4d9117bbcc..61bf903a116cf 100644 --- a/lld/test/wasm/data-segments.ll +++ b/lld/test/wasm/data-segments.ll @@ -122,7 +122,7 @@ ; PASSIVE64-PIC-NEXT: - Type: I64 ; PASSIVE-PIC-NEXT: Count: 1 ; PASSIVE32-PIC-NEXT: Body: 230141B4CE006A2100200041004101FE480200044020004101427FFE0102001A05410023016A4100410DFC080000411023016A41004114FC08010020004102FE1702002000417FFE0002001A0BFC0900FC09010B -; PASSIVE64-PIC-NEXT: Body: 230142B4CE006A2100200041004101FE480200044020004101427FFE0102001A05420023016A4100410DFC080000421023016A41004114FC08010020004102FE1702002000417FFE0002001A0BFC0900FC09010B +; PASSIVE64-PIC-NEXT: Body: 230142B4CE007C2100200041004101FE480200044020004101427FFE0102001A05420023017C4100410DFC080000421023017C41004114FC08010020004102FE1702002000417FFE0002001A0BFC0900FC09010B ; PASSIVE-PIC-NEXT: - Index: 3 ; PASSIVE-PIC-NEXT: Locals: [] ; PASSIVE-PIC-NEXT: Body: 0B diff --git a/lld/test/wasm/shared64.s b/lld/test/wasm/shared64.s index 14553c349c8a7..36528e1031a65 100644 --- a/lld/test/wasm/shared64.s +++ b/lld/test/wasm/shared64.s @@ -17,13 +17,13 @@ data: .section .data.indirect_func_external,"",@ indirect_func_external: - .int32 func_external -.size indirect_func_external, 4 + .int64 func_external +.size indirect_func_external, 8 .section .data.indirect_func,"",@ indirect_func: - .int32 foo - .size indirect_func, 4 + .int64 foo + .size indirect_func, 8 # Test data relocations @@ -68,7 +68,8 @@ foo: i32.load 0 local.set 1 global.get indirect_func@GOT - i32.load 0 + i64.load 0 + i32.wrap_i64 call_indirect () -> (i32) drop local.get 0 @@ -128,7 +129,7 @@ get_local_func_address: # CHECK: Sections: # CHECK-NEXT: - Type: CUSTOM # CHECK-NEXT: Name: dylink -# CHECK-NEXT: MemorySize: 28 +# CHECK-NEXT: MemorySize: 36 # CHECK-NEXT: MemoryAlignment: 2 # CHECK-NEXT: TableSize: 2 # CHECK-NEXT: TableAlignment: 0 @@ -180,22 +181,22 @@ get_local_func_address: # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: indirect_func # CHECK-NEXT: Kind: GLOBAL -# CHECK-NEXT: GlobalType: I32 +# CHECK-NEXT: GlobalType: I64 # CHECK-NEXT: GlobalMutable: true # CHECK-NEXT: - Module: GOT.func # CHECK-NEXT: Field: func_external # CHECK-NEXT: Kind: GLOBAL -# CHECK-NEXT: GlobalType: I32 +# CHECK-NEXT: GlobalType: I64 # CHECK-NEXT: GlobalMutable: true # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: data_external # CHECK-NEXT: Kind: GLOBAL -# CHECK-NEXT: GlobalType: I32 +# CHECK-NEXT: GlobalType: I64 # CHECK-NEXT: GlobalMutable: true # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: extern_struct # CHECK-NEXT: Kind: GLOBAL -# CHECK-NEXT: GlobalType: I32 +# CHECK-NEXT: GlobalType: I64 # CHECK-NEXT: GlobalMutable: true # CHECK-NEXT: - Type: FUNCTION @@ -224,7 +225,7 @@ get_local_func_address: # CHECK-NEXT: Body: 10020B # CHECK-NEXT: - Index: 2 # CHECK-NEXT: Locals: [] -# CHECK-NEXT: Body: 230142047C2305360200230142087C230241016A3602002301420C7C230141006A360200230142107C2306370200230142187C230741046A3602000B +# CHECK-NEXT: Body: 230142047C23053702002301420C7C230242017C370200230142147C230141006A360200230142187C2306370200230142207C230741046A3602000B # check the data segment initialized with __memory_base global as offset @@ -235,4 +236,4 @@ get_local_func_address: # CHECK-NEXT: Offset: # CHECK-NEXT: Opcode: GLOBAL_GET # CHECK-NEXT: Index: 1 -# CHECK-NEXT: Content: '02000000000000000100000000000000000000000000000000000000' +# CHECK-NEXT: Content: '020000000000000000000000010000000000000000000000000000000000000000000000' diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 206fde64dabb3..7e0c030482fb9 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -621,6 +621,8 @@ static void createSyntheticSymbols() { "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, make(nullSignature, "__wasm_call_ctors")); + bool is64 = config->is64.getValueOr(false); + if (config->isPic) { WasmSym::stackPointer = createUndefinedGlobal("__stack_pointer", config->is64.getValueOr(false) @@ -631,7 +633,6 @@ static void createSyntheticSymbols() { // which to load our static data and function table. // See: // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md - bool is64 = config->is64.getValueOr(false); auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32; WasmSym::memoryBase = createUndefinedGlobal("__memory_base", globalType); WasmSym::tableBase = createUndefinedGlobal("__table_base", globalType); @@ -657,7 +658,7 @@ static void createSyntheticSymbols() { WasmSym::initTLS = symtab->addSyntheticFunction( "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN, make( - config->is64.getValueOr(false) ? i64ArgSignature : i32ArgSignature, + is64 ? i64ArgSignature : i32ArgSignature, "__wasm_init_tls")); } } diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index 6912fcda0ba3f..cfd1f56104087 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -39,6 +39,10 @@ bool relocIs64(uint8_t relocType) { case R_WASM_MEMORY_ADDR_SLEB64: case R_WASM_MEMORY_ADDR_REL_SLEB64: case R_WASM_MEMORY_ADDR_I64: + case R_WASM_TABLE_INDEX_SLEB64: + case R_WASM_TABLE_INDEX_I64: + case R_WASM_FUNCTION_OFFSET_I64: + case R_WASM_TABLE_INDEX_REL_SLEB64: return true; default: return false; @@ -355,12 +359,11 @@ void InputChunk::generateRelocationCode(raw_ostream &os) const { LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName() << " count=" << relocations.size() << "\n"); - unsigned opcode_ptr_const = config->is64.getValueOr(false) - ? WASM_OPCODE_I64_CONST - : WASM_OPCODE_I32_CONST; - unsigned opcode_ptr_add = config->is64.getValueOr(false) - ? WASM_OPCODE_I64_ADD - : WASM_OPCODE_I32_ADD; + bool is64 = config->is64.getValueOr(false); + unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST + : WASM_OPCODE_I32_CONST; + unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD + : WASM_OPCODE_I32_ADD; uint64_t tombstone = getTombstone(); // TODO(sbc): Encode the relocations in the data section and write a loop diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index a3d6207bbe61b..96f7f30553161 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -125,6 +125,8 @@ void ImportSection::writeBody() { writeUleb128(os, getNumImports(), "import count"); + bool is64 = config->is64.getValueOr(false); + if (config->importMemory) { WasmImport import; import.Module = defaultModule; @@ -138,7 +140,7 @@ void ImportSection::writeBody() { } if (config->sharedMemory) import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; - if (config->is64.getValueOr(false)) + if (is64) import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64; writeImport(os, import); } @@ -180,7 +182,8 @@ void ImportSection::writeBody() { for (const Symbol *sym : gotSymbols) { WasmImport import; import.Kind = WASM_EXTERNAL_GLOBAL; - import.Global = {WASM_TYPE_I32, true}; + auto ptrType = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32; + import.Global = {static_cast(ptrType), true}; if (isa(sym)) import.Module = "GOT.mem"; else @@ -317,12 +320,11 @@ void GlobalSection::addInternalGOTEntry(Symbol *sym) { } void GlobalSection::generateRelocationCode(raw_ostream &os) const { - unsigned opcode_ptr_const = config->is64.getValueOr(false) - ? WASM_OPCODE_I64_CONST - : WASM_OPCODE_I32_CONST; - unsigned opcode_ptr_add = config->is64.getValueOr(false) - ? WASM_OPCODE_I64_ADD - : WASM_OPCODE_I32_ADD; + bool is64 = config->is64.getValueOr(false); + unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST + : WASM_OPCODE_I32_CONST; + unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD + : WASM_OPCODE_I32_ADD; for (const Symbol *sym : internalGotSymbols) { if (auto *d = dyn_cast(sym)) { diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 7312386ef417f..42dbc27261f2b 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -1057,7 +1057,7 @@ void Writer::createInitMemoryFunction() { writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base"); writePtrConst(os, flagAddress, is64, "flag address"); - writeU8(os, WASM_OPCODE_I32_ADD, "add"); + writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, "add"); writeU8(os, WASM_OPCODE_LOCAL_SET, "local.set"); writeUleb128(os, 0, "local 0"); } else { @@ -1104,7 +1104,8 @@ void Writer::createInitMemoryFunction() { writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base"); - writeU8(os, WASM_OPCODE_I32_ADD, "i32.add"); + writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, + "i32.add"); } // source segment offset writeI32Const(os, 0, "segment offset"); diff --git a/lldb/bindings/interface/SBProcess.i b/lldb/bindings/interface/SBProcess.i index 27c015df85cda..14566a2942d04 100644 --- a/lldb/bindings/interface/SBProcess.i +++ b/lldb/bindings/interface/SBProcess.i @@ -417,6 +417,25 @@ public: lldb::SBProcessInfo GetProcessInfo(); + %feature("autodoc", " + Allocates a block of memory within the process, with size and + access permissions specified in the arguments. The permisssions + argument is an or-combination of zero or more of + lldb.ePermissionsWritable, lldb.ePermissionsReadable, and + lldb.ePermissionsExecutable. Returns the address + of the allocated buffer in the process, or + lldb.LLDB_INVALID_ADDRESS if the allocation failed.") AllocateMemory; + + lldb::addr_t + AllocateMemory(size_t size, uint32_t permissions, lldb::SBError &error); + + %feature("autodoc", " + Deallocates the block of memory (previously allocated using + AllocateMemory) given in the argument.") DeallocateMemory; + + lldb::SBError + DeallocateMemory(lldb::addr_t ptr); + STRING_EXTENSION(SBProcess) #ifdef SWIGPYTHON diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst index cb774d76c6296..6e2afcae0e262 100644 --- a/lldb/docs/resources/build.rst +++ b/lldb/docs/resources/build.rst @@ -71,7 +71,7 @@ commands below. :: > yum install libedit-devel libxml2-devel ncurses-devel python-devel swig - > sudo apt-get install build-essential subversion swig python3-dev libedit-dev libncurses5-dev + > sudo apt-get install build-essential swig python3-dev libedit-dev libncurses5-dev > pkg install swig python > pkgin install swig python36 cmake ninja-build > brew install swig cmake ninja diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h index a5676c2cab9a8..73a8d918f4d65 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -370,6 +370,45 @@ class LLDB_API SBProcess { /// valid. lldb::SBProcessInfo GetProcessInfo(); + /// Allocate memory within the process. + /// + /// This function will allocate memory in the process's address space. + /// + /// \param[in] size + /// The size of the allocation requested. + /// + /// \param[in] permissions + /// Or together any of the lldb::Permissions bits. The + /// permissions on a given memory allocation can't be changed + /// after allocation. Note that a block that isn't set writable + /// can still be written from lldb, just not by the process + /// itself. + /// + /// \param[out] error + /// An error object that gets filled in with any errors that + /// might occur when trying allocate. + /// + /// \return + /// The address of the allocated buffer in the process, or + /// LLDB_INVALID_ADDRESS if the allocation failed. + lldb::addr_t AllocateMemory(size_t size, uint32_t permissions, + lldb::SBError &error); + + /// Deallocate memory in the process. + /// + /// This function will deallocate memory in the process's address + /// space that was allocated with AllocateMemory. + /// + /// \param[in] ptr + /// A return value from AllocateMemory, pointing to the memory you + /// want to deallocate. + /// + /// \return + /// An error object describes any errors that occurred while + /// deallocating. + /// + lldb::SBError DeallocateMemory(lldb::addr_t ptr); + protected: friend class SBAddress; friend class SBBreakpoint; diff --git a/lldb/include/lldb/Target/MemoryTagManager.h b/lldb/include/lldb/Target/MemoryTagManager.h index f6383d82efcd7..a5e0deba14a90 100644 --- a/lldb/include/lldb/Target/MemoryTagManager.h +++ b/lldb/include/lldb/Target/MemoryTagManager.h @@ -9,6 +9,7 @@ #ifndef LLDB_TARGET_MEMORYTAGMANAGER_H #define LLDB_TARGET_MEMORYTAGMANAGER_H +#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/RangeMap.h" #include "lldb/lldb-private.h" #include "llvm/Support/Error.h" @@ -57,6 +58,20 @@ class MemoryTagManager { // expanded to 2 granules. virtual TagRange ExpandToGranule(TagRange range) const = 0; + // Given a range addr to end_addr, check that: + // * end_addr >= addr (when memory tags are removed) + // * the granule aligned range is completely covered by tagged memory + // (which may include one or more memory regions) + // + // If so, return a modified range which will have been expanded + // to be granule aligned. + // + // Tags in the input addresses are ignored and not present + // in the returned range. + virtual llvm::Expected MakeTaggedRange( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const = 0; + // Return the type value to use in GDB protocol qMemTags packets to read // allocation tags. This is named "Allocation" specifically because the spec // allows for logical tags to be read the same way, though we do not use that. @@ -72,11 +87,45 @@ class MemoryTagManager { virtual size_t GetTagSizeInBytes() const = 0; // Unpack tags from their stored format (e.g. gdb qMemTags data) into seperate - // tags. Checks that each tag is within the expected value range and that the - // number of tags found matches the number of granules we originally asked - // for. + // tags. + // + // Checks that each tag is within the expected value range and if granules is + // set to non-zero, that the number of tags found matches the number of + // granules we expected to cover. + virtual llvm::Expected> + UnpackTagsData(const std::vector &tags, + size_t granules = 0) const = 0; + + // Pack uncompressed tags into their storage format (e.g. for gdb QMemTags). + // Checks that each tag is within the expected value range. + // We do not check the number of tags or range they apply to because + // it is up to the remote to repeat them as needed. + virtual llvm::Expected> + PackTags(const std::vector &tags) const = 0; + + // Take a set of tags and repeat them as much as needed to cover the given + // range. We assume that this range has been previously expanded/aligned to + // granules. (this method is used by lldb-server to implement QMemTags + // packet handling) + // + // If the range is empty, zero tags are returned. + // If the range is not empty and... + // * there are no tags, an error is returned. + // * there are fewer tags than granules, the tags are repeated to fill the + // range. + // * there are more tags than granules, only the tags required to cover + // the range are returned. + // + // When repeating tags it will not always return a multiple of the original + // list. For example if your range is 3 granules and your tags are 1 and 2. + // You will get tags 1, 2 and 1 returned. Rather than getting 1, 2, 1, 2, + // which would be one too many tags for the range. + // + // A single tag will just be repeated as you'd expected. Tag 1 over 3 granules + // would return 1, 1, 1. virtual llvm::Expected> - UnpackTagsData(const std::vector &tags, size_t granules) const = 0; + RepeatTagsForRange(const std::vector &tags, + TagRange range) const = 0; virtual ~MemoryTagManager() {} }; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 03b05c8e25d9a..2457ac31c19db 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -95,6 +95,7 @@ class ProcessProperties : public Properties { bool GetWarningsUnsupportedLanguage() const; bool GetStopOnExec() const; std::chrono::seconds GetUtilityExpressionTimeout() const; + std::chrono::seconds GetInterruptTimeout() const; bool GetOSPluginReportsAllThreads() const; void SetOSPluginReportsAllThreads(bool does_report); bool GetSteppingRunsAllThreads() const; @@ -1708,30 +1709,19 @@ class Process : public std::enable_shared_from_this, lldb::addr_t CallocateMemory(size_t size, uint32_t permissions, Status &error); - /// If the address range given is in a memory tagged range and this - /// architecture and process supports memory tagging, return a tag + /// If this architecture and process supports memory tagging, return a tag /// manager that can be used to maniupulate those memory tags. - /// Tags present in the addresses given are ignored. - /// - /// \param[in] addr - /// Start of memory range. - /// - /// \param[in] end_addr - /// End of the memory range. Where end is one beyond the last byte to be - /// included. /// /// \return /// Either a valid pointer to a tag manager or an error describing why one /// could not be provided. - llvm::Expected - GetMemoryTagManager(lldb::addr_t addr, lldb::addr_t end_addr); + llvm::Expected GetMemoryTagManager(); - /// Expands the range addr to addr+len to align with granule boundaries and - /// then calls DoReadMemoryTags to do the target specific operations. - /// Tags are returned unpacked so can be used without conversion. + /// Read memory tags for the range addr to addr+len. It is assumed + /// that this range has already been granule aligned. + /// (see MemoryTagManager::MakeTaggedRange) /// - /// \param[in] tag_manager - /// The tag manager to get memory tagging information from. + /// This calls DoReadMemoryTags to do the target specific operations. /// /// \param[in] addr /// Start of memory range to read tags for. @@ -1740,11 +1730,12 @@ class Process : public std::enable_shared_from_this, /// Length of memory range to read tags for (in bytes). /// /// \return - /// Either the unpacked tags or an error describing a failure to read - /// or unpack them. - llvm::Expected> - ReadMemoryTags(const MemoryTagManager *tag_manager, lldb::addr_t addr, - size_t len); + /// If this architecture or process does not support memory tagging, + /// an error saying so. + /// If it does, either the memory tags or an error describing a + /// failure to read or unpack them. + llvm::Expected> ReadMemoryTags(lldb::addr_t addr, + size_t len); /// Resolve dynamically loaded indirect functions. /// diff --git a/lldb/include/lldb/Target/TargetList.h b/lldb/include/lldb/Target/TargetList.h index 903ca4bcefbcb..65781a4811fd8 100644 --- a/lldb/include/lldb/Target/TargetList.h +++ b/lldb/include/lldb/Target/TargetList.h @@ -14,6 +14,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Iterable.h" namespace lldb_private { @@ -42,6 +43,11 @@ class TargetList : public Broadcaster { return GetStaticBroadcasterClass(); } + typedef std::vector collection; + typedef LockingAdaptedIterable + TargetIterable; + /// Create a new Target. /// /// Clients must use this function to create a Target. This allows @@ -179,14 +185,15 @@ class TargetList : public Broadcaster { lldb::TargetSP GetSelectedTarget(); -protected: - typedef std::vector collection; - // Member variables. + TargetIterable Targets() { + return TargetIterable(m_target_list, m_target_list_mutex); + } + +private: collection m_target_list; mutable std::recursive_mutex m_target_list_mutex; uint32_t m_selected_target_idx; -private: static Status CreateTargetInternal( Debugger &debugger, llvm::StringRef user_exe_path, llvm::StringRef triple_str, LoadDependentFiles load_dependent_files, diff --git a/lldb/include/lldb/Target/ThreadPlanStack.h b/lldb/include/lldb/Target/ThreadPlanStack.h index 9ba58b1dec41f..e0f76f8e1df52 100644 --- a/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/lldb/include/lldb/Target/ThreadPlanStack.h @@ -110,6 +110,7 @@ class ThreadPlanStack { size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for // completed plan checkpoints. std::unordered_map m_completed_plan_store; + mutable std::recursive_mutex m_stack_mutex; }; class ThreadPlanStackMap { @@ -153,7 +154,7 @@ class ThreadPlanStackMap { } void Clear() { - for (auto plan : m_plans_list) + for (auto &plan : m_plans_list) plan.second.ThreadDestroyed(nullptr); m_plans_list.clear(); } diff --git a/lldb/include/lldb/Target/Trace.h b/lldb/include/lldb/Target/Trace.h index cc84270b80081..c82d17b029557 100644 --- a/lldb/include/lldb/Target/Trace.h +++ b/lldb/include/lldb/Target/Trace.h @@ -45,11 +45,6 @@ namespace lldb_private { class Trace : public PluginInterface, public std::enable_shared_from_this { public: - enum class TraceDirection { - Forwards = 0, - Backwards, - }; - /// Dump the trace data that this plug-in has access to. /// /// This function will dump all of the trace data for all threads in a user @@ -137,62 +132,6 @@ class Trace : public PluginInterface, /// The JSON schema of this Trace plug-in. virtual llvm::StringRef GetSchema() = 0; - /// Dump \a count instructions of the given thread's trace ending at the - /// given \a end_position position. - /// - /// The instructions are printed along with their indices or positions, which - /// are increasing chronologically. This means that the \a index 0 represents - /// the oldest instruction of the trace chronologically. - /// - /// \param[in] thread - /// The thread whose trace will be dumped. - /// - /// \param[in] s - /// The stream object where the instructions are printed. - /// - /// \param[in] count - /// The number of instructions to print. - /// - /// \param[in] end_position - /// The position of the last instruction to print. - /// - /// \param[in] raw - /// Dump only instruction addresses without disassembly nor symbol - /// information. - void DumpTraceInstructions(Thread &thread, Stream &s, size_t count, - size_t end_position, bool raw); - - /// Run the provided callback on the instructions of the trace of the given - /// thread. - /// - /// The instructions will be traversed starting at the given \a position - /// sequentially until the callback returns \b false, in which case no more - /// instructions are inspected. - /// - /// The purpose of this method is to allow inspecting traced instructions - /// without exposing the internal representation of how they are stored on - /// memory. - /// - /// \param[in] thread - /// The thread whose trace will be traversed. - /// - /// \param[in] position - /// The instruction position to start iterating on. - /// - /// \param[in] direction - /// If \b TraceDirection::Forwards, then then instructions will be - /// traversed forwards chronologically, i.e. with incrementing indices. If - /// \b TraceDirection::Backwards, the traversal is done backwards - /// chronologically, i.e. with decrementing indices. - /// - /// \param[in] callback - /// The callback to execute on each instruction. If it returns \b false, - /// the iteration stops. - virtual void TraverseInstructions( - Thread &thread, size_t position, TraceDirection direction, - std::function load_addr)> - callback) = 0; - /// Get a \a TraceCursor for the given thread's trace. /// /// \return @@ -201,16 +140,6 @@ class Trace : public PluginInterface, /// trace. virtual lldb::TraceCursorUP GetCursor(Thread &thread) = 0; - /// Get the number of available instructions in the trace of the given thread. - /// - /// \param[in] thread - /// The thread whose trace will be inspected. - /// - /// \return - /// The total number of instructions in the trace, or \a llvm::None if the - /// thread is not being traced. - virtual llvm::Optional GetInstructionCount(Thread &thread) = 0; - /// Check if a thread is currently traced by this object. /// /// \param[in] thread diff --git a/lldb/include/lldb/Target/TraceCursor.h b/lldb/include/lldb/Target/TraceCursor.h index c27bba3abf4cb..e15ced82a470f 100644 --- a/lldb/include/lldb/Target/TraceCursor.h +++ b/lldb/include/lldb/Target/TraceCursor.h @@ -11,6 +11,8 @@ #include "lldb/lldb-private.h" +#include "lldb/Target/ExecutionContext.h" + namespace lldb_private { /// Class used for iterating over the instructions of a thread's trace. @@ -36,74 +38,134 @@ namespace lldb_private { /// A \a TraceCursor always points to a specific instruction or error in the /// trace. /// -/// The Trace initially points to the last item in the trace. +/// Defaults: +/// By default, the cursor points at the end item of the trace, moves +/// backwards, has a move granularity of \a +/// eTraceInstructionControlFlowTypeInstruction (i.e. visit every instruction) +/// and stops at every error (the "ignore errors" flag is \b false). See the +/// \a TraceCursor::Next() method for more documentation. /// /// Sample usage: /// /// TraceCursorUP cursor = trace.GetTrace(thread); /// -/// auto granularity = eTraceInstructionControlFlowTypeCall | -/// eTraceInstructionControlFlowTypeReturn; +/// cursor->SetGranularity(eTraceInstructionControlFlowTypeCall | +/// eTraceInstructionControlFlowTypeReturn); /// /// do { /// if (llvm::Error error = cursor->GetError()) /// cout << "error found at: " << llvm::toString(error) << endl; /// else if (cursor->GetInstructionControlFlowType() & -/// eTraceInstructionControlFlowTypeCall) +/// eTraceInstructionControlFlowTypeCall) /// std::cout << "call found at " << cursor->GetLoadAddress() << /// std::endl; /// else if (cursor->GetInstructionControlFlowType() & -/// eTraceInstructionControlFlowTypeReturn) +/// eTraceInstructionControlFlowTypeReturn) /// std::cout << "return found at " << cursor->GetLoadAddress() << /// std::endl; -/// } while(cursor->Prev(granularity)); +/// } while(cursor->Next()); +/// +/// Low level traversal: +/// Unlike the \a TraceCursor::Next() API, which uses a given granularity and +/// direction to advance the cursor, the \a TraceCursor::Seek() method can be +/// used to reposition the cursor to an offset of the end, beginning, or +/// current position of the trace. class TraceCursor { public: + /// Helper enum to indicate the reference point when invoking + /// \a TraceCursor::Seek(). + enum class SeekType { + /// The beginning of the trace, i.e the oldest item. + Set = 0, + /// The current position in the trace. + Current, + /// The end of the trace, i.e the most recent item. + End + }; + + /// Create a cursor that initially points to the end of the trace, i.e. the + /// most recent item. + TraceCursor(lldb::ThreadSP thread_sp); + virtual ~TraceCursor() = default; - /// Move the cursor to the next instruction more recent chronologically in the - /// trace given the provided granularity. If such instruction is not found, - /// the cursor doesn't move. + /// Set the granularity to use in the \a TraceCursor::Next() method. + void SetGranularity(lldb::TraceInstructionControlFlowType granularity); + + /// Set the "ignore errors" flag to use in the \a TraceCursor::Next() method. + void SetIgnoreErrors(bool ignore_errors); + + /// Set the direction to use in the \a TraceCursor::Next() method. + /// + /// \param[in] forwards + /// If \b true, then the traversal will be forwards, otherwise backwards. + void SetForwards(bool forwards); + + /// Check if the direction to use in the \a TraceCursor::Next() method is + /// forwards. + /// + /// \return + /// \b true if the current direction is forwards, \b false if backwards. + bool IsForwards() const; + + /// Move the cursor to the next instruction that matches the current + /// granularity. + /// + /// Direction: + /// The traversal is done following the current direction of the trace. If + /// it is forwards, the instructions are visited forwards + /// chronologically. Otherwise, the traversal is done in + /// the opposite direction. By default, a cursor moves backwards unless + /// changed with \a TraceCursor::SetForwards(). + /// + /// Granularity: + /// The cursor will traverse the trace looking for the first instruction + /// that matches the current granularity. If there aren't any matching + /// instructions, the cursor won't move, to give the opportunity of + /// changing granularities. + /// + /// Ignore errors: + /// If the "ignore errors" flags is \b false, the traversal will stop as + /// soon as it finds an error in the trace and the cursor will point at + /// it. + /// + /// \return + /// \b true if the cursor effectively moved, \b false otherwise. + virtual bool Next() = 0; + + /// Make the cursor point to an item in the trace based on an origin point and + /// an offset. This API doesn't distinguishes instruction types nor errors in + /// the trace, unlike the \a TraceCursor::Next() method. + /// + /// The resulting position of the trace is + /// origin + offset /// - /// \param[in] granularity - /// Bitmask granularity filter. The cursor stops at the next - /// instruction that matches the specified granularity. + /// If this resulting position would be out of bounds, it will be adjusted to + /// the last or first item in the trace correspondingly. /// - /// \param[in] ignore_errors - /// If \b false, the cursor stops as soon as it finds a failure in the - /// trace and points at it. + /// \param[in] offset + /// How many items to move forwards (if positive) or backwards (if + /// negative) from the given origin point. + /// + /// \param[in] origin + /// The reference point to use when moving the cursor. /// /// \return - /// \b true if the cursor effectively moved and now points to a different - /// item in the trace, including errors when \b ignore_errors is \b false. - /// In other words, if \b false is returned, then the trace is pointing at - /// the same item in the trace as before. - virtual bool Next(lldb::TraceInstructionControlFlowType granularity = - lldb::eTraceInstructionControlFlowTypeInstruction, - bool ignore_errors = false) = 0; - - /// Similar to \a TraceCursor::Next(), but moves backwards chronologically. - virtual bool Prev(lldb::TraceInstructionControlFlowType granularity = - lldb::eTraceInstructionControlFlowTypeInstruction, - bool ignore_errors = false) = 0; - - /// Force the cursor to point to the end of the trace, i.e. the most recent - /// item. - virtual void SeekToEnd() = 0; - - /// Force the cursor to point to the beginning of the trace, i.e. the oldest - /// item. - virtual void SeekToBegin() = 0; + /// The number of trace items moved from the origin. + virtual size_t Seek(ssize_t offset, SeekType origin) = 0; /// \return - /// \b true if the trace corresponds to a live process who has resumed after - /// the trace cursor was created. Otherwise, including the case in which the - /// process is a post-mortem one, return \b false. - bool IsStale(); + /// The \a ExecutionContextRef of the backing thread from the creation time + /// of this cursor. + ExecutionContextRef &GetExecutionContextRef(); /// Instruction or error information /// \{ + /// \return + /// Whether the cursor points to an error or not. + virtual bool IsError() = 0; + /// Get the corresponding error message if the cursor points to an error in /// the trace. /// @@ -124,14 +186,15 @@ class TraceCursor { /// to an error in the trace, return \b 0. virtual lldb::TraceInstructionControlFlowType GetInstructionControlFlowType() = 0; - /// \} -private: - /// The stop ID when the cursor was created. - uint32_t m_stop_id = 0; - /// The trace that owns this cursor. - lldb::TraceSP m_trace_sp; +protected: + ExecutionContextRef m_exe_ctx_ref; + + lldb::TraceInstructionControlFlowType m_granularity = + lldb::eTraceInstructionControlFlowTypeInstruction; + bool m_ignore_errors = false; + bool m_forwards = false; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Target/TraceInstructionDumper.h b/lldb/include/lldb/Target/TraceInstructionDumper.h new file mode 100644 index 0000000000000..388e5063d1725 --- /dev/null +++ b/lldb/include/lldb/Target/TraceInstructionDumper.h @@ -0,0 +1,72 @@ +//===-- TraceInstructionDumper.h --------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/TraceCursor.h" + +#ifndef LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H +#define LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H + +namespace lldb_private { + +/// Class used to dump the instructions of a \a TraceCursor using its current +/// state and granularity. +class TraceInstructionDumper { +public: + /// Create a instruction dumper for the cursor. + /// + /// \param[in] cursor + /// The cursor whose instructions will be dumped. + /// + /// \param[in] initial_index + /// Presentation index to use for referring to the current instruction + /// of the cursor. If the direction is forwards, the index will increase, + /// and if the direction is backwards, the index will decrease. + /// + /// \param[in] raw + /// Dump only instruction addresses without disassembly nor symbol + /// information. + TraceInstructionDumper(lldb::TraceCursorUP &&cursor_up, int initial_index = 0, + bool raw = false); + + /// Dump \a count instructions of the thread trace starting at the current + /// cursor position. + /// + /// This effectively moves the cursor to the next unvisited position, so that + /// a subsequent call to this method continues where it left off. + /// + /// \param[in] s + /// The stream object where the instructions are printed. + /// + /// \param[in] count + /// The number of instructions to print. + void DumpInstructions(Stream &s, size_t count); + + /// Indicate the dumper that no more data is available in the trace. + void SetNoMoreData(); + + /// \return + /// \b true if there's still more data to traverse in the trace. + bool HasMoreData(); + +private: + /// Move the cursor one step. + /// + /// \return + /// \b true if the cursor moved. + bool TryMoveOneStep(); + + lldb::TraceCursorUP m_cursor_up; + int m_index; + bool m_raw; + /// If \b true, all the instructions have been traversed. + bool m_no_more_data = false; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index f0c7c5f75a2e5..47c35a23b0781 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -1288,6 +1288,51 @@ lldb::SBProcessInfo SBProcess::GetProcessInfo() { return LLDB_RECORD_RESULT(sb_proc_info); } +lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions, + lldb::SBError &sb_error) { + LLDB_RECORD_METHOD(lldb::addr_t, SBProcess, AllocateMemory, + (size_t, uint32_t, lldb::SBError &), size, permissions, + sb_error); + + lldb::addr_t addr = LLDB_INVALID_ADDRESS; + ProcessSP process_sp(GetSP()); + if (process_sp) { + Process::StopLocker stop_locker; + if (stop_locker.TryLock(&process_sp->GetRunLock())) { + std::lock_guard guard( + process_sp->GetTarget().GetAPIMutex()); + addr = process_sp->AllocateMemory(size, permissions, sb_error.ref()); + } else { + sb_error.SetErrorString("process is running"); + } + } else { + sb_error.SetErrorString("SBProcess is invalid"); + } + return addr; +} + +lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) { + LLDB_RECORD_METHOD(lldb::SBError, SBProcess, DeallocateMemory, (lldb::addr_t), + ptr); + + lldb::SBError sb_error; + ProcessSP process_sp(GetSP()); + if (process_sp) { + Process::StopLocker stop_locker; + if (stop_locker.TryLock(&process_sp->GetRunLock())) { + std::lock_guard guard( + process_sp->GetTarget().GetAPIMutex()); + Status error = process_sp->DeallocateMemory(ptr); + sb_error.SetError(error); + } else { + sb_error.SetErrorString("process is running"); + } + } else { + sb_error.SetErrorString("SBProcess is invalid"); + } + return sb_error; +} + namespace lldb_private { namespace repro { @@ -1417,6 +1462,10 @@ void RegisterMethods(Registry &R) { LLDB_REGISTER_METHOD(lldb::SBMemoryRegionInfoList, SBProcess, GetMemoryRegions, ()); LLDB_REGISTER_METHOD(lldb::SBProcessInfo, SBProcess, GetProcessInfo, ()); + LLDB_REGISTER_METHOD(lldb::addr_t, SBProcess, AllocateMemory, + (size_t, uint32_t, lldb::SBError &)); + LLDB_REGISTER_METHOD(lldb::SBError, SBProcess, DeallocateMemory, + (lldb::addr_t)); LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDOUT); LLDB_REGISTER_CHAR_PTR_METHOD_CONST(size_t, SBProcess, GetSTDERR); diff --git a/lldb/source/Commands/CommandObjectMemoryTag.cpp b/lldb/source/Commands/CommandObjectMemoryTag.cpp index 07dccf5c16fb0..1dfb32a92f3bb 100644 --- a/lldb/source/Commands/CommandObjectMemoryTag.cpp +++ b/lldb/source/Commands/CommandObjectMemoryTag.cpp @@ -68,7 +68,7 @@ class CommandObjectMemoryTagRead : public CommandObjectParsed { Process *process = m_exe_ctx.GetProcessPtr(); llvm::Expected tag_manager_or_err = - process->GetMemoryTagManager(start_addr, end_addr); + process->GetMemoryTagManager(); if (!tag_manager_or_err) { result.SetError(Status(tag_manager_or_err.takeError())); @@ -76,9 +76,21 @@ class CommandObjectMemoryTagRead : public CommandObjectParsed { } const MemoryTagManager *tag_manager = *tag_manager_or_err; - ptrdiff_t len = tag_manager->AddressDiff(end_addr, start_addr); - llvm::Expected> tags = - process->ReadMemoryTags(tag_manager, start_addr, len); + + MemoryRegionInfos memory_regions; + // If this fails the list of regions is cleared, so we don't need to read + // the return status here. + process->GetMemoryRegions(memory_regions); + llvm::Expected tagged_range = + tag_manager->MakeTaggedRange(start_addr, end_addr, memory_regions); + + if (!tagged_range) { + result.SetError(Status(tagged_range.takeError())); + return false; + } + + llvm::Expected> tags = process->ReadMemoryTags( + tagged_range->GetRangeBase(), tagged_range->GetByteSize()); if (!tags) { result.SetError(Status(tags.takeError())); @@ -89,8 +101,7 @@ class CommandObjectMemoryTagRead : public CommandObjectParsed { tag_manager->GetLogicalTag(start_addr)); result.AppendMessage("Allocation tags:"); - MemoryTagManager::TagRange initial_range(start_addr, len); - addr_t addr = tag_manager->ExpandToGranule(initial_range).GetRangeBase(); + addr_t addr = tagged_range->GetRangeBase(); for (auto tag : *tags) { addr_t next_addr = addr + tag_manager->GetGranuleSize(); // Showing tagged adresses here until we have non address bit handling diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 292f9c6a0a74e..e4cf8a411b22b 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -8,6 +8,7 @@ #include "CommandObjectThread.h" +#include #include #include "CommandObjectThreadUtil.h" @@ -32,6 +33,7 @@ #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanStepInRange.h" #include "lldb/Target/Trace.h" +#include "lldb/Target/TraceInstructionDumper.h" #include "lldb/Utility/State.h" using namespace lldb; @@ -2004,21 +2006,24 @@ class CommandObjectTraceDumpInstructions m_count = count; break; } - case 'p': { - int32_t position; - if (option_arg.empty() || option_arg.getAsInteger(0, position) || - position < 0) + case 's': { + int32_t skip; + if (option_arg.empty() || option_arg.getAsInteger(0, skip) || skip < 0) error.SetErrorStringWithFormat( "invalid integer value for option '%s'", option_arg.str().c_str()); else - m_position = position; + m_skip = skip; break; } case 'r': { m_raw = true; break; } + case 'f': { + m_forwards = true; + break; + } default: llvm_unreachable("Unimplemented option"); } @@ -2027,8 +2032,9 @@ class CommandObjectTraceDumpInstructions void OptionParsingStarting(ExecutionContext *execution_context) override { m_count = kDefaultCount; - m_position = llvm::None; + m_skip = 0; m_raw = false; + m_forwards = false; } llvm::ArrayRef GetDefinitions() override { @@ -2039,14 +2045,15 @@ class CommandObjectTraceDumpInstructions // Instance variables to hold the values for command options. size_t m_count; - llvm::Optional m_position; + size_t m_skip; bool m_raw; + bool m_forwards; }; CommandObjectTraceDumpInstructions(CommandInterpreter &interpreter) : CommandObjectIterateOverThreads( interpreter, "thread trace dump instructions", - "Dump the traced instructions for one or more threads. If no " + "Dump the traced instructions for one or more threads. If no " "threads are specified, show the current thread. Use the " "thread-index \"all\" to see all threads.", nullptr, @@ -2063,14 +2070,14 @@ class CommandObjectTraceDumpInstructions uint32_t index) override { current_command_args.GetCommandString(m_repeat_command); m_create_repeat_command_just_invoked = true; - m_consecutive_repetitions = 0; return m_repeat_command.c_str(); } protected: bool DoExecute(Args &args, CommandReturnObject &result) override { - if (IsRepeatCommand()) - m_consecutive_repetitions++; + if (!IsRepeatCommand()) + m_dumpers.clear(); + bool status = CommandObjectIterateOverThreads::DoExecute(args, result); m_create_repeat_command_just_invoked = false; @@ -2082,24 +2089,37 @@ class CommandObjectTraceDumpInstructions } bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { + Stream &s = result.GetOutputStream(); + const TraceSP &trace_sp = m_exe_ctx.GetTargetSP()->GetTrace(); ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); - if (llvm::Optional insn_count = - trace_sp->GetInstructionCount(*thread_sp)) { - size_t count = m_options.m_count; - ssize_t position = - m_options.m_position.getValueOr((ssize_t)*insn_count - 1) - - m_consecutive_repetitions * count; - if (position < 0) - result.AppendError("error: no more data"); - else - trace_sp->DumpTraceInstructions(*thread_sp, result.GetOutputStream(), - count, position, m_options.m_raw); - } else { - result.AppendError("error: not traced"); + if (!m_dumpers.count(thread_sp->GetID())) { + lldb::TraceCursorUP cursor_up = trace_sp->GetCursor(*thread_sp); + // Set up the cursor and return the presentation index of the first + // instruction to dump after skipping instructions. + auto setUpCursor = [&]() { + cursor_up->SetForwards(m_options.m_forwards); + if (m_options.m_forwards) + return cursor_up->Seek(m_options.m_skip, TraceCursor::SeekType::Set); + return -cursor_up->Seek(-m_options.m_skip, TraceCursor::SeekType::End); + }; + + int initial_index = setUpCursor(); + + auto dumper = std::make_unique( + std::move(cursor_up), initial_index, m_options.m_raw); + + // This happens when the seek value was more than the number of available + // instructions. + if (std::abs(initial_index) < (int)m_options.m_skip) + dumper->SetNoMoreData(); + + m_dumpers[thread_sp->GetID()] = std::move(dumper); } + + m_dumpers[thread_sp->GetID()]->DumpInstructions(s, m_options.m_count); return true; } @@ -2108,7 +2128,7 @@ class CommandObjectTraceDumpInstructions // Repeat command helpers std::string m_repeat_command; bool m_create_repeat_command_just_invoked; - size_t m_consecutive_repetitions = 0; + std::map> m_dumpers; }; // CommandObjectMultiwordTraceDump diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 57208c5b30450..36b5a82a8831b 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -1049,13 +1049,19 @@ let Command = "thread plan list" in { } let Command = "thread trace dump instructions" in { + def thread_trace_dump_instructions_forwards: Option<"forwards", "f">, Group<1>, + Desc<"If specified, the trace is traversed forwards chronologically " + "starting at the oldest instruction. Otherwise, it starts at the most " + "recent one and the traversal is backwards.">; def thread_trace_dump_instructions_count : Option<"count", "c">, Group<1>, Arg<"Count">, - Desc<"The number of instructions to display ending at the current position.">; - def thread_trace_dump_instructions_position : Option<"position", "p">, + Desc<"The number of instructions to display starting at the most recent " + "instruction, or the oldest if --forwards is provided.">; + def thread_trace_dump_instructions_skip: Option<"skip", "s">, Group<1>, Arg<"Index">, - Desc<"The position to use instead of the current position of the trace.">; + Desc<"How many instruction to skip from the end of the trace to start " + "dumping instructions, or from the beginning if --forwards is provided">; def thread_trace_dump_instructions_raw : Option<"raw", "r">, Group<1>, Desc<"Dump only instruction address without disassembly nor symbol information.">; diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 12210ed541bc1..17c3ba426f719 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -773,12 +773,9 @@ void Debugger::Clear() { StopIOHandlerThread(); StopEventHandlerThread(); m_listener_sp->Clear(); - int num_targets = m_target_list.GetNumTargets(); - for (int i = 0; i < num_targets; i++) { - TargetSP target_sp(m_target_list.GetTargetAtIndex(i)); + for (TargetSP target_sp : m_target_list.Targets()) { if (target_sp) { - ProcessSP process_sp(target_sp->GetProcessSP()); - if (process_sp) + if (ProcessSP process_sp = target_sp->GetProcessSP()) process_sp->Finalize(); target_sp->Destroy(); } diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index d37271bd1e53a..d54c27cea0c80 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -40,6 +40,7 @@ #if LLDB_ENABLE_CURSES #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Symbol/Block.h" @@ -67,7 +68,6 @@ #include #include #include -#include #include #include #include @@ -608,9 +608,19 @@ class Window : public Surface { m_delete = del; } } - // + // Get the rectangle in our parent window Rect GetBounds() const { return Rect(GetParentOrigin(), GetSize()); } + + Rect GetCenteredRect(int width, int height) { + Size size = GetSize(); + width = std::min(size.width, width); + height = std::min(size.height, height); + int x = (size.width - width) / 2; + int y = (size.height - height) / 2; + return Rect(Point(x, y), Size(width, height)); + } + int GetChar() { return ::wgetch(m_window); } Point GetParentOrigin() const { return Point(GetParentX(), GetParentY()); } int GetParentX() const { return getparx(m_window); } @@ -1050,9 +1060,18 @@ class FieldDelegate { // Select the last element in the field if multiple elements exists. virtual void FieldDelegateSelectLastElement() { return; } + + bool FieldDelegateIsVisible() { return m_is_visible; } + + void FieldDelegateHide() { m_is_visible = false; } + + void FieldDelegateShow() { m_is_visible = true; } + +protected: + bool m_is_visible = true; }; -typedef std::shared_ptr FieldDelegateSP; +typedef std::unique_ptr FieldDelegateUP; class TextFieldDelegate : public FieldDelegate { public: @@ -1227,7 +1246,6 @@ class TextFieldDelegate : public FieldDelegate { void SetError(const char *error) { m_error = error; } - // Returns the text content of the field. const std::string &GetText() { return m_content; } protected: @@ -1634,7 +1652,7 @@ template class ListFieldDelegate : public FieldDelegate { m_selection_type = SelectionType::NewButton; } - HandleCharResult SelecteNext(int key) { + HandleCharResult SelectNext(int key) { if (m_selection_type == SelectionType::NewButton) return eKeyNotHandled; @@ -1707,7 +1725,7 @@ template class ListFieldDelegate : public FieldDelegate { } break; case '\t': - SelecteNext(key); + SelectNext(key); return eKeyHandled; case KEY_SHIFT_TAB: SelectPrevious(key); @@ -1812,7 +1830,15 @@ class FormDelegate { virtual ~FormDelegate() = default; - FieldDelegateSP &GetField(int field_index) { return m_fields[field_index]; } + virtual std::string GetName() = 0; + + virtual void UpdateFieldsVisibility() { return; } + + FieldDelegate *GetField(uint32_t field_index) { + if (field_index < m_fields.size()) + return m_fields[field_index].get(); + return nullptr; + } FormAction &GetAction(int action_index) { return m_actions[action_index]; } @@ -1832,8 +1858,7 @@ class FormDelegate { TextFieldDelegate *AddTextField(const char *label, const char *content) { TextFieldDelegate *delegate = new TextFieldDelegate(label, content); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } @@ -1841,8 +1866,7 @@ class FormDelegate { bool need_to_exist = true) { FileFieldDelegate *delegate = new FileFieldDelegate(label, content, need_to_exist); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } @@ -1851,22 +1875,19 @@ class FormDelegate { bool need_to_exist = true) { DirectoryFieldDelegate *delegate = new DirectoryFieldDelegate(label, content, need_to_exist); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } IntegerFieldDelegate *AddIntegerField(const char *label, int content) { IntegerFieldDelegate *delegate = new IntegerFieldDelegate(label, content); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } BooleanFieldDelegate *AddBooleanField(const char *label, bool content) { BooleanFieldDelegate *delegate = new BooleanFieldDelegate(label, content); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } @@ -1874,8 +1895,7 @@ class FormDelegate { std::vector choices) { ChoicesFieldDelegate *delegate = new ChoicesFieldDelegate(label, height, choices); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } @@ -1883,8 +1903,7 @@ class FormDelegate { ListFieldDelegate *AddListField(const char *label, T default_field) { ListFieldDelegate *delegate = new ListFieldDelegate(label, default_field); - FieldDelegateSP delegate_sp = FieldDelegateSP(delegate); - m_fields.push_back(delegate_sp); + m_fields.push_back(FieldDelegateUP(delegate)); return delegate; } @@ -1895,7 +1914,7 @@ class FormDelegate { } protected: - std::vector m_fields; + std::vector m_fields; std::vector m_actions; // Optional error message. If empty, form is considered to have no error. std::string m_error; @@ -1907,7 +1926,13 @@ class FormWindowDelegate : public WindowDelegate { public: FormWindowDelegate(FormDelegateSP &delegate_sp) : m_delegate_sp(delegate_sp), m_selection_index(0), - m_selection_type(SelectionType::Field), m_first_visible_line(0) {} + m_first_visible_line(0) { + assert(m_delegate_sp->GetNumberOfActions() > 0); + if (m_delegate_sp->GetNumberOfFields() > 0) + m_selection_type = SelectionType::Field; + else + m_selection_type = SelectionType::Action; + } // Signify which element is selected. If a field or an action is selected, // then m_selection_index signifies the particular field or action that is @@ -1948,6 +1973,8 @@ class FormWindowDelegate : public WindowDelegate { int height = 0; height += GetErrorHeight(); for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) { + if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible()) + continue; height += m_delegate_sp->GetField(i)->FieldDelegateGetHeight(); } height += GetActionsHeight(); @@ -1958,11 +1985,13 @@ class FormWindowDelegate : public WindowDelegate { if (m_selection_type == SelectionType::Action) return ScrollContext(GetContentHeight() - 1); - FieldDelegateSP &field = m_delegate_sp->GetField(m_selection_index); + FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); ScrollContext context = field->FieldDelegateGetScrollContext(); int offset = GetErrorHeight(); for (int i = 0; i < m_selection_index; i++) { + if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible()) + continue; offset += m_delegate_sp->GetField(i)->FieldDelegateGetHeight(); } context.Offset(offset); @@ -2018,8 +2047,10 @@ class FormWindowDelegate : public WindowDelegate { int width = surface.GetWidth(); bool a_field_is_selected = m_selection_type == SelectionType::Field; for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) { + FieldDelegate *field = m_delegate_sp->GetField(i); + if (!field->FieldDelegateIsVisible()) + continue; bool is_field_selected = a_field_is_selected && m_selection_index == i; - FieldDelegateSP &field = m_delegate_sp->GetField(i); int height = field->FieldDelegateGetHeight(); Rect bounds = Rect(Point(0, line), Size(width, height)); SubPad field_surface = SubPad(surface, bounds); @@ -2080,10 +2111,12 @@ class FormWindowDelegate : public WindowDelegate { } bool WindowDelegateDraw(Window &window, bool force) override { + m_delegate_sp->UpdateFieldsVisibility(); window.Erase(); - window.DrawTitleBox(window.GetName(), "Press Esc to cancel"); + window.DrawTitleBox(m_delegate_sp->GetName().c_str(), + "Press Esc to cancel"); Rect content_bounds = window.GetFrame(); content_bounds.Inset(2, 2); @@ -2093,7 +2126,22 @@ class FormWindowDelegate : public WindowDelegate { return true; } - HandleCharResult SelecteNext(int key) { + void SkipNextHiddenFields() { + while (true) { + if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible()) + return; + + if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) { + m_selection_type = SelectionType::Action; + m_selection_index = 0; + return; + } + + m_selection_index++; + } + } + + HandleCharResult SelectNext(int key) { if (m_selection_type == SelectionType::Action) { if (m_selection_index < m_delegate_sp->GetNumberOfActions() - 1) { m_selection_index++; @@ -2102,12 +2150,15 @@ class FormWindowDelegate : public WindowDelegate { m_selection_index = 0; m_selection_type = SelectionType::Field; - FieldDelegateSP &next_field = m_delegate_sp->GetField(m_selection_index); - next_field->FieldDelegateSelectFirstElement(); + SkipNextHiddenFields(); + if (m_selection_type == SelectionType::Field) { + FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index); + next_field->FieldDelegateSelectFirstElement(); + } return eKeyHandled; } - FieldDelegateSP &field = m_delegate_sp->GetField(m_selection_index); + FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); if (!field->FieldDelegateOnLastOrOnlyElement()) { return field->FieldDelegateHandleChar(key); } @@ -2121,14 +2172,32 @@ class FormWindowDelegate : public WindowDelegate { } m_selection_index++; + SkipNextHiddenFields(); - FieldDelegateSP &next_field = m_delegate_sp->GetField(m_selection_index); - next_field->FieldDelegateSelectFirstElement(); + if (m_selection_type == SelectionType::Field) { + FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index); + next_field->FieldDelegateSelectFirstElement(); + } return eKeyHandled; } - HandleCharResult SelectePrevious(int key) { + void SkipPreviousHiddenFields() { + while (true) { + if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible()) + return; + + if (m_selection_index == 0) { + m_selection_type = SelectionType::Action; + m_selection_index = 0; + return; + } + + m_selection_index--; + } + } + + HandleCharResult SelectPrevious(int key) { if (m_selection_type == SelectionType::Action) { if (m_selection_index > 0) { m_selection_index--; @@ -2136,13 +2205,16 @@ class FormWindowDelegate : public WindowDelegate { } m_selection_index = m_delegate_sp->GetNumberOfFields() - 1; m_selection_type = SelectionType::Field; - FieldDelegateSP &previous_field = - m_delegate_sp->GetField(m_selection_index); - previous_field->FieldDelegateSelectLastElement(); + SkipPreviousHiddenFields(); + if (m_selection_type == SelectionType::Field) { + FieldDelegate *previous_field = + m_delegate_sp->GetField(m_selection_index); + previous_field->FieldDelegateSelectLastElement(); + } return eKeyHandled; } - FieldDelegateSP &field = m_delegate_sp->GetField(m_selection_index); + FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); if (!field->FieldDelegateOnFirstOrOnlyElement()) { return field->FieldDelegateHandleChar(key); } @@ -2156,10 +2228,13 @@ class FormWindowDelegate : public WindowDelegate { } m_selection_index--; + SkipPreviousHiddenFields(); - FieldDelegateSP &previous_field = - m_delegate_sp->GetField(m_selection_index); - previous_field->FieldDelegateSelectLastElement(); + if (m_selection_type == SelectionType::Field) { + FieldDelegate *previous_field = + m_delegate_sp->GetField(m_selection_index); + previous_field->FieldDelegateSelectLastElement(); + } return eKeyHandled; } @@ -2167,9 +2242,11 @@ class FormWindowDelegate : public WindowDelegate { void ExecuteAction(Window &window) { FormAction &action = m_delegate_sp->GetAction(m_selection_index); action.Execute(window); - m_first_visible_line = 0; - m_selection_index = 0; - m_selection_type = SelectionType::Field; + if (m_delegate_sp->HasError()) { + m_first_visible_line = 0; + m_selection_index = 0; + m_selection_type = SelectionType::Field; + } } HandleCharResult WindowDelegateHandleChar(Window &window, int key) override { @@ -2183,9 +2260,9 @@ class FormWindowDelegate : public WindowDelegate { } break; case '\t': - return SelecteNext(key); + return SelectNext(key); case KEY_SHIFT_TAB: - return SelectePrevious(key); + return SelectPrevious(key); case KEY_ESCAPE: window.GetParent()->RemoveSubWindow(&window); return eKeyHandled; @@ -2196,7 +2273,7 @@ class FormWindowDelegate : public WindowDelegate { // If the key wasn't handled and one of the fields is selected, pass the key // to that field. if (m_selection_type == SelectionType::Field) { - FieldDelegateSP &field = m_delegate_sp->GetField(m_selection_index); + FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); return field->FieldDelegateHandleChar(key); } @@ -2213,6 +2290,223 @@ class FormWindowDelegate : public WindowDelegate { int m_first_visible_line; }; +/////////////////////////// +// Form Delegate Instances +/////////////////////////// + +class DetachOrKillProcessFormDelegate : public FormDelegate { +public: + DetachOrKillProcessFormDelegate(Process *process) : m_process(process) { + SetError("There is a running process, either detach or kill it."); + + m_keep_stopped_field = + AddBooleanField("Keep process stopped when detaching.", false); + + AddAction("Detach", [this](Window &window) { Detach(window); }); + AddAction("Kill", [this](Window &window) { Kill(window); }); + } + + std::string GetName() override { return "Detach/Kill Process"; } + + void Kill(Window &window) { + Status destroy_status(m_process->Destroy(false)); + if (destroy_status.Fail()) { + SetError("Failed to kill process."); + return; + } + window.GetParent()->RemoveSubWindow(&window); + } + + void Detach(Window &window) { + Status detach_status(m_process->Detach(m_keep_stopped_field->GetBoolean())); + if (detach_status.Fail()) { + SetError("Failed to detach from process."); + return; + } + window.GetParent()->RemoveSubWindow(&window); + } + +protected: + Process *m_process; + BooleanFieldDelegate *m_keep_stopped_field; +}; + +class ProcessAttachFormDelegate : public FormDelegate { +public: + ProcessAttachFormDelegate(Debugger &debugger, WindowSP main_window_sp) + : m_debugger(debugger), m_main_window_sp(main_window_sp) { + std::vector types; + types.push_back(std::string("Name")); + types.push_back(std::string("PID")); + m_type_field = AddChoicesField("Attach By", 2, types); + m_pid_field = AddIntegerField("PID", 0); + m_name_field = + AddTextField("Process Name", GetDefaultProcessName().c_str()); + m_continue_field = AddBooleanField("Continue once attached.", false); + m_wait_for_field = AddBooleanField("Wait for process to launch.", false); + m_include_existing_field = + AddBooleanField("Include existing processes.", false); + m_show_advanced_field = AddBooleanField("Show advanced settings.", false); + m_plugin_field = + AddChoicesField("Plugin Name", 3, GetPossiblePluginNames()); + + AddAction("Attach", [this](Window &window) { Attach(window); }); + } + + std::string GetName() override { return "Attach Process"; } + + void UpdateFieldsVisibility() override { + if (m_type_field->GetChoiceContent() == "Name") { + m_pid_field->FieldDelegateHide(); + m_name_field->FieldDelegateShow(); + m_wait_for_field->FieldDelegateShow(); + if (m_wait_for_field->GetBoolean()) + m_include_existing_field->FieldDelegateShow(); + else + m_include_existing_field->FieldDelegateHide(); + } else { + m_pid_field->FieldDelegateShow(); + m_name_field->FieldDelegateHide(); + m_wait_for_field->FieldDelegateHide(); + m_include_existing_field->FieldDelegateHide(); + } + if (m_show_advanced_field->GetBoolean()) + m_plugin_field->FieldDelegateShow(); + else + m_plugin_field->FieldDelegateHide(); + } + + // Get the basename of the target's main executable if available, empty string + // otherwise. + std::string GetDefaultProcessName() { + Target *target = m_debugger.GetSelectedTarget().get(); + if (target == nullptr) + return ""; + + ModuleSP module_sp = target->GetExecutableModule(); + if (!module_sp->IsExecutable()) + return ""; + + return module_sp->GetFileSpec().GetFilename().AsCString(); + } + + std::vector GetPossiblePluginNames() { + std::vector names; + names.push_back(""); + + size_t i = 0; + while (auto name = PluginManager::GetProcessPluginNameAtIndex(i++)) + names.push_back(name); + return names; + } + + bool StopRunningProcess() { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + + if (!exe_ctx.HasProcessScope()) + return false; + + Process *process = exe_ctx.GetProcessPtr(); + if (!(process && process->IsAlive())) + return false; + + FormDelegateSP form_delegate_sp = + FormDelegateSP(new DetachOrKillProcessFormDelegate(process)); + Rect bounds = m_main_window_sp->GetCenteredRect(85, 8); + WindowSP form_window_sp = m_main_window_sp->CreateSubWindow( + form_delegate_sp->GetName().c_str(), bounds, true); + WindowDelegateSP window_delegate_sp = + WindowDelegateSP(new FormWindowDelegate(form_delegate_sp)); + form_window_sp->SetDelegate(window_delegate_sp); + + return true; + } + + Target *GetTarget() { + Target *target = m_debugger.GetSelectedTarget().get(); + + if (target != nullptr) + return target; + + TargetSP new_target_sp; + m_debugger.GetTargetList().CreateTarget( + m_debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); + + target = new_target_sp.get(); + + if (target == nullptr) + SetError("Failed to create target."); + + m_debugger.GetTargetList().SetSelectedTarget(new_target_sp); + + return target; + } + + ProcessAttachInfo GetAttachInfo() { + ProcessAttachInfo attach_info; + attach_info.SetContinueOnceAttached(m_continue_field->GetBoolean()); + if (m_type_field->GetChoiceContent() == "Name") { + attach_info.GetExecutableFile().SetFile(m_name_field->GetText(), + FileSpec::Style::native); + attach_info.SetWaitForLaunch(m_wait_for_field->GetBoolean()); + if (m_wait_for_field->GetBoolean()) + attach_info.SetIgnoreExisting(!m_include_existing_field->GetBoolean()); + } else { + attach_info.SetProcessID(m_pid_field->GetInteger()); + } + if (m_plugin_field->GetChoiceContent() != "") + attach_info.SetProcessPluginName(m_plugin_field->GetChoiceContent()); + + return attach_info; + } + + void Attach(Window &window) { + ClearError(); + + bool process_is_running = StopRunningProcess(); + if (process_is_running) + return; + + Target *target = GetTarget(); + if (HasError()) + return; + + StreamString stream; + ProcessAttachInfo attach_info = GetAttachInfo(); + Status status = target->Attach(attach_info, &stream); + + if (status.Fail()) { + SetError(status.AsCString()); + return; + } + + ProcessSP process_sp(target->GetProcessSP()); + if (!process_sp) { + SetError("Attached sucessfully but target has no process."); + return; + } + + if (attach_info.GetContinueOnceAttached()) + process_sp->Resume(); + + window.GetParent()->RemoveSubWindow(&window); + } + +protected: + Debugger &m_debugger; + WindowSP m_main_window_sp; + + ChoicesFieldDelegate *m_type_field; + IntegerFieldDelegate *m_pid_field; + TextFieldDelegate *m_name_field; + BooleanFieldDelegate *m_continue_field; + BooleanFieldDelegate *m_wait_for_field; + BooleanFieldDelegate *m_include_existing_field; + BooleanFieldDelegate *m_show_advanced_field; + ChoicesFieldDelegate *m_plugin_field; +}; + class MenuDelegate { public: virtual ~MenuDelegate() = default; @@ -2627,8 +2921,6 @@ class Application { } void Initialize() { - ::setlocale(LC_ALL, ""); - ::setlocale(LC_CTYPE, ""); m_screen = ::newterm(nullptr, m_out, m_in); ::start_color(); ::curs_set(0); @@ -4462,6 +4754,19 @@ class ApplicationDelegate : public WindowDelegate, public MenuDelegate { } return MenuActionResult::Handled; + case eMenuID_ProcessAttach: { + WindowSP main_window_sp = m_app.GetMainWindow(); + FormDelegateSP form_delegate_sp = FormDelegateSP( + new ProcessAttachFormDelegate(m_debugger, main_window_sp)); + Rect bounds = main_window_sp->GetCenteredRect(80, 22); + WindowSP form_window_sp = main_window_sp->CreateSubWindow( + form_delegate_sp->GetName().c_str(), bounds, true); + WindowDelegateSP window_delegate_sp = + WindowDelegateSP(new FormWindowDelegate(form_delegate_sp)); + form_window_sp->SetDelegate(window_delegate_sp); + return MenuActionResult::Handled; + } + case eMenuID_ProcessContinue: { ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 69c94c36cf0b6..528208665a4e5 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -740,8 +740,8 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); StringExtractorGDBRemote response; - auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", - response, false); + auto result = + m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", response); if (result != decltype(result)::Success || response.GetResponseType() != response.eResponse) diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp index 987a55e7e8575..d74b66b58afc9 100644 --- a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp +++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp @@ -66,16 +66,76 @@ MemoryTagManagerAArch64MTE::ExpandToGranule(TagRange range) const { return TagRange(new_start, new_len); } -llvm::Expected> -MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector &tags, - size_t granules) const { - size_t num_tags = tags.size() / GetTagSizeInBytes(); - if (num_tags != granules) { +llvm::Expected +MemoryTagManagerAArch64MTE::MakeTaggedRange( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const { + // First check that the range is not inverted. + // We must remove tags here otherwise an address with a higher + // tag value will always be > the other. + ptrdiff_t len = AddressDiff(end_addr, addr); + if (len <= 0) { return llvm::createStringError( llvm::inconvertibleErrorCode(), - "Packed tag data size does not match expected number of tags. " - "Expected %zu tag(s) for %zu granules, got %zu tag(s).", - granules, granules, num_tags); + "End address (0x%" PRIx64 + ") must be greater than the start address (0x%" PRIx64 ")", + end_addr, addr); + } + + // Region addresses will not have memory tags. So when searching + // we must use an untagged address. + MemoryRegionInfo::RangeType tag_range(RemoveNonAddressBits(addr), len); + tag_range = ExpandToGranule(tag_range); + + // Make a copy so we can use the original for errors and the final return. + MemoryRegionInfo::RangeType remaining_range(tag_range); + + // While there are parts of the range that don't have a matching tagged memory + // region + while (remaining_range.IsValid()) { + // Search for a region that contains the start of the range + MemoryRegionInfos::const_iterator region = std::find_if( + memory_regions.cbegin(), memory_regions.cend(), + [&remaining_range](const MemoryRegionInfo ®ion) { + return region.GetRange().Contains(remaining_range.GetRangeBase()); + }); + + if (region == memory_regions.cend() || + region->GetMemoryTagged() != MemoryRegionInfo::eYes) { + // Some part of this range is untagged (or unmapped) so error + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Address range 0x%" PRIx64 ":0x%" PRIx64 + " is not in a memory tagged region", + tag_range.GetRangeBase(), + tag_range.GetRangeEnd()); + } + + // We've found some part of the range so remove that part and continue + // searching for the rest. Moving the base "slides" the range so we need to + // save/restore the original end. If old_end is less than the new base, the + // range will be set to have 0 size and we'll exit the while. + lldb::addr_t old_end = remaining_range.GetRangeEnd(); + remaining_range.SetRangeBase(region->GetRange().GetRangeEnd()); + remaining_range.SetRangeEnd(old_end); + } + + // Every part of the range is contained within a tagged memory region. + return tag_range; +} + +llvm::Expected> +MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector &tags, + size_t granules /*=0*/) const { + // 0 means don't check the number of tags before unpacking + if (granules) { + size_t num_tags = tags.size() / GetTagSizeInBytes(); + if (num_tags != granules) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Packed tag data size does not match expected number of tags. " + "Expected %zu tag(s) for %zu granule(s), got %zu tag(s).", + granules, granules, num_tags); + } } // (if bytes per tag was not 1, we would reconstruct them here) @@ -95,3 +155,46 @@ MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector &tags, return unpacked; } + +llvm::Expected> MemoryTagManagerAArch64MTE::PackTags( + const std::vector &tags) const { + std::vector packed; + packed.reserve(tags.size() * GetTagSizeInBytes()); + + for (auto tag : tags) { + if (tag > MTE_TAG_MAX) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Found tag 0x%" PRIx64 + " which is > max MTE tag value of 0x%x.", + tag, MTE_TAG_MAX); + } + packed.push_back(static_cast(tag)); + } + + return packed; +} + +llvm::Expected> +MemoryTagManagerAArch64MTE::RepeatTagsForRange( + const std::vector &tags, TagRange range) const { + std::vector new_tags; + + // If the range is not empty + if (range.IsValid()) { + if (tags.empty()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Expected some tags to cover given range, got zero."); + } + + // We assume that this range has already been expanded/aligned to granules + size_t granules = range.GetByteSize() / GetGranuleSize(); + new_tags.reserve(granules); + for (size_t to_copy = 0; granules > 0; granules -= to_copy) { + to_copy = granules > tags.size() ? tags.size() : granules; + new_tags.insert(new_tags.end(), tags.begin(), tags.begin() + to_copy); + } + } + + return new_tags; +} diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h index ef1d0791bcd09..d4e8249da93fb 100644 --- a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h +++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h @@ -32,9 +32,20 @@ class MemoryTagManagerAArch64MTE : public MemoryTagManager { TagRange ExpandToGranule(TagRange range) const override; + llvm::Expected MakeTaggedRange( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const override; + llvm::Expected> UnpackTagsData(const std::vector &tags, - size_t granules) const override; + size_t granules = 0) const override; + + llvm::Expected> + PackTags(const std::vector &tags) const override; + + llvm::Expected> + RepeatTagsForRange(const std::vector &tags, + TagRange range) const override; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index fdaa60e2df41e..a4c71e864a767 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -20,7 +20,10 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace std::chrono; -static const seconds kInterruptTimeout(5); +// When we've sent a continue packet and are waiting for the target to stop, +// we wake up the wait with this interval to make sure the stub hasn't gone +// away while we were waiting. +static const seconds kWakeupInterval(5); ///////////////////////// // GDBRemoteClientBase // @@ -35,7 +38,8 @@ GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name, StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( ContinueDelegate &delegate, const UnixSignals &signals, - llvm::StringRef payload, StringExtractorGDBRemote &response) { + llvm::StringRef payload, std::chrono::seconds interrupt_timeout, + StringExtractorGDBRemote &response) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); response.Clear(); @@ -48,16 +52,37 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( if (!cont_lock) return eStateInvalid; OnRunPacketSent(true); - + // The main ReadPacket loop wakes up at computed_timeout intervals, just to + // check that the connection hasn't dropped. When we wake up we also check + // whether there is an interrupt request that has reached its endpoint. + // If we want a shorter interrupt timeout that kWakeupInterval, we need to + // choose the shorter interval for the wake up as well. + std::chrono::seconds computed_timeout = std::min(interrupt_timeout, + kWakeupInterval); for (;;) { - PacketResult read_result = ReadPacket(response, kInterruptTimeout, false); + PacketResult read_result = ReadPacket(response, computed_timeout, false); + // Reset the computed_timeout to the default value in case we are going + // round again. + computed_timeout = std::min(interrupt_timeout, kWakeupInterval); switch (read_result) { case PacketResult::ErrorReplyTimeout: { std::lock_guard lock(m_mutex); - if (m_async_count == 0) + if (m_async_count == 0) { continue; - if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout) + } + auto cur_time = steady_clock::now(); + if (cur_time >= m_interrupt_endpoint) return eStateInvalid; + else { + // We woke up and found an interrupt is in flight, but we haven't + // exceeded the interrupt wait time. So reset the wait time to the + // time left till the interrupt timeout. But don't wait longer + // than our wakeup timeout. + auto new_wait = m_interrupt_endpoint - cur_time; + computed_timeout = std::min(kWakeupInterval, + std::chrono::duration_cast(new_wait)); + continue; + } break; } case PacketResult::Success: @@ -133,8 +158,9 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( } } -bool GDBRemoteClientBase::SendAsyncSignal(int signo) { - Lock lock(*this, true); +bool GDBRemoteClientBase::SendAsyncSignal( + int signo, std::chrono::seconds interrupt_timeout) { + Lock lock(*this, interrupt_timeout); if (!lock || !lock.DidInterrupt()) return false; @@ -144,25 +170,26 @@ bool GDBRemoteClientBase::SendAsyncSignal(int signo) { return true; } -bool GDBRemoteClientBase::Interrupt() { - Lock lock(*this, true); +bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout) { + Lock lock(*this, interrupt_timeout); if (!lock.DidInterrupt()) return false; m_should_stop = true; return true; } + GDBRemoteCommunication::PacketResult GDBRemoteClientBase::SendPacketAndWaitForResponse( llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async) { - Lock lock(*this, send_async); + std::chrono::seconds interrupt_timeout) { + Lock lock(*this, interrupt_timeout); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) LLDB_LOGF(log, "GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), send_async); + "packet '%.*s'", + __FUNCTION__, int(payload.size()), payload.data()); return PacketResult::ErrorSendFailed; } @@ -172,16 +199,16 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse( GDBRemoteCommunication::PacketResult GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport( llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async, + std::chrono::seconds interrupt_timeout, llvm::function_ref output_callback) { - Lock lock(*this, send_async); + Lock lock(*this, interrupt_timeout); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) LLDB_LOGF(log, "GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), send_async); + "packet '%.*s'", + __FUNCTION__, int(payload.size()), payload.data()); return PacketResult::ErrorSendFailed; } @@ -222,13 +249,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( return packet_result; } -bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, - StringExtractorGDBRemote &response) { +bool GDBRemoteClientBase::SendvContPacket( + llvm::StringRef payload, std::chrono::seconds interrupt_timeout, + StringExtractorGDBRemote &response) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__); // we want to lock down packet sending while we continue - Lock lock(*this, true); + Lock lock(*this, interrupt_timeout); LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", @@ -336,18 +364,20 @@ GDBRemoteClientBase::ContinueLock::lock() { // GDBRemoteClientBase::Lock // /////////////////////////////// -GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt) +GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, + std::chrono::seconds interrupt_timeout) : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm), - m_acquired(false), m_did_interrupt(false) { - SyncWithContinueThread(interrupt); + m_interrupt_timeout(interrupt_timeout), m_acquired(false), + m_did_interrupt(false) { + SyncWithContinueThread(); if (m_acquired) m_async_lock.lock(); } -void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { +void GDBRemoteClientBase::Lock::SyncWithContinueThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); std::unique_lock lock(m_comm.m_mutex); - if (m_comm.m_is_running && !interrupt) + if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0)) return; // We were asked to avoid interrupting the sender. Lock is not // acquired. @@ -365,9 +395,9 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { "interrupt packet"); return; } + m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout; if (log) log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03"); - m_comm.m_interrupt_time = steady_clock::now(); } m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; }); m_did_interrupt = true; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index cd9f6ebd76424..518b81318b6cc 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -33,29 +33,46 @@ class GDBRemoteClientBase : public GDBRemoteCommunication { GDBRemoteClientBase(const char *comm_name, const char *listener_name); - bool SendAsyncSignal(int signo); + bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout); - bool Interrupt(); + bool Interrupt(std::chrono::seconds interrupt_timeout); lldb::StateType SendContinuePacketAndWaitForResponse( ContinueDelegate &delegate, const UnixSignals &signals, - llvm::StringRef payload, StringExtractorGDBRemote &response); - - PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, - StringExtractorGDBRemote &response, - bool send_async); + llvm::StringRef payload, std::chrono::seconds interrupt_timeout, + StringExtractorGDBRemote &response); + + // If interrupt_timeout == 0 seconds, don't interrupt the target. + // Only send the packet if the target is stopped. + // If you want to use this mode, use the fact that the timeout is defaulted + // so it's clear from the call-site that you are using no-interrupt. + // If it is non-zero, interrupt the target if it is running, and + // send the packet. + // It the target doesn't respond within the given timeout, it returns + // ErrorReplyTimeout. + PacketResult SendPacketAndWaitForResponse( + llvm::StringRef payload, StringExtractorGDBRemote &response, + std::chrono::seconds interrupt_timeout = std::chrono::seconds(0)); PacketResult SendPacketAndReceiveResponseWithOutputSupport( llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async, + std::chrono::seconds interrupt_timeout, llvm::function_ref output_callback); bool SendvContPacket(llvm::StringRef payload, + std::chrono::seconds interrupt_timeout, StringExtractorGDBRemote &response); class Lock { public: - Lock(GDBRemoteClientBase &comm, bool interrupt); + // If interrupt_timeout == 0 seconds, only take the lock if the target is + // not running. If using this option, use the fact that the + // interrupt_timeout is defaulted so it will be obvious at the call site + // that you are choosing this mode. If it is non-zero, interrupt the target + // if it is running, waiting for the given timeout for the interrupt to + // succeed. + Lock(GDBRemoteClientBase &comm, + std::chrono::seconds interrupt_timeout = std::chrono::seconds(0)); ~Lock(); explicit operator bool() { return m_acquired; } @@ -67,10 +84,11 @@ class GDBRemoteClientBase : public GDBRemoteCommunication { private: std::unique_lock m_async_lock; GDBRemoteClientBase &m_comm; + std::chrono::seconds m_interrupt_timeout; bool m_acquired; bool m_did_interrupt; - void SyncWithContinueThread(bool interrupt); + void SyncWithContinueThread(); }; protected: @@ -109,7 +127,7 @@ class GDBRemoteClientBase : public GDBRemoteCommunication { /// When was the interrupt packet sent. Used to make sure we time out if the /// stub does not respond to interrupt requests. - std::chrono::time_point m_interrupt_time; + std::chrono::time_point m_interrupt_endpoint; /// Number of threads interested in sending. uint32_t m_async_count; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 8a1ebb98e5ba1..a07a3f91c0c88 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -182,7 +182,7 @@ bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() { ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6))); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == + if (SendPacketAndWaitForResponse("QStartNoAckMode", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_send_acks = false; @@ -199,8 +199,8 @@ void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() { m_supports_threads_in_stop_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_supports_threads_in_stop_reply = eLazyBoolYes; } @@ -212,8 +212,8 @@ bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() { m_attach_or_wait_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_attach_or_wait_reply = eLazyBoolYes; } @@ -226,8 +226,8 @@ bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() { m_prepare_for_reg_writing_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_prepare_for_reg_writing_reply = eLazyBoolYes; } @@ -327,8 +327,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { } StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, - /*send_async=*/false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { // Hang on to the qSupported packet, so that platforms can do custom // configuration of the transport before attaching/launching the process. @@ -386,8 +385,8 @@ bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() { if (m_supports_thread_suffix == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_thread_suffix = eLazyBoolNo; - if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_supports_thread_suffix = eLazyBoolYes; } @@ -403,7 +402,7 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { m_supports_vCont_C = eLazyBoolNo; m_supports_vCont_s = eLazyBoolNo; m_supports_vCont_S = eLazyBoolNo; - if (SendPacketAndWaitForResponse("vCont?", response, false) == + if (SendPacketAndWaitForResponse("vCont?", response) == PacketResult::Success) { const char *response_cstr = response.GetStringRef().data(); if (::strstr(response_cstr, ";c")) @@ -455,9 +454,9 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( - lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, - bool send_async) { - Lock lock(*this, send_async); + lldb::tid_t tid, StreamString &&payload, + StringExtractorGDBRemote &response) { + Lock lock(*this); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) @@ -494,7 +493,7 @@ LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported( payload.PutCString(packetStr); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) == PacketResult::Success && + tid, std::move(payload), response) == PacketResult::Success && response.IsNormalResponse()) { return eLazyBoolYes; } @@ -508,7 +507,7 @@ StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() { if (m_supports_jThreadsInfo) { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == + if (SendPacketAndWaitForResponse("jThreadsInfo", response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) { m_supports_jThreadsInfo = false; @@ -525,7 +524,7 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jThreadExtendedInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == + if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jThreadExtendedInfo = eLazyBoolYes; @@ -541,7 +540,7 @@ void GDBRemoteCommunicationClient::EnableErrorStringInPacket() { // We try to enable error strings in remote packets but if we fail, we just // work in the older way. m_supports_error_string_reply = eLazyBoolNo; - if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) == + if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_error_string_reply = eLazyBoolYes; @@ -555,8 +554,7 @@ bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { StringExtractorGDBRemote response; m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo; if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", - response, - false) == PacketResult::Success) { + response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes; } @@ -569,7 +567,7 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() { if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jGetSharedCacheInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) == + if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jGetSharedCacheInfo = eLazyBoolYes; @@ -595,7 +593,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr, Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_MEMORY); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) != + if (SendPacketAndWaitForResponse(packet.GetString(), response) != PacketResult::Success || !response.IsNormalResponse()) { LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed", @@ -636,7 +634,7 @@ bool GDBRemoteCommunicationClient::GetxPacketSupported() { m_supports_x = eLazyBoolNo; char packet[256]; snprintf(packet, sizeof(packet), "x0,0"); - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsOKResponse()) m_supports_x = eLazyBoolYes; @@ -648,7 +646,7 @@ bool GDBRemoteCommunicationClient::GetxPacketSupported() { GDBRemoteCommunicationClient::PacketResult GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( const char *payload_prefix, std::string &response_string) { - Lock lock(*this, false); + Lock lock(*this); if (!lock) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); @@ -709,8 +707,7 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { // the thread id, which newer debugserver and lldb-gdbserver stubs return // correctly. StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC", response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) { if (response.GetChar() == 'Q') { if (response.GetChar() == 'C') { m_curr_pid_run = m_curr_pid = @@ -746,7 +743,7 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) { error_str.clear(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) == + if (SendPacketAndWaitForResponse("qLaunchSuccess", response) == PacketResult::Success) { if (response.IsOKResponse()) return true; @@ -800,7 +797,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket( } StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -850,7 +847,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket( if (m_supports_QEnvironmentHexEncoded) { packet.PutCString("QEnvironmentHexEncoded:"); packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value)); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -864,7 +861,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket( } else if (m_supports_QEnvironment) { packet.Printf("QEnvironment:%s", name_equal_value); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -884,7 +881,7 @@ int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) { StreamString packet; packet.Printf("QLaunchArch:%s", arch); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -902,7 +899,7 @@ int GDBRemoteCommunicationClient::SendLaunchEventDataPacket( StreamString packet; packet.Printf("QSetProcessEvent:%s", data); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) { if (was_supported) @@ -987,7 +984,7 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() { m_qGDBServerVersion_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) == + if (SendPacketAndWaitForResponse("qGDBServerVersion", response) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name, value; @@ -1079,7 +1076,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( if (avail_type != CompressionType::None) { StringExtractorGDBRemote response; llvm::Twine packet = "QEnableCompression:type:" + avail_name + ";"; - if (SendPacketAndWaitForResponse(packet.str(), response, false) != + if (SendPacketAndWaitForResponse(packet.str(), response) != PacketResult::Success) return; @@ -1105,8 +1102,7 @@ uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() { bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC", response, false) != - PacketResult::Success) + if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success) return false; if (!response.IsNormalResponse()) @@ -1156,7 +1152,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { ScopedTimeout timeout(*this, seconds(10)); m_qHostInfo_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qHostInfo", response, false) == + if (SendPacketAndWaitForResponse("qHostInfo", response) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name; @@ -1354,7 +1350,7 @@ int GDBRemoteCommunicationClient::SendAttach( ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid); UNUSED_IF_ASSERT_DISABLED(packet_len); assert(packet_len < (int)sizeof(packet)); - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsErrorResponse()) return response.GetError(); @@ -1370,7 +1366,7 @@ int GDBRemoteCommunicationClient::SendStdinNotification(const char *data, packet.PutCString("I"); packet.PutBytesAsRawHex8(data, data_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { return 0; } @@ -1408,7 +1404,7 @@ addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size, assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_alloc_dealloc_memory = eLazyBoolNo; @@ -1430,7 +1426,7 @@ bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_alloc_dealloc_memory = eLazyBoolNo; @@ -1454,7 +1450,7 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success && response.IsOKResponse()) { m_supports_detach_stay_stopped = eLazyBoolYes; @@ -1468,15 +1464,13 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) { return error; } else { StringExtractorGDBRemote response; - PacketResult packet_result = - SendPacketAndWaitForResponse("D1", response, false); + PacketResult packet_result = SendPacketAndWaitForResponse("D1", response); if (packet_result != PacketResult::Success) error.SetErrorString("Sending extended disconnect packet failed."); } } else { StringExtractorGDBRemote response; - PacketResult packet_result = - SendPacketAndWaitForResponse("D", response, false); + PacketResult packet_result = SendPacketAndWaitForResponse("D", response); if (packet_result != PacketResult::Success) error.SetErrorString("Sending disconnect packet failed."); } @@ -1496,7 +1490,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success && response.GetResponseType() == StringExtractorGDBRemote::eResponse) { llvm::StringRef name; @@ -1754,8 +1748,8 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { num = 0; if (m_supports_watchpoint_support_info != eLazyBoolNo) { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) == + PacketResult::Success) { m_supports_watchpoint_support_info = eLazyBoolYes; llvm::StringRef name; llvm::StringRef value; @@ -1823,7 +1817,7 @@ int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1843,7 +1837,7 @@ int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1863,7 +1857,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1877,7 +1871,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) == + if (SendPacketAndWaitForResponse("qGetWorkingDir", response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) return false; @@ -1899,7 +1893,7 @@ int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1918,8 +1912,7 @@ int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); @@ -1936,8 +1929,7 @@ int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); @@ -2055,7 +2047,7 @@ bool GDBRemoteCommunicationClient::GetProcessInfo( assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { return DecodeProcessInfoResponse(response, process_info); } else { @@ -2080,7 +2072,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { GetHostInfo(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qProcessInfo", response, false) == + if (SendPacketAndWaitForResponse("qProcessInfo", response) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name; @@ -2276,7 +2268,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( // Increase timeout as the first qfProcessInfo packet takes a long time on // Android. The value of 1min was arrived at empirically. ScopedTimeout timeout(*this, minutes(1)); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { do { ProcessInstanceInfo process_info; @@ -2284,7 +2276,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( break; process_infos.push_back(process_info); response = StringExtractorGDBRemote(); - } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) == + } while (SendPacketAndWaitForResponse("qsProcessInfo", response) == PacketResult::Success); } else { m_supports_qfProcessInfo = false; @@ -2303,7 +2295,7 @@ bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid, assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsNormalResponse()) { // Make sure we parsed the right number of characters. The response is @@ -2330,7 +2322,7 @@ bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid, assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsNormalResponse()) { // Make sure we parsed the right number of characters. The response is @@ -2358,8 +2350,7 @@ bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) { StringExtractorGDBRemote response; // Send to target - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) if (response.IsOKResponse()) return true; @@ -2431,7 +2422,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, for (i = 0; i < num_packets; ++i) { const auto packet_start_time = steady_clock::now(); StringExtractorGDBRemote response; - SendPacketAndWaitForResponse(packet.GetString(), response, false); + SendPacketAndWaitForResponse(packet.GetString(), response); const auto packet_end_time = steady_clock::now(); packet_times.push_back(packet_end_time - packet_start_time); } @@ -2485,7 +2476,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, uint32_t packet_count = 0; while (bytes_read < recv_amount) { StringExtractorGDBRemote response; - SendPacketAndWaitForResponse(packet.GetString(), response, false); + SendPacketAndWaitForResponse(packet.GetString(), response); bytes_read += recv_size; ++packet_count; } @@ -2539,7 +2530,7 @@ bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size, } StringExtractorGDBRemote response; - return SendPacketAndWaitForResponse(packet.GetString(), response, false) == + return SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success; } @@ -2569,7 +2560,7 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer( // give the process a few seconds to startup ScopedTimeout timeout(*this, seconds(10)); - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { llvm::StringRef name; llvm::StringRef value; @@ -2593,7 +2584,7 @@ size_t GDBRemoteCommunicationClient::QueryGDBServer( connection_urls.clear(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != + if (SendPacketAndWaitForResponse("qQueryGDBServer", response) != PacketResult::Success) return 0; @@ -2632,7 +2623,7 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) { stream.Printf("qKillSpawnedProcess:%" PRId64, pid); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return true; @@ -2660,8 +2651,8 @@ GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid, packet.PutHex64(tid); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse(packet.GetString(), response) + == PacketResult::Success) { if (response.IsOKResponse()) return {{pid, tid}}; @@ -2710,8 +2701,7 @@ bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid, bool GDBRemoteCommunicationClient::GetStopReply( StringExtractorGDBRemote &response) { - if (SendPacketAndWaitForResponse("?", response, false) == - PacketResult::Success) + if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success) return response.IsNormalResponse(); return false; } @@ -2724,7 +2714,7 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo( ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_qThreadStopInfo = false; @@ -2740,7 +2730,8 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo( } uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( - GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { + GDBStoppointType type, bool insert, addr_t addr, uint32_t length, + std::chrono::seconds timeout) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, __FUNCTION__, insert ? "add" : "remove", addr); @@ -2761,7 +2752,7 @@ uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( // or "" (unsupported) response.SetResponseValidatorToOKErrorNotSupported(); // Try to send the breakpoint packet, and check that it was correctly sent - if (SendPacketAndWaitForResponse(packet, response, true) == + if (SendPacketAndWaitForResponse(packet, response, timeout) == PacketResult::Success) { // Receive and OK packet when the breakpoint successfully placed if (response.IsOKResponse()) @@ -2804,7 +2795,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs( bool &sequence_mutex_unavailable) { std::vector> ids; - Lock lock(*this, false); + Lock lock(*this); if (lock) { sequence_mutex_unavailable = false; StringExtractorGDBRemote response; @@ -2876,7 +2867,7 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) != + if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) != PacketResult::Success || !response.IsNormalResponse()) return LLDB_INVALID_ADDRESS; @@ -2909,7 +2900,7 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand( stream.PutStringAsRawHex8(path); } StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return Status("malformed reply"); @@ -2947,8 +2938,7 @@ Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) != - PacketResult::Success) + if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success) return Status("failed to send '%s' packet", packet.str().c_str()); if (response.GetChar() != 'F') @@ -2969,8 +2959,7 @@ GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec, llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) != - PacketResult::Success) + if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success) return Status("failed to send '%s' packet", stream.GetData()); if (response.GetChar() != 'F') @@ -3012,7 +3001,7 @@ GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, stream.PutChar(','); stream.PutHex32(mode); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { return ParseHostIOPacketResponse(response, UINT64_MAX, error); } @@ -3024,7 +3013,7 @@ bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, lldb_private::StreamString stream; stream.Printf("vFile:close:%i", (int)fd); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { return ParseHostIOPacketResponse(response, -1, error) == 0; } @@ -3039,7 +3028,7 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( stream.PutCString("vFile:size:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return UINT64_MAX; @@ -3057,7 +3046,7 @@ void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory( stream.PutChar(','); stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix()); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { StreamString strm; char ch = response.GetChar(); @@ -3083,7 +3072,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, stream.PutCString("vFile:mode:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') { error.SetErrorStringWithFormat("invalid response to '%s' packet", @@ -3118,7 +3107,7 @@ uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd, stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return 0; @@ -3152,7 +3141,7 @@ uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd, stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset); stream.PutEscapedBytes(src, src_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') { error.SetErrorStringWithFormat("write file failed"); @@ -3187,7 +3176,7 @@ Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, stream.PutChar(','); stream.PutStringAsRawHex8(src_path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() == 'F') { uint32_t result = response.GetU32(UINT32_MAX); @@ -3218,7 +3207,7 @@ Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { // so we follow suit here stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() == 'F') { uint32_t result = response.GetU32(UINT32_MAX); @@ -3248,7 +3237,7 @@ bool GDBRemoteCommunicationClient::GetFileExists( stream.PutCString("vFile:exists:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return false; @@ -3267,7 +3256,7 @@ bool GDBRemoteCommunicationClient::CalculateMD5( stream.PutCString("vFile:MD5:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return false; @@ -3314,7 +3303,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, payload.Printf("p%x", reg); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success || + tid, std::move(payload), response) != PacketResult::Success || !response.IsNormalResponse()) return nullptr; @@ -3329,7 +3318,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) { payload.PutChar('g'); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success || + tid, std::move(payload), response) != PacketResult::Success || !response.IsNormalResponse()) return nullptr; @@ -3348,9 +3337,8 @@ bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; - return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), - response, false) == - PacketResult::Success && + return SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response) == PacketResult::Success && response.IsOKResponse(); } @@ -3362,9 +3350,8 @@ bool GDBRemoteCommunicationClient::WriteAllRegisters( endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; - return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), - response, false) == - PacketResult::Success && + return SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response) == PacketResult::Success && response.IsOKResponse(); } @@ -3379,7 +3366,7 @@ bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid, payload.PutCString("QSaveRegisterState"); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success) + tid, std::move(payload), response) != PacketResult::Success) return false; if (response.IsUnsupportedResponse()) @@ -3405,7 +3392,7 @@ bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid, payload.Printf("QRestoreRegisterState:%u", save_id); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success) + tid, std::move(payload), response) != PacketResult::Success) return false; if (response.IsOKResponse()) @@ -3423,13 +3410,13 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { StreamString packet; StringExtractorGDBRemote response; packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid); - return SendPacketAndWaitForResponse(packet.GetString(), response, false) == + return SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success && response.IsOKResponse(); } llvm::Expected -GDBRemoteCommunicationClient::SendTraceSupported() { +GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StreamGDBRemote escaped_packet; @@ -3437,7 +3424,7 @@ GDBRemoteCommunicationClient::SendTraceSupported() { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsErrorResponse()) return response.GetStatus().ToError(); @@ -3454,7 +3441,8 @@ GDBRemoteCommunicationClient::SendTraceSupported() { } llvm::Error -GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request) { +GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request, + std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StreamGDBRemote escaped_packet; @@ -3469,7 +3457,7 @@ GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request) { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsErrorResponse()) return response.GetStatus().ToError(); @@ -3488,7 +3476,8 @@ GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request) { } llvm::Error -GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value ¶ms) { +GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value ¶ms, + std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StreamGDBRemote escaped_packet; @@ -3503,7 +3492,7 @@ GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value ¶ms) { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsErrorResponse()) return response.GetStatus().ToError(); @@ -3522,7 +3511,8 @@ GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value ¶ms) { } llvm::Expected -GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type) { +GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type, + std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StreamGDBRemote escaped_packet; @@ -3537,7 +3527,7 @@ GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type) { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsErrorResponse()) return response.GetStatus().ToError(); @@ -3556,7 +3546,7 @@ GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type) { llvm::Expected> GDBRemoteCommunicationClient::SendTraceGetBinaryData( - const TraceGetBinaryDataRequest &request) { + const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StreamGDBRemote escaped_packet; @@ -3571,7 +3561,7 @@ GDBRemoteCommunicationClient::SendTraceGetBinaryData( StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsErrorResponse()) return response.GetStatus().ToError(); @@ -3591,8 +3581,8 @@ GDBRemoteCommunicationClient::SendTraceGetBinaryData( llvm::Optional GDBRemoteCommunicationClient::GetQOffsets() { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse( - "qOffsets", response, /*send_async=*/false) != PacketResult::Success) + if (SendPacketAndWaitForResponse("qOffsets", response) != + PacketResult::Success) return llvm::None; if (!response.IsNormalResponse()) return llvm::None; @@ -3647,7 +3637,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo( packet.PutStringAsRawHex8(triple); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) != + if (SendPacketAndWaitForResponse(packet.GetString(), response) != PacketResult::Success) return false; @@ -3754,7 +3744,7 @@ GDBRemoteCommunicationClient::GetModulesInfo( ScopedTimeout timeout(*this, std::chrono::seconds(10)); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(payload.GetString(), response, false) != + if (SendPacketAndWaitForResponse(payload.GetString(), response) != PacketResult::Success || response.IsErrorResponse()) return llvm::None; @@ -3813,7 +3803,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature( << "," << std::hex << size; GDBRemoteCommunication::PacketResult res = - SendPacketAndWaitForResponse(packet.str(), chunk, false); + SendPacketAndWaitForResponse(packet.str(), chunk); if (res != GDBRemoteCommunication::PacketResult::Success) { err.SetErrorString("Error sending $qXfer packet"); @@ -3902,7 +3892,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( bool first_qsymbol_query = true; if (m_supports_qSymbol && !m_qSymbol_requests_done) { - Lock lock(*this, false); + Lock lock(*this); if (lock) { StreamString packet; packet.PutCString("qSymbol::"); @@ -4030,9 +4020,8 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { // Poll it now. StringExtractorGDBRemote response; - const bool send_async = false; - if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response, - send_async) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) == + PacketResult::Success) { m_supported_async_json_packets_sp = StructuredData::ParseJSON(std::string(response.GetStringRef())); if (m_supported_async_json_packets_sp && @@ -4076,7 +4065,7 @@ Status GDBRemoteCommunicationClient::SendSignalsToIgnore( std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str(); StringExtractorGDBRemote response; - auto send_status = SendPacketAndWaitForResponse(packet, response, false); + auto send_status = SendPacketAndWaitForResponse(packet, response); if (send_status != GDBRemoteCommunication::PacketResult::Success) return Status("Sending QPassSignals packet failed"); @@ -4115,10 +4104,8 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( stream.Flush(); // Send the packet. - const bool send_async = false; StringExtractorGDBRemote response; - auto result = - SendPacketAndWaitForResponse(stream.GetString(), response, send_async); + auto result = SendPacketAndWaitForResponse(stream.GetString(), response); if (result == PacketResult::Success) { // We failed if the config result comes back other than OK. if (strcmp(response.GetStringRef().data(), "OK") == 0) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 4fe05a8a4e54c..48e3e5e41fde6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -327,7 +327,8 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { GDBStoppointType type, // Type of breakpoint or watchpoint bool insert, // Insert or remove? lldb::addr_t addr, // Address of breakpoint or watchpoint - uint32_t length); // Byte Size of breakpoint or watchpoint + uint32_t length, // Byte Size of breakpoint or watchpoint + std::chrono::seconds interrupt_timeout); // Time to wait for an interrupt bool SetNonStopMode(const bool enable); @@ -526,16 +527,22 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { ConfigureRemoteStructuredData(ConstString type_name, const StructuredData::ObjectSP &config_sp); - llvm::Expected SendTraceSupported(); + llvm::Expected + SendTraceSupported(std::chrono::seconds interrupt_timeout); - llvm::Error SendTraceStart(const llvm::json::Value &request); + llvm::Error SendTraceStart(const llvm::json::Value &request, + std::chrono::seconds interrupt_timeout); - llvm::Error SendTraceStop(const TraceStopRequest &request); + llvm::Error SendTraceStop(const TraceStopRequest &request, + std::chrono::seconds interrupt_timeout); - llvm::Expected SendTraceGetState(llvm::StringRef type); + llvm::Expected + SendTraceGetState(llvm::StringRef type, + std::chrono::seconds interrupt_timeout); llvm::Expected> - SendTraceGetBinaryData(const TraceGetBinaryDataRequest &request); + SendTraceGetBinaryData(const TraceGetBinaryDataRequest &request, + std::chrono::seconds interrupt_timeout); protected: LazyBool m_supports_not_sending_acks = eLazyBoolCalculate; @@ -636,7 +643,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { PacketResult SendThreadSpecificPacketAndWaitForResponse( lldb::tid_t tid, StreamString &&payload, - StringExtractorGDBRemote &response, bool send_async); + StringExtractorGDBRemote &response); Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index d1ae85a142677..65cf9fb2a8345 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -364,7 +364,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, reg_info->byte_size, // dst length m_reg_data.GetByteOrder())) // dst byte order { - GDBRemoteClientBase::Lock lock(gdb_comm, false); + GDBRemoteClientBase::Lock lock(gdb_comm); if (lock) { if (m_write_all_at_once) { // Invalidate all register values @@ -508,7 +508,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( const bool use_g_packet = !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process); - GDBRemoteClientBase::Lock lock(gdb_comm, false); + GDBRemoteClientBase::Lock lock(gdb_comm); if (lock) { if (gdb_comm.SyncThreadState(m_thread.GetProtocolID())) InvalidateAllRegisters(); @@ -574,7 +574,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( const bool use_g_packet = !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process); - GDBRemoteClientBase::Lock lock(gdb_comm, false); + GDBRemoteClientBase::Lock lock(gdb_comm); if (lock) { // The data_sp contains the G response packet. if (use_g_packet) { diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 0bcfcb5f6d8f3..4844d73e5310d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -465,7 +465,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response) == GDBRemoteCommunication::PacketResult::Success) { response_type = response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { @@ -1015,7 +1015,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { for (size_t idx = 0; idx < num_cmds; idx++) { StringExtractorGDBRemote response; m_gdb_comm.SendPacketAndWaitForResponse( - GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false); + GetExtraStartupCommands().GetArgumentAtIndex(idx), response); } return error; } @@ -1210,25 +1210,25 @@ Status ProcessGDBRemote::DoAttachToProcessWithName( } llvm::Expected ProcessGDBRemote::TraceSupported() { - return m_gdb_comm.SendTraceSupported(); + return m_gdb_comm.SendTraceSupported(GetInterruptTimeout()); } llvm::Error ProcessGDBRemote::TraceStop(const TraceStopRequest &request) { - return m_gdb_comm.SendTraceStop(request); + return m_gdb_comm.SendTraceStop(request, GetInterruptTimeout()); } llvm::Error ProcessGDBRemote::TraceStart(const llvm::json::Value &request) { - return m_gdb_comm.SendTraceStart(request); + return m_gdb_comm.SendTraceStart(request, GetInterruptTimeout()); } llvm::Expected ProcessGDBRemote::TraceGetState(llvm::StringRef type) { - return m_gdb_comm.SendTraceGetState(type); + return m_gdb_comm.SendTraceGetState(type, GetInterruptTimeout()); } llvm::Expected> ProcessGDBRemote::TraceGetBinaryData(const TraceGetBinaryDataRequest &request) { - return m_gdb_comm.SendTraceGetBinaryData(request); + return m_gdb_comm.SendTraceGetBinaryData(request, GetInterruptTimeout()); } void ProcessGDBRemote::DidExit() { @@ -1473,7 +1473,7 @@ void ProcessGDBRemote::HandleStopReplySequence() { while (true) { // Send vStopped StringExtractorGDBRemote response; - m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false); + m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response); // OK represents end of signal list if (response.IsOKResponse()) @@ -2414,7 +2414,7 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) { // file handle and debugserver will go away, and we can be done... m_gdb_comm.Disconnect(); } else - caused_stop = m_gdb_comm.Interrupt(); + caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); return error; } @@ -2563,11 +2563,11 @@ Status ProcessGDBRemote::DoDestroy() { if (m_gdb_comm.IsConnected()) { if (m_public_state.GetValue() != eStateAttaching) { StringExtractorGDBRemote response; - bool send_async = true; GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, std::chrono::seconds(3)); - if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) == + if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { char packet_cmd = response.GetChar(0); @@ -2731,7 +2731,8 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, assert(packet_len + 1 < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, true) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsNormalResponse()) { error.Clear(); @@ -2880,7 +2881,7 @@ Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) { StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - true) == + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { m_erased_flash_ranges.Insert(range, true); @@ -2909,7 +2910,8 @@ Status ProcessGDBRemote::FlashDone() { if (m_erased_flash_ranges.IsEmpty()) return status; StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) == + if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { m_erased_flash_ranges.Clear(); @@ -2970,7 +2972,7 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, } StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - true) == + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { error.Clear(); @@ -3146,7 +3148,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { (!bp_site->HardwareRequired())) { // Try to send off a software breakpoint packet ($Z0) uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( - eBreakpointSoftware, true, addr, bp_op_size); + eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout()); if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3186,7 +3188,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Try to send off a hardware breakpoint packet ($Z1) uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( - eBreakpointHardware, true, addr, bp_op_size); + eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout()); if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3250,13 +3252,15 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { case BreakpointSite::eHardware: if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, - addr, bp_op_size)) + addr, bp_op_size, + GetInterruptTimeout())) error.SetErrorToGenericError(); break; case BreakpointSite::eExternal: { if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, - addr, bp_op_size)) + addr, bp_op_size, + GetInterruptTimeout())) error.SetErrorToGenericError(); } break; } @@ -3312,7 +3316,8 @@ Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { // Pass down an appropriate z/Z packet... if (m_gdb_comm.SupportsGDBStoppointPacket(type)) { if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, - wp->GetByteSize()) == 0) { + wp->GetByteSize(), + GetInterruptTimeout()) == 0) { wp->SetEnabled(true, notify); return error; } else @@ -3358,7 +3363,8 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { GDBStoppointType type = GetGDBStoppointType(wp); // Pass down an appropriate z/Z packet... if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, - wp->GetByteSize()) == 0) { + wp->GetByteSize(), + GetInterruptTimeout()) == 0) { wp->SetEnabled(false, notify); return error; } else @@ -3383,7 +3389,7 @@ Status ProcessGDBRemote::DoSignal(int signo) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo); - if (!m_gdb_comm.SendAsyncSignal(signo)) + if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout())) error.SetErrorStringWithFormat("failed to send signal %i", signo); return error; } @@ -3761,7 +3767,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { // send the vCont packet if (!process->GetGDBRemote().SendvContPacket( llvm::StringRef(continue_cstr, continue_cstr_len), - response)) { + process->GetInterruptTimeout(), response)) { // Something went wrong done = true; break; @@ -3773,6 +3779,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { process->GetGDBRemote().SendContinuePacketAndWaitForResponse( *process, *process->GetUnixSignals(), llvm::StringRef(continue_cstr, continue_cstr_len), + process->GetInterruptTimeout(), response); // We need to immediately clear the thread ID list so we are sure @@ -4067,8 +4074,7 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4140,8 +4146,7 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4174,8 +4179,7 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4941,8 +4945,7 @@ Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, packet.PutStringAsRawHex8(file_path); StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) != + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != GDBRemoteCommunication::PacketResult::Success) return Status("Sending qFileLoadAddress packet failed"); @@ -5317,10 +5320,9 @@ class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { if (process) { for (size_t i = 0; i < argc; ++i) { const char *packet_cstr = command.GetArgumentAtIndex(0); - bool send_async = true; StringExtractorGDBRemote response; process->GetGDBRemote().SendPacketAndWaitForResponse( - packet_cstr, response, send_async); + packet_cstr, response, process->GetInterruptTimeout()); result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet_cstr); @@ -5368,11 +5370,10 @@ class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw { packet.PutCString("qRcmd,"); packet.PutBytesAsRawHex8(command.data(), command.size()); - bool send_async = true; StringExtractorGDBRemote response; Stream &output_strm = result.GetOutputStream(); process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport( - packet.GetString(), response, send_async, + packet.GetString(), response, process->GetInterruptTimeout(), [&output_strm](llvm::StringRef output) { output_strm << output; }); result.SetStatus(eReturnStatusSuccessFinishResult); output_strm.Printf(" packet: %s\n", packet.GetData()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 8db2193230312..6bbcf46ef34d6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1270,13 +1270,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, LinkDeclContextToDIE(function_decl, die); if (!function_param_decls.empty()) { - m_ast.SetFunctionParameters(function_decl, - &function_param_decls.front(), - function_param_decls.size()); + m_ast.SetFunctionParameters(function_decl, function_param_decls); if (template_function_decl) m_ast.SetFunctionParameters(template_function_decl, - &function_param_decls.front(), - function_param_decls.size()); + function_param_decls); } ClangASTMetadata metadata; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 5b4ab78ac2197..43cf262016c2f 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1093,7 +1093,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, } if (!params.empty()) - m_clang.SetFunctionParameters(&function_decl, params.data(), params.size()); + m_clang.SetFunctionParameters(&function_decl, params); } clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 0912059c7438d..78a0d09a681ae 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -970,7 +970,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { } } if (params.size()) - m_ast.SetFunctionParameters(decl, params.data(), params.size()); + m_ast.SetFunctionParameters(decl, params); m_uid_to_decl[sym_id] = decl; diff --git a/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt b/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt index a75d9676a6f3a..5b58a5703c09b 100644 --- a/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt +++ b/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt @@ -17,6 +17,7 @@ add_lldb_library(lldbPluginTraceIntelPT PLUGIN CommandObjectTraceStartIntelPT.cpp DecodedThread.cpp IntelPTDecoder.cpp + TraceCursorIntelPT.cpp TraceIntelPT.cpp TraceIntelPTSessionFileParser.cpp diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp index c65fa692e7d67..5c15e663fd638 100644 --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp @@ -8,8 +8,13 @@ #include "DecodedThread.h" +#include +#include + +#include "TraceCursorIntelPT.h" #include "lldb/Utility/StreamString.h" +using namespace lldb; using namespace lldb_private; using namespace lldb_private::trace_intel_pt; using namespace llvm; @@ -30,13 +35,18 @@ void IntelPTError::log(llvm::raw_ostream &OS) const { OS << "error: " << libipt_error_message; } +IntelPTInstruction::IntelPTInstruction(llvm::Error err) { + llvm::handleAllErrors(std::move(err), + [&](std::unique_ptr info) { + m_error = std::move(info); + }); + m_pt_insn.ip = LLDB_INVALID_ADDRESS; + m_pt_insn.iclass = ptic_error; +} + bool IntelPTInstruction::IsError() const { return (bool)m_error; } -Expected IntelPTInstruction::GetLoadAddress() const { - if (IsError()) - return ToError(); - return m_pt_insn.ip; -} +lldb::addr_t IntelPTInstruction::GetLoadAddress() const { return m_pt_insn.ip; } Error IntelPTInstruction::ToError() const { if (!IsError()) @@ -48,22 +58,54 @@ Error IntelPTInstruction::ToError() const { m_error->convertToErrorCode()); } -size_t DecodedThread::GetLastPosition() const { - return m_instructions.empty() ? 0 : m_instructions.size() - 1; +TraceInstructionControlFlowType +IntelPTInstruction::GetControlFlowType(lldb::addr_t next_load_address) const { + if (IsError()) + return (TraceInstructionControlFlowType)0; + + TraceInstructionControlFlowType mask = + eTraceInstructionControlFlowTypeInstruction; + + switch (m_pt_insn.iclass) { + case ptic_cond_jump: + case ptic_jump: + case ptic_far_jump: + mask |= eTraceInstructionControlFlowTypeBranch; + if (m_pt_insn.ip + m_pt_insn.size != next_load_address) + mask |= eTraceInstructionControlFlowTypeTakenBranch; + break; + case ptic_return: + case ptic_far_return: + mask |= eTraceInstructionControlFlowTypeReturn; + break; + case ptic_call: + case ptic_far_call: + mask |= eTraceInstructionControlFlowTypeCall; + break; + default: + break; + } + + return mask; } ArrayRef DecodedThread::GetInstructions() const { return makeArrayRef(m_instructions); } -size_t DecodedThread::GetCursorPosition() const { return m_position; } +DecodedThread::DecodedThread(ThreadSP thread_sp, Error error) + : m_thread_sp(thread_sp) { + m_instructions.emplace_back(std::move(error)); +} -size_t DecodedThread::SetCursorPosition(size_t new_position) { - m_position = std::min(new_position, GetLastPosition()); - return m_position; +DecodedThread::DecodedThread(ThreadSP thread_sp, + std::vector &&instructions) + : m_thread_sp(thread_sp), m_instructions(std::move(instructions)) { + if (m_instructions.empty()) + m_instructions.emplace_back( + createStringError(inconvertibleErrorCode(), "empty trace")); } -DecodedThread::DecodedThread(Error error) { - m_instructions.emplace_back(std::move(error)); - m_position = GetLastPosition(); +lldb::TraceCursorUP DecodedThread::GetCursor() { + return std::make_unique(m_thread_sp, shared_from_this()); } diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h index aabd85bcfd314..d5983c363367b 100644 --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h @@ -66,12 +66,7 @@ class IntelPTInstruction { /// Error constructor /// /// libipt errors should use the underlying \a IntelPTError class. - IntelPTInstruction(llvm::Error err) { - llvm::handleAllErrors(std::move(err), - [&](std::unique_ptr info) { - m_error = std::move(info); - }); - } + IntelPTInstruction(llvm::Error err); /// Check if this object represents an error (i.e. a gap). /// @@ -80,15 +75,27 @@ class IntelPTInstruction { bool IsError() const; /// \return - /// The instruction pointer address, or an \a llvm::Error if it is an - /// error. - llvm::Expected GetLoadAddress() const; + /// The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is + /// an error. + lldb::addr_t GetLoadAddress() const; /// \return /// An \a llvm::Error object if this class corresponds to an Error, or an /// \a llvm::Error::success otherwise. llvm::Error ToError() const; + /// Get the \a lldb::TraceInstructionControlFlowType categories of the + /// instruction. + /// + /// \param[in] next_load_address + /// The address of the next instruction in the trace or \b + /// LLDB_INVALID_ADDRESS if not available. + /// + /// \return + /// The control flow categories, or \b 0 if the instruction is an error. + lldb::TraceInstructionControlFlowType + GetControlFlowType(lldb::addr_t next_load_address) const; + IntelPTInstruction(IntelPTInstruction &&other) = default; private: @@ -106,15 +113,14 @@ class IntelPTInstruction { /// /// Each decoded thread contains a cursor to the current position the user is /// stopped at. See \a Trace::GetCursorPosition for more information. -class DecodedThread { +class DecodedThread : public std::enable_shared_from_this { public: - DecodedThread(std::vector &&instructions) - : m_instructions(std::move(instructions)), m_position(GetLastPosition()) { - } + DecodedThread(lldb::ThreadSP thread_sp, + std::vector &&instructions); /// Constructor with a single error signaling a complete failure of the /// decoding process. - DecodedThread(llvm::Error error); + DecodedThread(lldb::ThreadSP thread_sp, llvm::Error error); /// Get the instructions from the decoded trace. Some of them might indicate /// errors (i.e. gaps) in the trace. @@ -123,28 +129,16 @@ class DecodedThread { /// The instructions of the trace. llvm::ArrayRef GetInstructions() const; - /// \return - /// The current position of the cursor of this trace, or 0 if there are no - /// instructions. - size_t GetCursorPosition() const; - - /// Change the position of the cursor of this trace. If this value is to high, - /// the new position will be set as the last instruction of the trace. - /// - /// \return - /// The effective new position. - size_t SetCursorPosition(size_t new_position); - /// \} + /// Get a new cursor for the decoded thread. + lldb::TraceCursorUP GetCursor(); private: - /// \return - /// The index of the last element of the trace, or 0 if empty. - size_t GetLastPosition() const; - + lldb::ThreadSP m_thread_sp; std::vector m_instructions; - size_t m_position; }; +using DecodedThreadSP = std::shared_ptr; + } // namespace trace_intel_pt } // namespace lldb_private diff --git a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp index 5d9aa0a1c743c..fa9e42131f0a0 100644 --- a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp @@ -222,7 +222,7 @@ DecodeLiveThread(Thread &thread, TraceIntelPT &trace) { return cpu_info.takeError(); } -const DecodedThread &ThreadDecoder::Decode() { +DecodedThreadSP ThreadDecoder::Decode() { if (!m_decoded_thread.hasValue()) m_decoded_thread = DoDecode(); return *m_decoded_thread; @@ -232,22 +232,26 @@ PostMortemThreadDecoder::PostMortemThreadDecoder( const lldb::ThreadPostMortemTraceSP &trace_thread, TraceIntelPT &trace) : m_trace_thread(trace_thread), m_trace(trace) {} -DecodedThread PostMortemThreadDecoder::DoDecode() { +DecodedThreadSP PostMortemThreadDecoder::DoDecode() { if (Expected> instructions = DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace, m_trace_thread->GetTraceFile())) - return DecodedThread(std::move(*instructions)); + return std::make_shared(m_trace_thread->shared_from_this(), + std::move(*instructions)); else - return DecodedThread(instructions.takeError()); + return std::make_shared(m_trace_thread->shared_from_this(), + instructions.takeError()); } LiveThreadDecoder::LiveThreadDecoder(Thread &thread, TraceIntelPT &trace) : m_thread_sp(thread.shared_from_this()), m_trace(trace) {} -DecodedThread LiveThreadDecoder::DoDecode() { +DecodedThreadSP LiveThreadDecoder::DoDecode() { if (Expected> instructions = DecodeLiveThread(*m_thread_sp, m_trace)) - return DecodedThread(std::move(*instructions)); + return std::make_shared(m_thread_sp, + std::move(*instructions)); else - return DecodedThread(instructions.takeError()); + return std::make_shared(m_thread_sp, + instructions.takeError()); } diff --git a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h index 3768a8d80a2bf..e969db579e52a 100644 --- a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h +++ b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h @@ -31,7 +31,7 @@ class ThreadDecoder { /// /// \return /// A \a DecodedThread instance. - const DecodedThread &Decode(); + DecodedThreadSP Decode(); ThreadDecoder(const ThreadDecoder &other) = delete; ThreadDecoder &operator=(const ThreadDecoder &other) = delete; @@ -41,9 +41,9 @@ class ThreadDecoder { /// /// \return /// A \a DecodedThread instance. - virtual DecodedThread DoDecode() = 0; + virtual DecodedThreadSP DoDecode() = 0; - llvm::Optional m_decoded_thread; + llvm::Optional m_decoded_thread; }; /// Decoder implementation for \a lldb_private::ThreadPostMortemTrace, which are @@ -59,7 +59,7 @@ class PostMortemThreadDecoder : public ThreadDecoder { TraceIntelPT &trace); private: - DecodedThread DoDecode() override; + DecodedThreadSP DoDecode() override; lldb::ThreadPostMortemTraceSP m_trace_thread; TraceIntelPT &m_trace; @@ -75,7 +75,7 @@ class LiveThreadDecoder : public ThreadDecoder { LiveThreadDecoder(Thread &thread, TraceIntelPT &trace); private: - DecodedThread DoDecode() override; + DecodedThreadSP DoDecode() override; lldb::ThreadSP m_thread_sp; TraceIntelPT &m_trace; diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp new file mode 100644 index 0000000000000..25c2446162994 --- /dev/null +++ b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp @@ -0,0 +1,96 @@ +//===-- TraceCursorIntelPT.cpp --------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "TraceCursorIntelPT.h" +#include "DecodedThread.h" +#include "TraceIntelPT.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::trace_intel_pt; +using namespace llvm; + +TraceCursorIntelPT::TraceCursorIntelPT(ThreadSP thread_sp, + DecodedThreadSP decoded_thread_sp) + : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp) { + assert(!m_decoded_thread_sp->GetInstructions().empty() && + "a trace should have at least one instruction or error"); + m_pos = m_decoded_thread_sp->GetInstructions().size() - 1; +} + +size_t TraceCursorIntelPT::GetInternalInstructionSize() { + return m_decoded_thread_sp->GetInstructions().size(); +} + +bool TraceCursorIntelPT::Next() { + auto canMoveOne = [&]() { + if (IsForwards()) + return m_pos + 1 < GetInternalInstructionSize(); + return m_pos > 0; + }; + + size_t initial_pos = m_pos; + + while (canMoveOne()) { + m_pos += IsForwards() ? 1 : -1; + if (!m_ignore_errors && IsError()) + return true; + if (GetInstructionControlFlowType() & m_granularity) + return true; + } + + // Didn't find any matching instructions + m_pos = initial_pos; + return false; +} + +size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) { + int64_t last_index = GetInternalInstructionSize() - 1; + + auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t { + return std::min(std::max((int64_t)0, raw_pos), last_index); + }; + + switch (origin) { + case TraceCursor::SeekType::Set: + m_pos = fitPosToBounds(offset); + return m_pos; + case TraceCursor::SeekType::End: + m_pos = fitPosToBounds(offset + last_index); + return last_index - m_pos; + case TraceCursor::SeekType::Current: + int64_t new_pos = fitPosToBounds(offset + m_pos); + int64_t dist = m_pos - new_pos; + m_pos = new_pos; + return std::abs(dist); + } +} + +bool TraceCursorIntelPT::IsError() { + return m_decoded_thread_sp->GetInstructions()[m_pos].IsError(); +} + +Error TraceCursorIntelPT::GetError() { + return m_decoded_thread_sp->GetInstructions()[m_pos].ToError(); +} + +lldb::addr_t TraceCursorIntelPT::GetLoadAddress() { + return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress(); +} + +TraceInstructionControlFlowType +TraceCursorIntelPT::GetInstructionControlFlowType() { + lldb::addr_t next_load_address = + m_pos + 1 < GetInternalInstructionSize() + ? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress() + : LLDB_INVALID_ADDRESS; + return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType( + next_load_address); +} diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h new file mode 100644 index 0000000000000..4eb4e638905fa --- /dev/null +++ b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h @@ -0,0 +1,48 @@ +//===-- TraceCursorIntelPT.h ------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H +#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H + +#include "IntelPTDecoder.h" +#include "TraceIntelPTSessionFileParser.h" + +namespace lldb_private { +namespace trace_intel_pt { + +class TraceCursorIntelPT : public TraceCursor { +public: + TraceCursorIntelPT(lldb::ThreadSP thread_sp, + DecodedThreadSP decoded_thread_sp); + + size_t Seek(int64_t offset, SeekType origin) override; + + virtual bool Next() override; + + llvm::Error GetError() override; + + lldb::addr_t GetLoadAddress() override; + + lldb::TraceInstructionControlFlowType + GetInstructionControlFlowType() override; + + bool IsError() override; + +private: + size_t GetInternalInstructionSize(); + + /// Storage of the actual instructions + DecodedThreadSP m_decoded_thread_sp; + /// Internal instruction index currently pointing at. + size_t m_pos; +}; + +} // namespace trace_intel_pt +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp index df4e1e11b99a2..527e0d5e66287 100644 --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp @@ -9,6 +9,7 @@ #include "TraceIntelPT.h" #include "CommandObjectTraceStartIntelPT.h" +#include "DecodedThread.h" #include "TraceIntelPTConstants.h" #include "TraceIntelPTSessionFileParser.h" #include "lldb/Core/PluginManager.h" @@ -88,44 +89,23 @@ TraceIntelPT::TraceIntelPT( thread.get(), std::make_unique(thread, *this)); } -const DecodedThread *TraceIntelPT::Decode(Thread &thread) { +DecodedThreadSP TraceIntelPT::Decode(Thread &thread) { RefreshLiveProcessState(); - if (m_failed_live_threads_decoder.hasValue()) - return &*m_failed_live_threads_decoder; + if (m_live_refresh_error.hasValue()) + return std::make_shared( + thread.shared_from_this(), + createStringError(inconvertibleErrorCode(), *m_live_refresh_error)); auto it = m_thread_decoders.find(&thread); if (it == m_thread_decoders.end()) - return nullptr; - return &it->second->Decode(); + return std::make_shared( + thread.shared_from_this(), + createStringError(inconvertibleErrorCode(), "thread not traced")); + return it->second->Decode(); } lldb::TraceCursorUP TraceIntelPT::GetCursor(Thread &thread) { - // TODO: to implement - return nullptr; -} - -void TraceIntelPT::TraverseInstructions( - Thread &thread, size_t position, TraceDirection direction, - std::function load_addr)> - callback) { - const DecodedThread *decoded_thread = Decode(thread); - if (!decoded_thread) - return; - - ArrayRef instructions = decoded_thread->GetInstructions(); - - ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1; - for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0; - i += delta) - if (!callback(i, instructions[i].GetLoadAddress())) - break; -} - -Optional TraceIntelPT::GetInstructionCount(Thread &thread) { - if (const DecodedThread *decoded_thread = Decode(thread)) - return decoded_thread->GetInstructions().size(); - else - return None; + return Decode(thread)->GetCursor(); } Expected TraceIntelPT::GetCPUInfoForLiveProcess() { @@ -195,7 +175,7 @@ void TraceIntelPT::DoRefreshLiveProcessState( m_thread_decoders.clear(); if (!state) { - m_failed_live_threads_decoder = DecodedThread(state.takeError()); + m_live_refresh_error = toString(state.takeError()); return; } diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h index 2e414abca4ea6..9433ab8601f13 100644 --- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h @@ -65,13 +65,6 @@ class TraceIntelPT : public Trace { llvm::StringRef GetSchema() override; - void TraverseInstructions( - Thread &thread, size_t position, TraceDirection direction, - std::function load_addr)> - callback) override; - - llvm::Optional GetInstructionCount(Thread &thread) override; - lldb::TraceCursorUP GetCursor(Thread &thread) override; void DoRefreshLiveProcessState( @@ -145,24 +138,23 @@ class TraceIntelPT : public Trace { : Trace(live_process), m_thread_decoders(){}; /// Decode the trace of the given thread that, i.e. recontruct the traced - /// instructions. That trace must be managed by this class. + /// instructions. /// /// \param[in] thread /// If \a thread is a \a ThreadTrace, then its internal trace file will be /// decoded. Live threads are not currently supported. /// /// \return - /// A \a DecodedThread instance if decoding was successful, or a \b - /// nullptr if the thread's trace is not managed by this class. - const DecodedThread *Decode(Thread &thread); + /// A \a DecodedThread shared pointer with the decoded instructions. Any + /// errors are embedded in the instruction list. + DecodedThreadSP Decode(Thread &thread); /// It is provided by either a session file or a live process' "cpuInfo" /// binary data. llvm::Optional m_cpu_info; std::map> m_thread_decoders; - /// Dummy DecodedThread used when decoding threads after there were errors - /// when refreshing the live process state. - llvm::Optional m_failed_live_threads_decoder; + /// Error gotten after a failed live process update, if any. + llvm::Optional m_live_refresh_error; }; } // namespace trace_intel_pt diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 306573e06250e..df21c00a61c5f 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -687,8 +687,8 @@ void TypeSystemClang::SetTargetTriple(llvm::StringRef target_triple) { void TypeSystemClang::SetExternalSource( llvm::IntrusiveRefCntPtr &ast_source_up) { ASTContext &ast = getASTContext(); - ast.setExternalSource(ast_source_up); ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true); + ast.setExternalSource(ast_source_up); } ASTContext &TypeSystemClang::getASTContext() { @@ -746,7 +746,7 @@ void TypeSystemClang::CreateASTContext() { *m_diagnostics_engine_up, *m_file_manager_up); m_ast_up = std::make_unique( *m_language_options_up, *m_source_manager_up, *m_identifier_table_up, - *m_selector_table_up, *m_builtins_up); + *m_selector_table_up, *m_builtins_up, TU_Complete); m_diagnostic_consumer_up = std::make_unique(); m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false); @@ -2220,11 +2220,10 @@ ParmVarDecl *TypeSystemClang::CreateParameterDeclaration( return decl; } -void TypeSystemClang::SetFunctionParameters(FunctionDecl *function_decl, - ParmVarDecl **params, - unsigned num_params) { +void TypeSystemClang::SetFunctionParameters( + FunctionDecl *function_decl, llvm::ArrayRef params) { if (function_decl) - function_decl->setParams(ArrayRef(params, num_params)); + function_decl->setParams(params); } CompilerType diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 7c056cc7a8e76..62679e99d234d 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -423,7 +423,7 @@ class TypeSystemClang : public TypeSystem { int storage, bool add_decl = false); void SetFunctionParameters(clang::FunctionDecl *function_decl, - clang::ParmVarDecl **params, unsigned num_params); + llvm::ArrayRef params); CompilerType CreateBlockPointerType(const CompilerType &function_type); diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt index 13e9568d52f12..3875bc987dd02 100644 --- a/lldb/source/Target/CMakeLists.txt +++ b/lldb/source/Target/CMakeLists.txt @@ -69,6 +69,7 @@ add_lldb_library(lldbTarget ThreadPostMortemTrace.cpp Trace.cpp TraceCursor.cpp + TraceInstructionDumper.cpp TraceSessionFileParser.cpp UnixSignals.cpp UnwindAssembly.cpp diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index c6411f6c2244b..2907c71054f08 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -10,6 +10,7 @@ #include #include +#include "llvm/ADT/ScopeExit.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/Threading.h" @@ -297,6 +298,13 @@ std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const { return std::chrono::seconds(value); } +std::chrono::seconds ProcessProperties::GetInterruptTimeout() const { + const uint32_t idx = ePropertyInterruptTimeout; + uint64_t value = m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_process_properties[idx].default_uint_value); + return std::chrono::seconds(value); +} + bool ProcessProperties::GetSteppingRunsAllThreads() const { const uint32_t idx = ePropertySteppingRunsAllThreads; return m_collection_sp->GetPropertyAtIndexAsBoolean( @@ -485,25 +493,9 @@ void Process::Finalize() { if (m_finalizing.exchange(true)) return; - // Destroy this process if needed - switch (GetPrivateState()) { - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateStopped: - case eStateRunning: - case eStateStepping: - case eStateCrashed: - case eStateSuspended: - DestroyImpl(false); - break; - - case eStateInvalid: - case eStateUnloaded: - case eStateDetached: - case eStateExited: - break; - } + // Destroy the process. This will call the virtual function DoDestroy under + // the hood, giving our derived class a chance to do the ncessary tear down. + DestroyImpl(false); // Clear our broadcaster before we proceed with destroying Broadcaster::Clear(); @@ -1334,8 +1326,8 @@ Status Process::ResumeSynchronous(Stream *stream) { Status error = PrivateResume(); if (error.Success()) { - StateType state = - WaitForProcessToStop(llvm::None, nullptr, true, listener_sp, stream); + StateType state = WaitForProcessToStop(llvm::None, nullptr, true, + listener_sp, stream); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) @@ -2473,6 +2465,11 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) { if (error.Fail()) return error; + // Listen and queue events that are broadcasted during the process launch. + ListenerSP listener_sp(Listener::MakeListener("LaunchEventHijack")); + HijackProcessEvents(listener_sp); + auto on_exit = llvm::make_scope_exit([this]() { RestoreProcessEvents(); }); + if (PrivateStateThreadIsValid()) PausePrivateStateThread(); @@ -3077,9 +3074,10 @@ Status Process::Halt(bool clear_thread_plans, bool use_run_lock) { return Status(); } - // Wait for 10 second for the process to stop. - StateType state = WaitForProcessToStop( - seconds(10), &event_sp, true, halt_listener_sp, nullptr, use_run_lock); + // Wait for the process halt timeout seconds for the process to stop. + StateType state = + WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true, + halt_listener_sp, nullptr, use_run_lock); RestoreProcessEvents(); if (state == eStateInvalid || !event_sp) { @@ -3110,8 +3108,8 @@ Status Process::StopForDestroyOrDetach(lldb::EventSP &exit_event_sp) { SendAsyncInterrupt(); // Consume the interrupt event. - StateType state = - WaitForProcessToStop(seconds(10), &exit_event_sp, true, listener_sp); + StateType state = WaitForProcessToStop(GetInterruptTimeout(), + &exit_event_sp, true, listener_sp); RestoreProcessEvents(); @@ -6069,8 +6067,7 @@ bool Process::CallVoidArgVoidPtrReturn(const Address *address, return false; } -llvm::Expected -Process::GetMemoryTagManager(lldb::addr_t addr, lldb::addr_t end_addr) { +llvm::Expected Process::GetMemoryTagManager() { Architecture *arch = GetTarget().GetArchitecturePlugin(); const MemoryTagManager *tag_manager = arch ? arch->GetMemoryTagManager() : nullptr; @@ -6086,66 +6083,22 @@ Process::GetMemoryTagManager(lldb::addr_t addr, lldb::addr_t end_addr) { "Process does not support memory tagging"); } - ptrdiff_t len = tag_manager->AddressDiff(end_addr, addr); - if (len <= 0) { - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "End address (0x%" PRIx64 - ") must be greater than the start address (0x%" PRIx64 ")", - end_addr, addr); - } - - // Region lookup is not address size aware so mask the address - MemoryRegionInfo::RangeType tag_range(tag_manager->RemoveNonAddressBits(addr), - len); - tag_range = tag_manager->ExpandToGranule(tag_range); - - // Make a copy so we can use the original range in errors - MemoryRegionInfo::RangeType remaining_range(tag_range); - - // While we haven't found a matching memory region for some of the range - while (remaining_range.IsValid()) { - MemoryRegionInfo region; - Status status = GetMemoryRegionInfo(remaining_range.GetRangeBase(), region); - - if (status.Fail() || region.GetMemoryTagged() != MemoryRegionInfo::eYes) { - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "Address range 0x%lx:0x%lx is not in a memory tagged region", - tag_range.GetRangeBase(), tag_range.GetRangeEnd()); - } - - if (region.GetRange().GetRangeEnd() >= remaining_range.GetRangeEnd()) { - // We've found a region for the whole range or the last piece of a range - remaining_range.SetByteSize(0); - } else { - // We've found some part of the range, look for the rest - remaining_range.SetRangeBase(region.GetRange().GetRangeEnd()); - } - } - return tag_manager; } llvm::Expected> -Process::ReadMemoryTags(const MemoryTagManager *tag_manager, lldb::addr_t addr, - size_t len) { - if (!tag_manager) { - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "A memory tag manager is required for reading memory tags."); - } - - MemoryTagManager::TagRange range(tag_manager->RemoveNonAddressBits(addr), - len); - range = tag_manager->ExpandToGranule(range); +Process::ReadMemoryTags(lldb::addr_t addr, size_t len) { + llvm::Expected tag_manager_or_err = + GetMemoryTagManager(); + if (!tag_manager_or_err) + return tag_manager_or_err.takeError(); + const MemoryTagManager *tag_manager = *tag_manager_or_err; llvm::Expected> tag_data = - DoReadMemoryTags(range.GetRangeBase(), range.GetByteSize(), - tag_manager->GetAllocationTagType()); + DoReadMemoryTags(addr, len, tag_manager->GetAllocationTagType()); if (!tag_data) return tag_data.takeError(); - return tag_manager->UnpackTagsData( - *tag_data, range.GetByteSize() / tag_manager->GetGranuleSize()); + return tag_manager->UnpackTagsData(*tag_data, + len / tag_manager->GetGranuleSize()); } diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td index a3634a0bd54f1..8f627ad0f1a86 100644 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -230,6 +230,9 @@ let Definition = "process" in { def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">, DefaultUnsignedValue<15>, Desc<"The time in seconds to wait for LLDB-internal utility expressions.">; + def InterruptTimeout: Property<"interrupt-timeout", "UInt64">, + DefaultUnsignedValue<20>, + Desc<"The time in seconds to wait for an interrupt succeed in stopping the target.">; def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">, DefaultFalse, Desc<"If true, stepping operations will run all threads. This is equivalent to setting the run-mode option to 'all-threads'.">; diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index 8ae5c948e27b5..d25602d25b91f 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -39,6 +39,7 @@ ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) { void ThreadPlanStack::DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level, bool include_internal) const { + std::lock_guard guard(m_stack_mutex); s.IndentMore(); PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal); PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level, @@ -52,6 +53,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const { + std::lock_guard guard(m_stack_mutex); // If the stack is empty, just exit: if (stack.empty()) return; @@ -80,6 +82,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, } size_t ThreadPlanStack::CheckpointCompletedPlans() { + std::lock_guard guard(m_stack_mutex); m_completed_plan_checkpoint++; m_completed_plan_store.insert( std::make_pair(m_completed_plan_checkpoint, m_completed_plans)); @@ -87,6 +90,7 @@ size_t ThreadPlanStack::CheckpointCompletedPlans() { } void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) { + std::lock_guard guard(m_stack_mutex); auto result = m_completed_plan_store.find(checkpoint); assert(result != m_completed_plan_store.end() && "Asked for a checkpoint that didn't exist"); @@ -95,11 +99,13 @@ void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) { } void ThreadPlanStack::DiscardCompletedPlanCheckpoint(size_t checkpoint) { + std::lock_guard guard(m_stack_mutex); m_completed_plan_store.erase(checkpoint); } void ThreadPlanStack::ThreadDestroyed(Thread *thread) { // Tell the plan stacks that this thread is going away: + std::lock_guard guard(m_stack_mutex); for (ThreadPlanSP plan : m_plans) plan->ThreadDestroyed(); @@ -128,6 +134,7 @@ void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) { // If the thread plan doesn't already have a tracer, give it its parent's // tracer: // The first plan has to be a base plan: + std::lock_guard guard(m_stack_mutex); assert((m_plans.size() > 0 || new_plan_sp->IsBasePlan()) && "Zeroth plan must be a base plan"); @@ -140,6 +147,7 @@ void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) { } lldb::ThreadPlanSP ThreadPlanStack::PopPlan() { + std::lock_guard guard(m_stack_mutex); assert(m_plans.size() > 1 && "Can't pop the base thread plan"); lldb::ThreadPlanSP plan_sp = std::move(m_plans.back()); @@ -150,6 +158,7 @@ lldb::ThreadPlanSP ThreadPlanStack::PopPlan() { } lldb::ThreadPlanSP ThreadPlanStack::DiscardPlan() { + std::lock_guard guard(m_stack_mutex); assert(m_plans.size() > 1 && "Can't discard the base thread plan"); lldb::ThreadPlanSP plan_sp = std::move(m_plans.back()); @@ -162,6 +171,7 @@ lldb::ThreadPlanSP ThreadPlanStack::DiscardPlan() { // If the input plan is nullptr, discard all plans. Otherwise make sure this // plan is in the stack, and if so discard up to and including it. void ThreadPlanStack::DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { + std::lock_guard guard(m_stack_mutex); int stack_size = m_plans.size(); if (up_to_plan_ptr == nullptr) { @@ -189,6 +199,7 @@ void ThreadPlanStack::DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { } void ThreadPlanStack::DiscardAllPlans() { + std::lock_guard guard(m_stack_mutex); int stack_size = m_plans.size(); for (int i = stack_size - 1; i > 0; i--) { DiscardPlan(); @@ -197,6 +208,7 @@ void ThreadPlanStack::DiscardAllPlans() { } void ThreadPlanStack::DiscardConsultingMasterPlans() { + std::lock_guard guard(m_stack_mutex); while (true) { int master_plan_idx; bool discard = true; @@ -230,11 +242,13 @@ void ThreadPlanStack::DiscardConsultingMasterPlans() { } lldb::ThreadPlanSP ThreadPlanStack::GetCurrentPlan() const { + std::lock_guard guard(m_stack_mutex); assert(m_plans.size() != 0 && "There will always be a base plan."); return m_plans.back(); } lldb::ThreadPlanSP ThreadPlanStack::GetCompletedPlan(bool skip_private) const { + std::lock_guard guard(m_stack_mutex); if (m_completed_plans.empty()) return {}; @@ -252,6 +266,7 @@ lldb::ThreadPlanSP ThreadPlanStack::GetCompletedPlan(bool skip_private) const { lldb::ThreadPlanSP ThreadPlanStack::GetPlanByIndex(uint32_t plan_idx, bool skip_private) const { + std::lock_guard guard(m_stack_mutex); uint32_t idx = 0; for (lldb::ThreadPlanSP plan_sp : m_plans) { @@ -265,6 +280,7 @@ lldb::ThreadPlanSP ThreadPlanStack::GetPlanByIndex(uint32_t plan_idx, } lldb::ValueObjectSP ThreadPlanStack::GetReturnValueObject() const { + std::lock_guard guard(m_stack_mutex); if (m_completed_plans.empty()) return {}; @@ -278,6 +294,7 @@ lldb::ValueObjectSP ThreadPlanStack::GetReturnValueObject() const { } lldb::ExpressionVariableSP ThreadPlanStack::GetExpressionVariable() const { + std::lock_guard guard(m_stack_mutex); if (m_completed_plans.empty()) return {}; @@ -290,19 +307,23 @@ lldb::ExpressionVariableSP ThreadPlanStack::GetExpressionVariable() const { return {}; } bool ThreadPlanStack::AnyPlans() const { + std::lock_guard guard(m_stack_mutex); // There is always a base plan... return m_plans.size() > 1; } bool ThreadPlanStack::AnyCompletedPlans() const { + std::lock_guard guard(m_stack_mutex); return !m_completed_plans.empty(); } bool ThreadPlanStack::AnyDiscardedPlans() const { + std::lock_guard guard(m_stack_mutex); return !m_discarded_plans.empty(); } bool ThreadPlanStack::IsPlanDone(ThreadPlan *in_plan) const { + std::lock_guard guard(m_stack_mutex); for (auto plan : m_completed_plans) { if (plan.get() == in_plan) return true; @@ -311,6 +332,7 @@ bool ThreadPlanStack::IsPlanDone(ThreadPlan *in_plan) const { } bool ThreadPlanStack::WasPlanDiscarded(ThreadPlan *in_plan) const { + std::lock_guard guard(m_stack_mutex); for (auto plan : m_discarded_plans) { if (plan.get() == in_plan) return true; @@ -319,6 +341,7 @@ bool ThreadPlanStack::WasPlanDiscarded(ThreadPlan *in_plan) const { } ThreadPlan *ThreadPlanStack::GetPreviousPlan(ThreadPlan *current_plan) const { + std::lock_guard guard(m_stack_mutex); if (current_plan == nullptr) return nullptr; @@ -346,6 +369,7 @@ ThreadPlan *ThreadPlanStack::GetPreviousPlan(ThreadPlan *current_plan) const { } ThreadPlan *ThreadPlanStack::GetInnermostExpression() const { + std::lock_guard guard(m_stack_mutex); int stack_size = m_plans.size(); for (int i = stack_size - 1; i > 0; i--) { @@ -356,11 +380,13 @@ ThreadPlan *ThreadPlanStack::GetInnermostExpression() const { } void ThreadPlanStack::ClearThreadCache() { + std::lock_guard guard(m_stack_mutex); for (lldb::ThreadPlanSP thread_plan_sp : m_plans) thread_plan_sp->ClearThreadCache(); } void ThreadPlanStack::WillResume() { + std::lock_guard guard(m_stack_mutex); m_completed_plans.clear(); m_discarded_plans.clear(); } @@ -388,7 +414,7 @@ void ThreadPlanStackMap::Update(ThreadList ¤t_threads, std::vector missing_threads; // If we are going to delete plans from the plan stack, // then scan for absent TID's: - for (auto thread_plans : m_plans_list) { + for (auto &thread_plans : m_plans_list) { lldb::tid_t cur_tid = thread_plans.first; ThreadSP thread_sp = current_threads.FindThreadByID(cur_tid); if (!thread_sp) @@ -403,7 +429,7 @@ void ThreadPlanStackMap::DumpPlans(Stream &strm, lldb::DescriptionLevel desc_level, bool internal, bool condense_if_trivial, bool skip_unreported) { - for (auto elem : m_plans_list) { + for (auto &elem : m_plans_list) { lldb::tid_t tid = elem.first; uint32_t index_id = 0; ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(tid); diff --git a/lldb/source/Target/Trace.cpp b/lldb/source/Target/Trace.cpp index c703ba7b93633..f55346fbeff7b 100644 --- a/lldb/source/Target/Trace.cpp +++ b/lldb/source/Target/Trace.cpp @@ -98,264 +98,6 @@ Expected Trace::FindPluginSchema(StringRef name) { return createInvalidPlugInError(name); } -static int GetNumberOfDigits(size_t num) { - return num == 0 ? 1 : static_cast(log10(num)) + 1; -} - -/// \return -/// \b true if the provided line entries match line, column and source file. -/// This function assumes that the line entries are valid. -static bool FileLineAndColumnMatches(const LineEntry &a, const LineEntry &b) { - if (a.line != b.line) - return false; - if (a.column != b.column) - return false; - return a.file == b.file; -} - -// This custom LineEntry validator is neded because some line_entries have -// 0 as line, which is meaningless. Notice that LineEntry::IsValid only -// checks that line is not LLDB_INVALID_LINE_NUMBER, i.e. UINT32_MAX. -static bool IsLineEntryValid(const LineEntry &line_entry) { - return line_entry.IsValid() && line_entry.line > 0; -} - -/// Helper structure for \a TraverseInstructionsWithSymbolInfo. -struct InstructionSymbolInfo { - SymbolContext sc; - Address address; - lldb::addr_t load_address; - lldb::DisassemblerSP disassembler; - lldb::InstructionSP instruction; - lldb_private::ExecutionContext exe_ctx; -}; - -/// InstructionSymbolInfo object with symbol information for the given -/// instruction, calculated efficiently. -/// -/// \param[in] symbol_scope -/// If not \b 0, then the \a InstructionSymbolInfo will have its -/// SymbolContext calculated up to that level. -/// -/// \param[in] include_disassembler -/// If \b true, then the \a InstructionSymbolInfo will have the -/// \a disassembler and \a instruction objects calculated. -static void TraverseInstructionsWithSymbolInfo( - Trace &trace, Thread &thread, size_t position, - Trace::TraceDirection direction, SymbolContextItem symbol_scope, - bool include_disassembler, - std::function insn)> - callback) { - InstructionSymbolInfo prev_insn; - - Target &target = thread.GetProcess()->GetTarget(); - ExecutionContext exe_ctx; - target.CalculateExecutionContext(exe_ctx); - const ArchSpec &arch = target.GetArchitecture(); - - // Find the symbol context for the given address reusing the previous - // instruction's symbol context when possible. - auto calculate_symbol_context = [&](const Address &address) { - AddressRange range; - if (prev_insn.sc.GetAddressRange(symbol_scope, 0, - /*inline_block_range*/ false, range) && - range.Contains(address)) - return prev_insn.sc; - - SymbolContext sc; - address.CalculateSymbolContext(&sc, symbol_scope); - return sc; - }; - - // Find the disassembler for the given address reusing the previous - // instruction's disassembler when possible. - auto calculate_disass = [&](const Address &address, const SymbolContext &sc) { - if (prev_insn.disassembler) { - if (InstructionSP instruction = - prev_insn.disassembler->GetInstructionList() - .GetInstructionAtAddress(address)) - return std::make_tuple(prev_insn.disassembler, instruction); - } - - if (sc.function) { - if (DisassemblerSP disassembler = - sc.function->GetInstructions(exe_ctx, nullptr)) { - if (InstructionSP instruction = - disassembler->GetInstructionList().GetInstructionAtAddress( - address)) - return std::make_tuple(disassembler, instruction); - } - } - // We fallback to a single instruction disassembler - AddressRange range(address, arch.GetMaximumOpcodeByteSize()); - DisassemblerSP disassembler = - Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr, - /*flavor*/ nullptr, target, range); - return std::make_tuple(disassembler, - disassembler ? disassembler->GetInstructionList() - .GetInstructionAtAddress(address) - : InstructionSP()); - }; - - trace.TraverseInstructions( - thread, position, direction, - [&](size_t index, Expected load_address) -> bool { - if (!load_address) - return callback(index, load_address.takeError()); - - InstructionSymbolInfo insn; - insn.load_address = *load_address; - insn.exe_ctx = exe_ctx; - insn.address.SetLoadAddress(*load_address, &target); - if (symbol_scope != 0) - insn.sc = calculate_symbol_context(insn.address); - if (include_disassembler) - std::tie(insn.disassembler, insn.instruction) = - calculate_disass(insn.address, insn.sc); - prev_insn = insn; - return callback(index, insn); - }); -} - -/// Compare the symbol contexts of the provided \a InstructionSymbolInfo -/// objects. -/// -/// \return -/// \a true if both instructions belong to the same scope level analized -/// in the following order: -/// - module -/// - symbol -/// - function -/// - line -static bool -IsSameInstructionSymbolContext(const InstructionSymbolInfo &prev_insn, - const InstructionSymbolInfo &insn) { - // module checks - if (insn.sc.module_sp != prev_insn.sc.module_sp) - return false; - - // symbol checks - if (insn.sc.symbol != prev_insn.sc.symbol) - return false; - - // function checks - if (!insn.sc.function && !prev_insn.sc.function) - return true; - else if (insn.sc.function != prev_insn.sc.function) - return false; - - // line entry checks - const bool curr_line_valid = IsLineEntryValid(insn.sc.line_entry); - const bool prev_line_valid = IsLineEntryValid(prev_insn.sc.line_entry); - if (curr_line_valid && prev_line_valid) - return FileLineAndColumnMatches(insn.sc.line_entry, - prev_insn.sc.line_entry); - return curr_line_valid == prev_line_valid; -} - -/// Dump the symbol context of the given instruction address if it's different -/// from the symbol context of the previous instruction in the trace. -/// -/// \param[in] prev_sc -/// The symbol context of the previous instruction in the trace. -/// -/// \param[in] address -/// The address whose symbol information will be dumped. -/// -/// \return -/// The symbol context of the current address, which might differ from the -/// previous one. -static void -DumpInstructionSymbolContext(Stream &s, - Optional prev_insn, - InstructionSymbolInfo &insn) { - if (prev_insn && IsSameInstructionSymbolContext(*prev_insn, insn)) - return; - - s.Printf(" "); - - if (!insn.sc.module_sp) - s.Printf("(none)"); - else if (!insn.sc.function && !insn.sc.symbol) - s.Printf("%s`(none)", - insn.sc.module_sp->GetFileSpec().GetFilename().AsCString()); - else - insn.sc.DumpStopContext(&s, insn.exe_ctx.GetTargetPtr(), insn.address, - /*show_fullpath*/ false, - /*show_module*/ true, /*show_inlined_frames*/ false, - /*show_function_arguments*/ true, - /*show_function_name*/ true); - s.Printf("\n"); -} - -static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) { - if (!insn.instruction) - return; - s.Printf(" "); - insn.instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false, - /*max_opcode_byte_size*/ 0, &insn.exe_ctx, &insn.sc, - /*prev_sym_ctx*/ nullptr, - /*disassembly_addr_format*/ nullptr, - /*max_address_text_size*/ 0); -} - -void Trace::DumpTraceInstructions(Thread &thread, Stream &s, size_t count, - size_t end_position, bool raw) { - Optional instructions_count = GetInstructionCount(thread); - if (!instructions_count) { - s.Printf("thread #%u: tid = %" PRIu64 ", not traced\n", thread.GetIndexID(), - thread.GetID()); - return; - } - - s.Printf("thread #%u: tid = %" PRIu64 ", total instructions = %zu\n", - thread.GetIndexID(), thread.GetID(), *instructions_count); - - if (count == 0 || end_position >= *instructions_count) - return; - - int digits_count = GetNumberOfDigits(end_position); - size_t start_position = - end_position + 1 < count ? 0 : end_position + 1 - count; - auto printInstructionIndex = [&](size_t index) { - s.Printf(" [%*zu] ", digits_count, index); - }; - - bool was_prev_instruction_an_error = false; - Optional prev_insn; - - TraverseInstructionsWithSymbolInfo( - *this, thread, start_position, TraceDirection::Forwards, - eSymbolContextEverything, /*disassembler*/ true, - [&](size_t index, Expected insn) -> bool { - if (!insn) { - printInstructionIndex(index); - s << toString(insn.takeError()); - - prev_insn = None; - was_prev_instruction_an_error = true; - } else { - if (was_prev_instruction_an_error) - s.Printf(" ...missing instructions\n"); - - if (!raw) - DumpInstructionSymbolContext(s, prev_insn, *insn); - - printInstructionIndex(index); - s.Printf("0x%016" PRIx64, insn->load_address); - - if (!raw) - DumpInstructionDisassembly(s, *insn); - - prev_insn = *insn; - was_prev_instruction_an_error = false; - } - - s.Printf("\n"); - return index < end_position; - }); -} - Error Trace::Start(const llvm::json::Value &request) { if (!m_live_process) return createStringError(inconvertibleErrorCode(), diff --git a/lldb/source/Target/TraceCursor.cpp b/lldb/source/Target/TraceCursor.cpp index 80a7dadf3df5c..d0f69642cb90b 100644 --- a/lldb/source/Target/TraceCursor.cpp +++ b/lldb/source/Target/TraceCursor.cpp @@ -8,8 +8,28 @@ #include "lldb/Target/TraceCursor.h" -#include "lldb/Target/Trace.h" +#include "lldb/Target/ExecutionContext.h" +using namespace lldb; using namespace lldb_private; +using namespace llvm; -bool TraceCursor::IsStale() { return m_stop_id != m_trace_sp->GetStopID(); } +TraceCursor::TraceCursor(lldb::ThreadSP thread_sp) + : m_exe_ctx_ref(ExecutionContext(thread_sp)) {} + +ExecutionContextRef &TraceCursor::GetExecutionContextRef() { + return m_exe_ctx_ref; +} + +void TraceCursor::SetGranularity( + lldb::TraceInstructionControlFlowType granularity) { + m_granularity = granularity; +} + +void TraceCursor::SetIgnoreErrors(bool ignore_errors) { + m_ignore_errors = ignore_errors; +} + +void TraceCursor::SetForwards(bool forwards) { m_forwards = forwards; } + +bool TraceCursor::IsForwards() const { return m_forwards; } diff --git a/lldb/source/Target/TraceInstructionDumper.cpp b/lldb/source/Target/TraceInstructionDumper.cpp new file mode 100644 index 0000000000000..a8525d6a65c45 --- /dev/null +++ b/lldb/source/Target/TraceInstructionDumper.cpp @@ -0,0 +1,279 @@ +//===-- TraceInstructionDumper.cpp ----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/TraceInstructionDumper.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/SectionLoadList.h" + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; + +TraceInstructionDumper::TraceInstructionDumper(lldb::TraceCursorUP &&cursor_up, + int initial_index, bool raw) + : m_cursor_up(std::move(cursor_up)), m_index(initial_index), m_raw(raw) {} + +/// \return +/// Return \b true if the cursor could move one step. +bool TraceInstructionDumper::TryMoveOneStep() { + if (!m_cursor_up->Next()) { + SetNoMoreData(); + return false; + } + m_index += m_cursor_up->IsForwards() ? 1 : -1; + return true; +} + +/// \return +/// The number of characters that would be needed to print the given +/// integer. +static int GetNumberOfChars(int num) { + if (num == 0) + return 1; + return (num < 0 ? 1 : 0) + static_cast(log10(abs(num))) + 1; +} + +/// Helper struct that holds symbol, disassembly and address information of an +/// instruction. +struct InstructionSymbolInfo { + SymbolContext sc; + Address address; + lldb::addr_t load_address; + lldb::DisassemblerSP disassembler; + lldb::InstructionSP instruction; + lldb_private::ExecutionContext exe_ctx; +}; + +// This custom LineEntry validator is neded because some line_entries have +// 0 as line, which is meaningless. Notice that LineEntry::IsValid only +// checks that line is not LLDB_INVALID_LINE_NUMBER, i.e. UINT32_MAX. +static bool IsLineEntryValid(const LineEntry &line_entry) { + return line_entry.IsValid() && line_entry.line > 0; +} + +/// \return +/// \b true if the provided line entries match line, column and source file. +/// This function assumes that the line entries are valid. +static bool FileLineAndColumnMatches(const LineEntry &a, const LineEntry &b) { + if (a.line != b.line) + return false; + if (a.column != b.column) + return false; + return a.file == b.file; +} + +/// Compare the symbol contexts of the provided \a InstructionSymbolInfo +/// objects. +/// +/// \return +/// \a true if both instructions belong to the same scope level analized +/// in the following order: +/// - module +/// - symbol +/// - function +/// - line +static bool +IsSameInstructionSymbolContext(const InstructionSymbolInfo &prev_insn, + const InstructionSymbolInfo &insn) { + // module checks + if (insn.sc.module_sp != prev_insn.sc.module_sp) + return false; + + // symbol checks + if (insn.sc.symbol != prev_insn.sc.symbol) + return false; + + // function checks + if (!insn.sc.function && !prev_insn.sc.function) + return true; + else if (insn.sc.function != prev_insn.sc.function) + return false; + + // line entry checks + const bool curr_line_valid = IsLineEntryValid(insn.sc.line_entry); + const bool prev_line_valid = IsLineEntryValid(prev_insn.sc.line_entry); + if (curr_line_valid && prev_line_valid) + return FileLineAndColumnMatches(insn.sc.line_entry, + prev_insn.sc.line_entry); + return curr_line_valid == prev_line_valid; +} + +/// Dump the symbol context of the given instruction address if it's different +/// from the symbol context of the previous instruction in the trace. +/// +/// \param[in] prev_sc +/// The symbol context of the previous instruction in the trace. +/// +/// \param[in] address +/// The address whose symbol information will be dumped. +/// +/// \return +/// The symbol context of the current address, which might differ from the +/// previous one. +static void +DumpInstructionSymbolContext(Stream &s, + Optional prev_insn, + InstructionSymbolInfo &insn) { + if (prev_insn && IsSameInstructionSymbolContext(*prev_insn, insn)) + return; + + s.Printf(" "); + + if (!insn.sc.module_sp) + s.Printf("(none)"); + else if (!insn.sc.function && !insn.sc.symbol) + s.Printf("%s`(none)", + insn.sc.module_sp->GetFileSpec().GetFilename().AsCString()); + else + insn.sc.DumpStopContext(&s, insn.exe_ctx.GetTargetPtr(), insn.address, + /*show_fullpath=*/false, + /*show_module=*/true, /*show_inlined_frames=*/false, + /*show_function_arguments=*/true, + /*show_function_name=*/true); + s.Printf("\n"); +} + +static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) { + if (!insn.instruction) + return; + s.Printf(" "); + insn.instruction->Dump(&s, /*show_address=*/false, /*show_bytes=*/false, + /*max_opcode_byte_size=*/0, &insn.exe_ctx, &insn.sc, + /*prev_sym_ctx=*/nullptr, + /*disassembly_addr_format=*/nullptr, + /*max_address_text_size=*/0); +} + +void TraceInstructionDumper::SetNoMoreData() { m_no_more_data = true; } + +bool TraceInstructionDumper::HasMoreData() { return !m_no_more_data; } + +void TraceInstructionDumper::DumpInstructions(Stream &s, size_t count) { + ThreadSP thread_sp = m_cursor_up->GetExecutionContextRef().GetThreadSP(); + if (!thread_sp) { + s.Printf("invalid thread"); + return; + } + + s.Printf("thread #%u: tid = %" PRIu64 "\n", thread_sp->GetIndexID(), + thread_sp->GetID()); + + int digits_count = GetNumberOfChars( + m_cursor_up->IsForwards() ? m_index + count - 1 : m_index - count + 1); + bool was_prev_instruction_an_error = false; + + auto printMissingInstructionsMessage = [&]() { + s.Printf(" ...missing instructions\n"); + }; + + auto printInstructionIndex = [&]() { + s.Printf(" [%*d] ", digits_count, m_index); + }; + + InstructionSymbolInfo prev_insn_info; + + Target &target = thread_sp->GetProcess()->GetTarget(); + ExecutionContext exe_ctx; + target.CalculateExecutionContext(exe_ctx); + const ArchSpec &arch = target.GetArchitecture(); + + // Find the symbol context for the given address reusing the previous + // instruction's symbol context when possible. + auto calculateSymbolContext = [&](const Address &address) { + AddressRange range; + if (prev_insn_info.sc.GetAddressRange(eSymbolContextEverything, 0, + /*inline_block_range*/ false, + range) && + range.Contains(address)) + return prev_insn_info.sc; + + SymbolContext sc; + address.CalculateSymbolContext(&sc, eSymbolContextEverything); + return sc; + }; + + // Find the disassembler for the given address reusing the previous + // instruction's disassembler when possible. + auto calculateDisass = [&](const Address &address, const SymbolContext &sc) { + if (prev_insn_info.disassembler) { + if (InstructionSP instruction = + prev_insn_info.disassembler->GetInstructionList() + .GetInstructionAtAddress(address)) + return std::make_tuple(prev_insn_info.disassembler, instruction); + } + + if (sc.function) { + if (DisassemblerSP disassembler = + sc.function->GetInstructions(exe_ctx, nullptr)) { + if (InstructionSP instruction = + disassembler->GetInstructionList().GetInstructionAtAddress( + address)) + return std::make_tuple(disassembler, instruction); + } + } + // We fallback to a single instruction disassembler + AddressRange range(address, arch.GetMaximumOpcodeByteSize()); + DisassemblerSP disassembler = + Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr, + /*flavor*/ nullptr, target, range); + return std::make_tuple(disassembler, + disassembler ? disassembler->GetInstructionList() + .GetInstructionAtAddress(address) + : InstructionSP()); + }; + + for (size_t i = 0; i < count; i++) { + if (!HasMoreData()) { + s.Printf(" no more data\n"); + break; + } + + if (Error err = m_cursor_up->GetError()) { + if (!m_cursor_up->IsForwards() && !was_prev_instruction_an_error) + printMissingInstructionsMessage(); + + was_prev_instruction_an_error = true; + + printInstructionIndex(); + s << toString(std::move(err)); + } else { + if (m_cursor_up->IsForwards() && was_prev_instruction_an_error) + printMissingInstructionsMessage(); + + was_prev_instruction_an_error = false; + + InstructionSymbolInfo insn_info; + + if (!m_raw) { + insn_info.load_address = m_cursor_up->GetLoadAddress(); + insn_info.exe_ctx = exe_ctx; + insn_info.address.SetLoadAddress(insn_info.load_address, &target); + insn_info.sc = calculateSymbolContext(insn_info.address); + std::tie(insn_info.disassembler, insn_info.instruction) = + calculateDisass(insn_info.address, insn_info.sc); + + DumpInstructionSymbolContext(s, prev_insn_info, insn_info); + } + + printInstructionIndex(); + s.Printf("0x%016" PRIx64, m_cursor_up->GetLoadAddress()); + + if (!m_raw) + DumpInstructionDisassembly(s, insn_info); + + prev_insn_info = insn_info; + } + + s.Printf("\n"); + TryMoveOneStep(); + } +} diff --git a/lldb/test/API/commands/trace/TestTraceDumpInstructions.py b/lldb/test/API/commands/trace/TestTraceDumpInstructions.py index c1cb9b611d193..745a4c61a5d56 100644 --- a/lldb/test/API/commands/trace/TestTraceDumpInstructions.py +++ b/lldb/test/API/commands/trace/TestTraceDumpInstructions.py @@ -35,8 +35,9 @@ def testRawDumpInstructions(self): os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"), substrs=["intel-pt"]) - self.expect("thread trace dump instructions --raw", - substrs=['''thread #1: tid = 3842849, total instructions = 21 + self.expect("thread trace dump instructions --raw --count 21 --forwards", + substrs=['''thread #1: tid = 3842849 + [ 0] 0x0000000000400511 [ 1] 0x0000000000400518 [ 2] 0x000000000040051f [ 3] 0x0000000000400529 @@ -58,19 +59,27 @@ def testRawDumpInstructions(self): [19] 0x0000000000400529 [20] 0x000000000040052d''']) - # We check if we can pass count and position - self.expect("thread trace dump instructions --count 5 --position 10 --raw", - substrs=['''thread #1: tid = 3842849, total instructions = 21 + # We check if we can pass count and skip + self.expect("thread trace dump instructions --count 5 --skip 6 --raw --forwards", + substrs=['''thread #1: tid = 3842849 [ 6] 0x0000000000400525 [ 7] 0x0000000000400529 [ 8] 0x000000000040052d [ 9] 0x0000000000400521 [10] 0x0000000000400525''']) + self.expect("thread trace dump instructions --count 5 --skip 6 --raw", + substrs=['''thread #1: tid = 3842849 + [ -6] 0x0000000000400525 + [ -7] 0x0000000000400521 + [ -8] 0x000000000040052d + [ -9] 0x0000000000400529 + [-10] 0x0000000000400525''']) + # We check if we can access the thread by index id self.expect("thread trace dump instructions 1 --raw", - substrs=['''thread #1: tid = 3842849, total instructions = 21 - [ 1] 0x0000000000400518''']) + substrs=['''thread #1: tid = 3842849 + [ 0] 0x000000000040052d''']) # We check that we get an error when using an invalid thread index id self.expect("thread trace dump instructions 10", error=True, @@ -83,85 +92,87 @@ def testDumpFullInstructionsWithMultipleThreads(self): # We print the instructions of two threads simultaneously self.expect("thread trace dump instructions 1 2 --count 2", - substrs=['''thread #1: tid = 3842849, total instructions = 21 - a.out`main + 28 at main.cpp:4 - [19] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) - [20] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 -thread #2: tid = 3842850, total instructions = 21 - a.out`main + 28 at main.cpp:4 - [19] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) - [20] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5''']) - - # We use custom --count and --position, saving the command to history for later - self.expect("thread trace dump instructions 1 2 --count 2 --position 20", inHistory=True, - substrs=['''thread #1: tid = 3842849, total instructions = 21 - a.out`main + 28 at main.cpp:4 - [19] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) - [20] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 -thread #2: tid = 3842850, total instructions = 21 - a.out`main + 28 at main.cpp:4 - [19] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) - [20] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5''']) + substrs=['''thread #1: tid = 3842849 + a.out`main + 32 at main.cpp:4 + [ 0] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 + [-1] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) +thread #2: tid = 3842850 + a.out`main + 32 at main.cpp:4 + [ 0] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 + [-1] 0x0000000000400529 cmpl $0x3, -0x8(%rbp)''']) + + # We use custom --count and --skip, saving the command to history for later + self.expect("thread trace dump instructions 1 2 --count 2 --skip 2", inHistory=True, + substrs=['''thread #1: tid = 3842849 + a.out`main + 24 at main.cpp:4 + [-2] 0x0000000000400525 addl $0x1, -0x8(%rbp) + a.out`main + 20 at main.cpp:5 + [-3] 0x0000000000400521 xorl $0x1, -0x4(%rbp) +thread #2: tid = 3842850 + a.out`main + 24 at main.cpp:4 + [-2] 0x0000000000400525 addl $0x1, -0x8(%rbp) + a.out`main + 20 at main.cpp:5 + [-3] 0x0000000000400521 xorl $0x1, -0x4(%rbp)''']) # We use a repeat command twice and ensure the previous count is used and the # start position moves with each command. self.expect("", inHistory=True, - substrs=['''thread #1: tid = 3842849, total instructions = 21 - a.out`main + 20 at main.cpp:5 - [17] 0x0000000000400521 xorl $0x1, -0x4(%rbp) + substrs=['''thread #1: tid = 3842849 + a.out`main + 32 at main.cpp:4 + [-4] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 + [-5] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) +thread #2: tid = 3842850 + a.out`main + 32 at main.cpp:4 + [-4] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 + [-5] 0x0000000000400529 cmpl $0x3, -0x8(%rbp)''']) + + self.expect("", inHistory=True, + substrs=['''thread #1: tid = 3842849 a.out`main + 24 at main.cpp:4 - [18] 0x0000000000400525 addl $0x1, -0x8(%rbp) -thread #2: tid = 3842850, total instructions = 21 + [-6] 0x0000000000400525 addl $0x1, -0x8(%rbp) a.out`main + 20 at main.cpp:5 - [17] 0x0000000000400521 xorl $0x1, -0x4(%rbp) + [-7] 0x0000000000400521 xorl $0x1, -0x4(%rbp) +thread #2: tid = 3842850 a.out`main + 24 at main.cpp:4 - [18] 0x0000000000400525 addl $0x1, -0x8(%rbp)''']) - - self.expect("", inHistory=True, - substrs=['''thread #1: tid = 3842849, total instructions = 21 - a.out`main + 28 at main.cpp:4 - [15] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) - [16] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5 -thread #2: tid = 3842850, total instructions = 21 - a.out`main + 28 at main.cpp:4 - [15] 0x0000000000400529 cmpl $0x3, -0x8(%rbp) - [16] 0x000000000040052d jle 0x400521 ; <+20> at main.cpp:5''']) + [-6] 0x0000000000400525 addl $0x1, -0x8(%rbp) + a.out`main + 20 at main.cpp:5 + [-7] 0x0000000000400521 xorl $0x1, -0x4(%rbp)''']) def testInvalidBounds(self): self.expect("trace load -v " + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json")) # The output should be work when too many instructions are asked - self.expect("thread trace dump instructions --count 20 --position 2", - substrs=['''thread #1: tid = 3842849, total instructions = 21 + self.expect("thread trace dump instructions --count 20 --forwards", + substrs=['''thread #1: tid = 3842849 a.out`main + 4 at main.cpp:2 - [0] 0x0000000000400511 movl $0x0, -0x4(%rbp) + [ 0] 0x0000000000400511 movl $0x0, -0x4(%rbp) a.out`main + 11 at main.cpp:4 - [1] 0x0000000000400518 movl $0x0, -0x8(%rbp) - [2] 0x000000000040051f jmp 0x400529 ; <+28> at main.cpp:4''']) + [ 1] 0x0000000000400518 movl $0x0, -0x8(%rbp) + [ 2] 0x000000000040051f jmp 0x400529 ; <+28> at main.cpp:4''']) # Should print no instructions if the position is out of bounds - self.expect("thread trace dump instructions --position 23", - endstr='thread #1: tid = 3842849, total instructions = 21\n') + self.expect("thread trace dump instructions --skip 23", + endstr='no more data\n') # Should fail with negative bounds - self.expect("thread trace dump instructions --position -1", error=True) + self.expect("thread trace dump instructions --skip -1", error=True) self.expect("thread trace dump instructions --count -1", error=True) def testWrongImage(self): self.expect("trace load " + os.path.join(self.getSourceDir(), "intelpt-trace", "trace_bad_image.json")) - self.expect("thread trace dump instructions", - substrs=['''thread #1: tid = 3842849, total instructions = 2 - [0] 0x0000000000400511 error: no memory mapped at this address - [1] 0x0000000000400518 error: no memory mapped at this address''']) + self.expect("thread trace dump instructions --forwards", + substrs=['''thread #1: tid = 3842849 + [ 0] 0x0000000000400511 error: no memory mapped at this address + [ 1] 0x0000000000400518 error: no memory mapped at this address''']) def testWrongCPU(self): self.expect("trace load " + os.path.join(self.getSourceDir(), "intelpt-trace", "trace_wrong_cpu.json")) - self.expect("thread trace dump instructions", - substrs=['''thread #1: tid = 3842849, total instructions = 1 - [0] error: unknown cpu''']) + self.expect("thread trace dump instructions --forwards", + substrs=['''thread #1: tid = 3842849 + [ 0] error: unknown cpu''']) def testMultiFileTraceWithMissingModule(self): self.expect("trace load " + @@ -181,8 +192,8 @@ def testMultiFileTraceWithMissingModule(self): # line is printed showing the symbol context change. # # Finally, the instruction disassembly is included in the dump. - self.expect("thread trace dump instructions --count 50", - substrs=['''thread #1: tid = 815455, total instructions = 46 + self.expect("thread trace dump instructions --count 50 --forwards", + substrs=['''thread #1: tid = 815455 a.out`main + 15 at main.cpp:10 [ 0] 0x000000000040066f callq 0x400540 ; symbol stub for: foo() a.out`symbol stub for: foo() @@ -252,3 +263,83 @@ def testMultiFileTraceWithMissingModule(self): [43] 0x00000000004006a4 movl -0xc(%rbp), %ecx [44] 0x00000000004006a7 addl %eax, %ecx [45] 0x00000000004006a9 movl %ecx, -0xc(%rbp)''']) + + + self.expect("thread trace dump instructions --count 50", + substrs=['''thread #1: tid = 815455 + a.out`main + 73 at main.cpp:16 + [ 0] 0x00000000004006a9 movl %ecx, -0xc(%rbp) + [ -1] 0x00000000004006a7 addl %eax, %ecx + [ -2] 0x00000000004006a4 movl -0xc(%rbp), %ecx + libfoo.so`foo() + 35 at foo.cpp:6 + [ -3] 0x00007ffff7bd9703 retq''', + '''[ -4] 0x00007ffff7bd9702 popq %rbp + [ -5] 0x00007ffff7bd96fe addq $0x10, %rsp + [ -6] 0x00007ffff7bd96fb movl -0x4(%rbp), %eax + libfoo.so`foo() + 24 at foo.cpp:5 + [ -7] 0x00007ffff7bd96f8 movl %eax, -0x4(%rbp) + [ -8] 0x00007ffff7bd96f3 addl $0x1, %eax + [ -9] 0x00007ffff7bd96f0 movl -0x4(%rbp), %eax + libfoo.so`foo() + 13 at foo.cpp:4 + [-10] 0x00007ffff7bd96ed movl %eax, -0x4(%rbp) + libbar.so`bar() + 26 at bar.cpp:4 + [-11] 0x00007ffff79d76aa retq''', + '''[-12] 0x00007ffff79d76a9 popq %rbp + [-13] 0x00007ffff79d76a6 movl -0x4(%rbp), %eax + libbar.so`bar() + 19 at bar.cpp:3 + [-14] 0x00007ffff79d76a3 movl %eax, -0x4(%rbp) + [-15] 0x00007ffff79d769e addl $0x1, %eax + [-16] 0x00007ffff79d769b movl -0x4(%rbp), %eax + libbar.so`bar() + 4 at bar.cpp:2 + [-17] 0x00007ffff79d7694 movl $0x1, -0x4(%rbp) + libbar.so`bar() + 1 at bar.cpp:1 + [-18] 0x00007ffff79d7691 movq %rsp, %rbp + [-19] 0x00007ffff79d7690 pushq %rbp + libfoo.so`symbol stub for: bar() + [-20] 0x00007ffff7bd95d0 jmpq *0x200a4a(%rip) ; _GLOBAL_OFFSET_TABLE_ + 32 + libfoo.so`foo() + 8 at foo.cpp:4 + [-21] 0x00007ffff7bd96e8 callq 0x7ffff7bd95d0 ; symbol stub for: bar() + [-22] 0x00007ffff7bd96e4 subq $0x10, %rsp + libfoo.so`foo() + 1 at foo.cpp:3 + [-23] 0x00007ffff7bd96e1 movq %rsp, %rbp + [-24] 0x00007ffff7bd96e0 pushq %rbp + a.out`symbol stub for: foo() + [-25] 0x0000000000400540 jmpq *0x200ae2(%rip) ; _GLOBAL_OFFSET_TABLE_ + 40 + a.out`main + 63 at main.cpp:16 + [-26] 0x000000000040069f callq 0x400540 ; symbol stub for: foo() + a.out`main + 60 at main.cpp:14 + [-27] 0x000000000040069c movl %ecx, -0xc(%rbp) + [-28] 0x000000000040069a addl %eax, %ecx + [-29] 0x0000000000400697 movl -0xc(%rbp), %ecx + a.out`main + 52 [inlined] inline_function() + 18 at main.cpp:6 + [-30] 0x0000000000400694 movl -0x4(%rbp), %eax + a.out`main + 49 [inlined] inline_function() + 15 at main.cpp:5 + [-31] 0x0000000000400691 movl %eax, -0x4(%rbp) + [-32] 0x000000000040068c addl $0x1, %eax + [-33] 0x0000000000400689 movl -0x4(%rbp), %eax + a.out`main + 34 [inlined] inline_function() at main.cpp:4 + [-34] 0x0000000000400682 movl $0x0, -0x4(%rbp) + a.out`main + 31 at main.cpp:12 + [-35] 0x000000000040067f movl %eax, -0xc(%rbp) + [-36] 0x000000000040067a addl $0x1, %eax + [-37] 0x0000000000400677 movl -0xc(%rbp), %eax + a.out`main + 20 at main.cpp:10 + [-38] 0x0000000000400674 movl %eax, -0xc(%rbp) + ...missing instructions + [-39] 0x00007ffff7df1950 error: no memory mapped at this address + a.out`(none) + [-40] 0x0000000000400516 jmpq *0x200af4(%rip) ; _GLOBAL_OFFSET_TABLE_ + 16 + [-41] 0x0000000000400510 pushq 0x200af2(%rip) ; _GLOBAL_OFFSET_TABLE_ + 8 + a.out`symbol stub for: foo() + 11 + [-42] 0x000000000040054b jmp 0x400510 + [-43] 0x0000000000400546 pushq $0x2 + [-44] 0x0000000000400540 jmpq *0x200ae2(%rip) ; _GLOBAL_OFFSET_TABLE_ + 40 + a.out`main + 15 at main.cpp:10 + [-45] 0x000000000040066f callq 0x400540 ; symbol stub for: foo()''']) + + self.expect("thread trace dump instructions --skip 100 --forwards", inHistory=True, + substrs=['''thread #1: tid = 815455 + no more data''']) + + self.expect("", substrs=['''thread #1: tid = 815455 + no more data''']) diff --git a/lldb/test/API/commands/trace/TestTraceStartStop.py b/lldb/test/API/commands/trace/TestTraceStartStop.py index 91cf5afa26002..841ca437b29f6 100644 --- a/lldb/test/API/commands/trace/TestTraceStartStop.py +++ b/lldb/test/API/commands/trace/TestTraceStartStop.py @@ -65,11 +65,12 @@ def testStoppingAThread(self): self.expect("r") self.expect("thread trace start") self.expect("n") - self.expect("thread trace dump instructions", substrs=["total instructions"]) + self.expect("thread trace dump instructions", substrs=["""0x0000000000400511 movl $0x0, -0x4(%rbp) + no more data"""]) # process stopping should stop the thread self.expect("process trace stop") self.expect("n") - self.expect("thread trace dump instructions", error=True, substrs=["not traced"]) + self.expect("thread trace dump instructions", substrs=["not traced"]) @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) @@ -110,22 +111,32 @@ def testStartStopLiveThreads(self): # We can reconstruct the single instruction executed in the first line self.expect("n") - self.expect("thread trace dump instructions", - patterns=[f'''thread #1: tid = .*, total instructions = 1 + self.expect("thread trace dump instructions -f", + patterns=[f'''thread #1: tid = .* a.out`main \+ 4 at main.cpp:2 - \[0\] {ADDRESS_REGEX} movl''']) + \[ 0\] {ADDRESS_REGEX} movl''']) # We can reconstruct the instructions up to the second line self.expect("n") - self.expect("thread trace dump instructions", - patterns=[f'''thread #1: tid = .*, total instructions = 5 + self.expect("thread trace dump instructions -f", + patterns=[f'''thread #1: tid = .* a.out`main \+ 4 at main.cpp:2 - \[0\] {ADDRESS_REGEX} movl .* + \[ 0\] {ADDRESS_REGEX} movl .* a.out`main \+ 11 at main.cpp:4 - \[1\] {ADDRESS_REGEX} movl .* - \[2\] {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4 - \[3\] {ADDRESS_REGEX} cmpl .* - \[4\] {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5''']) + \[ 1\] {ADDRESS_REGEX} movl .* + \[ 2\] {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4 + \[ 3\] {ADDRESS_REGEX} cmpl .* + \[ 4\] {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5''']) + + self.expect("thread trace dump instructions", + patterns=[f'''thread #1: tid = .* + a.out`main \+ 32 at main.cpp:4 + \[ 0\] {ADDRESS_REGEX} jle .* ; <\+20> at main.cpp:5 + \[ -1\] {ADDRESS_REGEX} cmpl .* + \[ -2\] {ADDRESS_REGEX} jmp .* ; <\+28> at main.cpp:4 + \[ -3\] {ADDRESS_REGEX} movl .* + a.out`main \+ 4 at main.cpp:2 + \[ -4\] {ADDRESS_REGEX} movl .* ''']) # We stop tracing self.expect("thread trace stop") @@ -138,10 +149,15 @@ def testStartStopLiveThreads(self): # thread self.expect("thread trace start") self.expect("n") + self.expect("thread trace dump instructions -f", + patterns=[f'''thread #1: tid = .* + a.out`main \+ 20 at main.cpp:5 + \[ 0\] {ADDRESS_REGEX} xorl''']) + self.expect("thread trace dump instructions", - patterns=[f'''thread #1: tid = .*, total instructions = 1 + patterns=[f'''thread #1: tid = .* a.out`main \+ 20 at main.cpp:5 - \[0\] {ADDRESS_REGEX} xorl''']) + \[ 0\] {ADDRESS_REGEX} xorl''']) self.expect("c") # Now the process has finished, so the commands should fail diff --git a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py index e58234ff18b88..4b7fbc9f388de 100644 --- a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py +++ b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py @@ -97,8 +97,8 @@ def testStartMultipleLiveThreadsWithStops(self): self.expect("continue") self.expect("thread trace dump instructions", substrs=['main.cpp:4']) self.expect("thread trace dump instructions 3", substrs=['main.cpp:4']) - self.expect("thread trace dump instructions 1", error=True, substrs=['not traced']) - self.expect("thread trace dump instructions 2", error=True, substrs=['not traced']) + self.expect("thread trace dump instructions 1", substrs=['not traced']) + self.expect("thread trace dump instructions 2", substrs=['not traced']) @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) def testStartMultipleLiveThreadsWithThreadStartAll(self): @@ -128,9 +128,9 @@ def testStartMultipleLiveThreadsWithThreadStartAll(self): # We'll stop at the next breakpoint in thread 3, and nothing should be traced self.expect("continue") - self.expect("thread trace dump instructions 3", error=True, substrs=['not traced']) - self.expect("thread trace dump instructions 1", error=True, substrs=['not traced']) - self.expect("thread trace dump instructions 2", error=True, substrs=['not traced']) + self.expect("thread trace dump instructions 3", substrs=['not traced']) + self.expect("thread trace dump instructions 1", substrs=['not traced']) + self.expect("thread trace dump instructions 2", substrs=['not traced']) @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64'])) @testSBAPIAndCommands diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestHaltFails.py b/lldb/test/API/functionalities/gdb_remote_client/TestHaltFails.py deleted file mode 100644 index 9f8e39e8ecca5..0000000000000 --- a/lldb/test/API/functionalities/gdb_remote_client/TestHaltFails.py +++ /dev/null @@ -1,72 +0,0 @@ -from __future__ import print_function -import lldb -from lldbsuite.test.lldbtest import * -from lldbsuite.test.decorators import * -from gdbclientutils import * - - -class TestHaltFails(GDBRemoteTestBase): - - class MyResponder(MockGDBServerResponder): - - def setBreakpoint(self, packet): - return "OK" - - def interrupt(self): - # Simulate process waiting longer than the interrupt - # timeout to stop, then sending the reply. - time.sleep(14) - return "T02reason:signal" - - def cont(self): - # No response, wait for the client to interrupt us. - return None - - def wait_for_and_check_event(self, wait_time, value): - event = lldb.SBEvent() - got_event = self.dbg.GetListener().WaitForEvent(wait_time, event) - self.assertTrue(got_event, "Failed to get event after wait") - self.assertTrue(lldb.SBProcess.EventIsProcessEvent(event), "Event was not a process event") - event_type = lldb.SBProcess.GetStateFromEvent(event) - self.assertEqual(event_type, value) - - def get_to_running(self): - self.server.responder = self.MyResponder() - self.target = self.createTarget("a.yaml") - process = self.connect(self.target) - self.dbg.SetAsync(True) - - # There should be a stopped event, consume that: - self.wait_for_and_check_event(2, lldb.eStateStopped) - process.Continue() - - # There should be a running event, consume that: - self.wait_for_and_check_event(2, lldb.eStateRunning) - return process - - @skipIfReproducer # FIXME: Unexpected packet during (passive) replay - def test_destroy_while_running(self): - process = self.get_to_running() - process.Destroy() - - # Again pretend that after failing to be interrupted, we delivered the stop - # and make sure we still exit properly. - self.wait_for_and_check_event(14, lldb.eStateExited) - - @skipIfReproducer # FIXME: Unexpected packet during (passive) replay - def test_async_interrupt(self): - """ - Test that explicitly calling AsyncInterrupt, which then fails, leads - to an "eStateExited" state. - """ - process = self.get_to_running() - # Now do the interrupt: - process.SendAsyncInterrupt() - - # That should have caused the Halt to time out and we should - # be in eStateExited: - self.wait_for_and_check_event(15, lldb.eStateExited) - - - - diff --git a/lldb/test/API/functionalities/step-vrs-interrupt/Makefile b/lldb/test/API/functionalities/step-vrs-interrupt/Makefile new file mode 100644 index 0000000000000..99998b20bcb05 --- /dev/null +++ b/lldb/test/API/functionalities/step-vrs-interrupt/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/functionalities/step-vrs-interrupt/TestStepVrsInterruptTimeout.py b/lldb/test/API/functionalities/step-vrs-interrupt/TestStepVrsInterruptTimeout.py new file mode 100644 index 0000000000000..43fbcffc8e4ab --- /dev/null +++ b/lldb/test/API/functionalities/step-vrs-interrupt/TestStepVrsInterruptTimeout.py @@ -0,0 +1,36 @@ +""" +This is to make sure that the interrupt timer +doesn't influence synchronous user level stepping. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class TestStepVrsInterruptTimeout(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_step_vrs_interrupt(self): + """This test is to make sure that the interrupt timeout + doesn't cause use to flub events from a synchronous step.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.cpp") + self.sample_test() + + def sample_test(self): + """You might use the test implementation in several ways, say so here.""" + + # This function starts a process, "a.out" by default, sets a source + # breakpoint, runs to it, and returns the thread, process & target. + # It optionally takes an SBLaunchOption argument if you want to pass + # arguments or environment variables. + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + self.dbg.SetAsync(False) + self.runCmd("settings set target.process.interrupt-timeout 1") + thread.StepOver() + self.assertEqual(process.GetState(), lldb.eStateStopped, "Stopped like we should") diff --git a/lldb/test/API/functionalities/step-vrs-interrupt/main.cpp b/lldb/test/API/functionalities/step-vrs-interrupt/main.cpp new file mode 100644 index 0000000000000..2c818921ee5f1 --- /dev/null +++ b/lldb/test/API/functionalities/step-vrs-interrupt/main.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +void call_me() { + printf("I was called"); + std::this_thread::sleep_for(std::chrono::seconds(3)); +} + +int +main() +{ + call_me(); // Set a breakpoint here + return 0; +} + diff --git a/lldb/test/API/python_api/process/TestProcessAPI.py b/lldb/test/API/python_api/process/TestProcessAPI.py index b7efc7e4affa6..790d794890d60 100644 --- a/lldb/test/API/python_api/process/TestProcessAPI.py +++ b/lldb/test/API/python_api/process/TestProcessAPI.py @@ -398,3 +398,58 @@ def test_get_process_info(self): "Process effective group ID is invalid") process_info.GetParentProcessID() + + def test_allocate_deallocate_memory(self): + """Test Python SBProcess.AllocateMemory() and SBProcess.DeallocateMemory() APIs.""" + self.build() + (target, process, main_thread, main_breakpoint) = lldbutil.run_to_source_breakpoint( + self, "// Set break point at this line", lldb.SBFileSpec("main.cpp")) + + # Allocate a block of memory in the target process + error = lldb.SBError() + addr = process.AllocateMemory(16384, lldb.ePermissionsReadable, error) + if not error.Success() or addr == lldb.LLDB_INVALID_ADDRESS: + self.fail("SBProcess.AllocateMemory() failed") + + # Now use WriteMemory() API to write 'a' into the allocated + # memory. Note that the debugger can do this even though the + # block is not set writable. + result = process.WriteMemory(addr, 'a', error) + if not error.Success() or result != 1: + self.fail("SBProcess.WriteMemory() failed") + + # Read from the memory location. This time it should be 'a'. + # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and + # expect to get a Python string as the result object! + content = process.ReadMemory(addr, 1, error) + if not error.Success(): + self.fail("SBProcess.ReadMemory() failed") + if self.TraceOn(): + print("memory content:", content) + + self.expect( + content, + "Result from SBProcess.ReadMemory() matches our expected output: 'a'", + exe=False, + startstr=b'a') + + # Verify that the process itself can read the allocated memory + frame = main_thread.GetFrameAtIndex(0) + val = frame.EvaluateExpression( + "test_read(reinterpret_cast({:#x}))".format(addr)) + self.expect(val.GetValue(), + "Result of test_read() matches expected output 'a'", + exe=False, + startstr="'a'") + + # Verify that the process cannot write into the block + val = frame.EvaluateExpression( + "test_write(reinterpret_cast({:#x}), 'b')".format(addr)) + if val.GetError().Success(): + self.fail( + "test_write() to allocated memory without write permission unexpectedly succeeded") + + # Deallocate the memory + error = process.DeallocateMemory(addr) + if not error.Success(): + self.fail("SBProcess.DeallocateMemory() failed") diff --git a/lldb/test/API/python_api/process/main.cpp b/lldb/test/API/python_api/process/main.cpp index f3cc7e12d3357..07cde05e2a054 100644 --- a/lldb/test/API/python_api/process/main.cpp +++ b/lldb/test/API/python_api/process/main.cpp @@ -21,3 +21,13 @@ int main (int argc, char const *argv[]) return 0; // Set break point at this line and check variable 'my_char'. // Use lldb Python API to set memory content for my_int and check the result. } + +char test_read (char *ptr) +{ + return *ptr; +} + +void test_write (char *ptr, char c) +{ + *ptr = c; +} diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm index 7eab2c6d185f1..9ab33cc4b3aaa 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm @@ -2684,10 +2684,6 @@ static bool FBSAddEventDataToOptions(NSMutableDictionary *options, bool MachProcess::GetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch) { -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000) - return false; -#else NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSOperatingSystemVersion vers = @@ -2702,7 +2698,6 @@ static bool FBSAddEventDataToOptions(NSMutableDictionary *options, [pool drain]; return true; -#endif } std::string MachProcess::GetMacCatalystVersionString() { diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 7273d355acf9e..fdf97ca33e905 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -149,8 +149,6 @@ uint64_t decode_uint64(const char *p, int base, char **end = nullptr, extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); -#if defined(__APPLE__) && \ - (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) // from System.framework/Versions/B/PrivateHeaders/sys/codesign.h extern "C" { #define CS_OPS_STATUS 0 /* return status */ @@ -165,7 +163,6 @@ typedef uint32_t csr_config_t; #define CSR_ALLOW_TASK_FOR_PID (1 << 2) int csr_check(csr_config_t mask); } -#endif RNBRemote::RNBRemote() : m_ctx(), m_comm(), m_arch(), m_continue_thread(-1), m_thread(-1), diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index b8c5aec5fd80b..a6a4a2a1b80b8 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -867,6 +868,10 @@ static llvm::Optional InitializeReproducer(llvm::StringRef argv0, } int main(int argc, char const *argv[]) { + // Editline uses for example iswprint which is dependent on LC_CTYPE. + std::setlocale(LC_ALL, ""); + std::setlocale(LC_CTYPE, ""); + // Setup LLVM signal handlers and make sure we call llvm_shutdown() on // destruction. llvm::InitLLVM IL(argc, argv, /*InstallPipeSignalExitHandler=*/false); diff --git a/lldb/tools/lldb-vscode/ProgressEvent.cpp b/lldb/tools/lldb-vscode/ProgressEvent.cpp index d973a578c2538..5c1f8c63ebefc 100644 --- a/lldb/tools/lldb-vscode/ProgressEvent.cpp +++ b/lldb/tools/lldb-vscode/ProgressEvent.cpp @@ -47,6 +47,7 @@ ProgressEvent::ProgressEvent(uint64_t progress_id, Optional message, m_percentage = 100; } else { // Update event + m_event_type = progressUpdate; m_percentage = std::min( (uint32_t)((double)completed / (double)total * 100.0), (uint32_t)99); if (prev_event->Reported()) { diff --git a/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp b/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp index efd6514dc6c05..128dac7a21c39 100644 --- a/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp +++ b/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp @@ -21,7 +21,7 @@ TEST(MemoryTagManagerAArch64MTETest, UnpackTagsData) { manager.UnpackTagsData(input, 2), llvm::FailedWithMessage( "Packed tag data size does not match expected number of tags. " - "Expected 2 tag(s) for 2 granules, got 0 tag(s).")); + "Expected 2 tag(s) for 2 granule(s), got 0 tag(s).")); // This is out of the valid tag range input.push_back(0x1f); @@ -41,6 +41,43 @@ TEST(MemoryTagManagerAArch64MTETest, UnpackTagsData) { manager.UnpackTagsData(input, 2); ASSERT_THAT_EXPECTED(got, llvm::Succeeded()); ASSERT_THAT(expected, testing::ContainerEq(*got)); + + // Error for too much tag data + ASSERT_THAT_EXPECTED( + manager.UnpackTagsData(input, 1), + llvm::FailedWithMessage( + "Packed tag data size does not match expected number of tags. " + "Expected 1 tag(s) for 1 granule(s), got 2 tag(s).")); + + // By default, we don't check number of tags + llvm::Expected> got_zero = + manager.UnpackTagsData(input); + ASSERT_THAT_EXPECTED(got_zero, llvm::Succeeded()); + ASSERT_THAT(expected, testing::ContainerEq(*got)); + + // Which is the same as granules=0 + got_zero = manager.UnpackTagsData(input, 0); + ASSERT_THAT_EXPECTED(got_zero, llvm::Succeeded()); + ASSERT_THAT(expected, testing::ContainerEq(*got)); +} + +TEST(MemoryTagManagerAArch64MTETest, PackTags) { + MemoryTagManagerAArch64MTE manager; + + // Error for tag out of range + llvm::Expected> invalid_tag_err = + manager.PackTags({0x10}); + ASSERT_THAT_EXPECTED( + invalid_tag_err, + llvm::FailedWithMessage( + "Found tag 0x10 which is > max MTE tag value of 0xf.")); + + // 0xf here is the max tag value that we can pack + std::vector tags{0, 1, 0xf}; + std::vector expected{0, 1, 0xf}; + llvm::Expected> packed = manager.PackTags(tags); + ASSERT_THAT_EXPECTED(packed, llvm::Succeeded()); + ASSERT_THAT(expected, testing::ContainerEq(*packed)); } TEST(MemoryTagManagerAArch64MTETest, GetLogicalTag) { @@ -94,6 +131,121 @@ TEST(MemoryTagManagerAArch64MTETest, ExpandToGranule) { manager.ExpandToGranule(MemoryTagManagerAArch64MTE::TagRange(18, 4))); } +static MemoryRegionInfo MakeRegionInfo(lldb::addr_t base, lldb::addr_t size, + bool tagged) { + return MemoryRegionInfo( + MemoryRegionInfo::RangeType(base, size), MemoryRegionInfo::eYes, + MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, MemoryRegionInfo::eYes, + ConstString(), MemoryRegionInfo::eNo, 0, + /*memory_tagged=*/ + tagged ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); +} + +TEST(MemoryTagManagerAArch64MTETest, MakeTaggedRange) { + MemoryTagManagerAArch64MTE manager; + MemoryRegionInfos memory_regions; + + // No regions means no tagged regions, error + ASSERT_THAT_EXPECTED( + manager.MakeTaggedRange(0, 0x10, memory_regions), + llvm::FailedWithMessage( + "Address range 0x0:0x10 is not in a memory tagged region")); + + // Alignment is done before checking regions. + // Here 1 is rounded up to the granule size of 0x10. + ASSERT_THAT_EXPECTED( + manager.MakeTaggedRange(0, 1, memory_regions), + llvm::FailedWithMessage( + "Address range 0x0:0x10 is not in a memory tagged region")); + + // Range must not be inverted + ASSERT_THAT_EXPECTED( + manager.MakeTaggedRange(1, 0, memory_regions), + llvm::FailedWithMessage( + "End address (0x0) must be greater than the start address (0x1)")); + + // Adding a single region to cover the whole range + memory_regions.push_back(MakeRegionInfo(0, 0x1000, true)); + + // Range can have different tags for begin and end + // (which would make it look inverted if we didn't remove them) + // Note that range comes back with an untagged base and alginment + // applied. + MemoryTagManagerAArch64MTE::TagRange expected_range(0x0, 0x10); + llvm::Expected got = + manager.MakeTaggedRange(0x0f00000000000000, 0x0e00000000000001, + memory_regions); + ASSERT_THAT_EXPECTED(got, llvm::Succeeded()); + ASSERT_EQ(*got, expected_range); + + // Error if the range isn't within any region + ASSERT_THAT_EXPECTED( + manager.MakeTaggedRange(0x1000, 0x1010, memory_regions), + llvm::FailedWithMessage( + "Address range 0x1000:0x1010 is not in a memory tagged region")); + + // Error if the first part of a range isn't tagged + memory_regions.clear(); + const char *err_msg = + "Address range 0x0:0x1000 is not in a memory tagged region"; + + // First because it has no region entry + memory_regions.push_back(MakeRegionInfo(0x10, 0x1000, true)); + ASSERT_THAT_EXPECTED(manager.MakeTaggedRange(0, 0x1000, memory_regions), + llvm::FailedWithMessage(err_msg)); + + // Then because the first region is untagged + memory_regions.push_back(MakeRegionInfo(0, 0x10, false)); + ASSERT_THAT_EXPECTED(manager.MakeTaggedRange(0, 0x1000, memory_regions), + llvm::FailedWithMessage(err_msg)); + + // If we tag that first part it succeeds + memory_regions.back().SetMemoryTagged(MemoryRegionInfo::eYes); + expected_range = MemoryTagManagerAArch64MTE::TagRange(0x0, 0x1000); + got = manager.MakeTaggedRange(0, 0x1000, memory_regions); + ASSERT_THAT_EXPECTED(got, llvm::Succeeded()); + ASSERT_EQ(*got, expected_range); + + // Error if the end of a range is untagged + memory_regions.clear(); + + // First because it has no region entry + memory_regions.push_back(MakeRegionInfo(0, 0xF00, true)); + ASSERT_THAT_EXPECTED(manager.MakeTaggedRange(0, 0x1000, memory_regions), + llvm::FailedWithMessage(err_msg)); + + // Then because the last region is untagged + memory_regions.push_back(MakeRegionInfo(0xF00, 0x100, false)); + ASSERT_THAT_EXPECTED(manager.MakeTaggedRange(0, 0x1000, memory_regions), + llvm::FailedWithMessage(err_msg)); + + // If we tag the last part it succeeds + memory_regions.back().SetMemoryTagged(MemoryRegionInfo::eYes); + got = manager.MakeTaggedRange(0, 0x1000, memory_regions); + ASSERT_THAT_EXPECTED(got, llvm::Succeeded()); + ASSERT_EQ(*got, expected_range); + + // Error if the middle of a range is untagged + memory_regions.clear(); + + // First because it has no entry + memory_regions.push_back(MakeRegionInfo(0, 0x500, true)); + memory_regions.push_back(MakeRegionInfo(0x900, 0x700, true)); + ASSERT_THAT_EXPECTED(manager.MakeTaggedRange(0, 0x1000, memory_regions), + llvm::FailedWithMessage(err_msg)); + + // Then because it's untagged + memory_regions.push_back(MakeRegionInfo(0x500, 0x400, false)); + ASSERT_THAT_EXPECTED(manager.MakeTaggedRange(0, 0x1000, memory_regions), + llvm::FailedWithMessage(err_msg)); + + // If we tag the middle part it succeeds + memory_regions.back().SetMemoryTagged(MemoryRegionInfo::eYes); + got = manager.MakeTaggedRange(0, 0x1000, memory_regions); + ASSERT_THAT_EXPECTED(got, llvm::Succeeded()); + ASSERT_EQ(*got, expected_range); +} + TEST(MemoryTagManagerAArch64MTETest, RemoveNonAddressBits) { MemoryTagManagerAArch64MTE manager; @@ -118,3 +270,53 @@ TEST(MemoryTagManagerAArch64MTETest, AddressDiff) { ASSERT_EQ(-32, manager.AddressDiff(0x5511222233334400, 0x4411222233334420)); ASSERT_EQ(65, manager.AddressDiff(0x9911222233334441, 0x6611222233334400)); } + +// Helper to check that repeating "tags" over "range" gives you +// "expected_tags". +static void +test_repeating_tags(const std::vector &tags, + MemoryTagManagerAArch64MTE::TagRange range, + const std::vector &expected_tags) { + MemoryTagManagerAArch64MTE manager; + llvm::Expected> tags_or_err = + manager.RepeatTagsForRange(tags, range); + ASSERT_THAT_EXPECTED(tags_or_err, llvm::Succeeded()); + ASSERT_THAT(expected_tags, testing::ContainerEq(*tags_or_err)); +} + +TEST(MemoryTagManagerAArch64MTETest, RepeatTagsForRange) { + MemoryTagManagerAArch64MTE manager; + + // Must have some tags if your range is not empty + llvm::Expected> no_tags_err = + manager.RepeatTagsForRange({}, + MemoryTagManagerAArch64MTE::TagRange{0, 16}); + ASSERT_THAT_EXPECTED( + no_tags_err, llvm::FailedWithMessage( + "Expected some tags to cover given range, got zero.")); + + // If the range is empty, you get no tags back + test_repeating_tags({1, 2, 3}, MemoryTagManagerAArch64MTE::TagRange{0, 0}, + {}); + // And you don't need tags for an empty range + test_repeating_tags({}, MemoryTagManagerAArch64MTE::TagRange{0, 0}, {}); + + // A single tag will just be multiplied as many times as needed + test_repeating_tags({5}, MemoryTagManagerAArch64MTE::TagRange{0, 16}, {5}); + test_repeating_tags({6}, MemoryTagManagerAArch64MTE::TagRange{0, 32}, {6, 6}); + + // If you've got as many tags as granules, it's a roundtrip + test_repeating_tags({7, 8}, MemoryTagManagerAArch64MTE::TagRange{0, 32}, + {7, 8}); + + // If you've got fewer tags than granules, they repeat. Exactly or partially + // as needed. + test_repeating_tags({7, 8}, MemoryTagManagerAArch64MTE::TagRange{0, 64}, + {7, 8, 7, 8}); + test_repeating_tags({7, 8}, MemoryTagManagerAArch64MTE::TagRange{0, 48}, + {7, 8, 7}); + + // If you've got more tags than granules you get back only those needed + test_repeating_tags({1, 2, 3, 4}, MemoryTagManagerAArch64MTE::TagRange{0, 32}, + {1, 2}); +} diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp index 5bbcfdff47343..eb4fd29b4df5f 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp @@ -55,6 +55,8 @@ class GDBRemoteClientBaseTest : public GDBRemoteTest { } protected: + // We don't have a process to get the interrupt timeout from, so make one up. + static std::chrono::seconds g_timeout; TestClient client; MockServer server; MockDelegate delegate; @@ -62,7 +64,8 @@ class GDBRemoteClientBaseTest : public GDBRemoteTest { StateType SendCPacket(StringExtractorGDBRemote &response) { return client.SendContinuePacketAndWaitForResponse(delegate, LinuxSignals(), - "c", response); + "c", g_timeout, + response); } void WaitForRunEvent() { @@ -72,6 +75,8 @@ class GDBRemoteClientBaseTest : public GDBRemoteTest { } }; +std::chrono::seconds GDBRemoteClientBaseTest::g_timeout(10); + } // end anonymous namespace TEST_F(GDBRemoteClientBaseTest, SendContinueAndWait) { @@ -103,7 +108,7 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) { StringExtractorGDBRemote continue_response, response; // SendAsyncSignal should do nothing when we are not running. - ASSERT_FALSE(client.SendAsyncSignal(0x47)); + ASSERT_FALSE(client.SendAsyncSignal(0x47, g_timeout)); // Continue. After the run packet is sent, send an async signal. std::future continue_state = std::async( @@ -112,8 +117,9 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) { ASSERT_EQ("c", response.GetStringRef()); WaitForRunEvent(); - std::future async_result = std::async( - std::launch::async, [&] { return client.SendAsyncSignal(0x47); }); + std::future async_result = std::async(std::launch::async, [&] { + return client.SendAsyncSignal(0x47, g_timeout); + }); // First we'll get interrupted. ASSERT_EQ(PacketResult::Success, server.GetPacket(response)); @@ -133,7 +139,6 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncSignal) { TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) { StringExtractorGDBRemote continue_response, async_response, response; - const bool send_async = true; // Continue. After the run packet is sent, send an async packet. std::future continue_state = std::async( @@ -143,13 +148,12 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndAsyncPacket) { WaitForRunEvent(); // Sending without async enabled should fail. - ASSERT_EQ( - PacketResult::ErrorSendFailed, - client.SendPacketAndWaitForResponse("qTest1", response, !send_async)); + ASSERT_EQ(PacketResult::ErrorSendFailed, + client.SendPacketAndWaitForResponse("qTest1", response)); std::future async_result = std::async(std::launch::async, [&] { return client.SendPacketAndWaitForResponse("qTest2", async_response, - send_async); + g_timeout); }); // First we'll get interrupted. @@ -178,7 +182,7 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) { StringExtractorGDBRemote continue_response, response; // Interrupt should do nothing when we're not running. - ASSERT_FALSE(client.Interrupt()); + ASSERT_FALSE(client.Interrupt(g_timeout)); // Continue. After the run packet is sent, send an interrupt. std::future continue_state = std::async( @@ -187,8 +191,8 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt) { ASSERT_EQ("c", response.GetStringRef()); WaitForRunEvent(); - std::future async_result = - std::async(std::launch::async, [&] { return client.Interrupt(); }); + std::future async_result = std::async( + std::launch::async, [&] { return client.Interrupt(g_timeout); }); // We get interrupted. ASSERT_EQ(PacketResult::Success, server.GetPacket(response)); @@ -211,8 +215,8 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) { ASSERT_EQ("c", response.GetStringRef()); WaitForRunEvent(); - std::future async_result = - std::async(std::launch::async, [&] { return client.Interrupt(); }); + std::future async_result = std::async( + std::launch::async, [&] { return client.Interrupt(g_timeout); }); // However, the target stops due to a different reason than the original // interrupt. @@ -233,10 +237,9 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndLateInterrupt) { TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) { StringExtractorGDBRemote continue_response, async_response, response; - const bool send_async = true; // Interrupt should do nothing when we're not running. - ASSERT_FALSE(client.Interrupt()); + ASSERT_FALSE(client.Interrupt(g_timeout)); // Continue. After the run packet is sent, send an async signal. std::future continue_state = std::async( @@ -245,8 +248,8 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) { ASSERT_EQ("c", response.GetStringRef()); WaitForRunEvent(); - std::future interrupt_result = - std::async(std::launch::async, [&] { return client.Interrupt(); }); + std::future interrupt_result = std::async( + std::launch::async, [&] { return client.Interrupt(g_timeout); }); // We get interrupted. We'll send two packets to simulate a buggy stub. ASSERT_EQ(PacketResult::Success, server.GetPacket(response)); @@ -261,8 +264,7 @@ TEST_F(GDBRemoteClientBaseTest, SendContinueAndInterrupt2PacketBug) { // Packet stream should remain synchronized. std::future send_result = std::async(std::launch::async, [&] { - return client.SendPacketAndWaitForResponse("qTest", async_response, - !send_async); + return client.SendPacketAndWaitForResponse("qTest", async_response); }); ASSERT_EQ(PacketResult::Success, server.GetPacket(response)); ASSERT_EQ("qTest", response.GetStringRef()); @@ -328,8 +330,8 @@ TEST_F(GDBRemoteClientBaseTest, InterruptNoResponse) { ASSERT_EQ("c", response.GetStringRef()); WaitForRunEvent(); - std::future async_result = - std::async(std::launch::async, [&] { return client.Interrupt(); }); + std::future async_result = std::async( + std::launch::async, [&] { return client.Interrupt(g_timeout); }); // We get interrupted, but we don't send a stop packet. ASSERT_EQ(PacketResult::Success, server.GetPacket(response)); @@ -352,7 +354,7 @@ TEST_F(GDBRemoteClientBaseTest, SendPacketAndReceiveResponseWithOutputSupport) { ASSERT_EQ(PacketResult::Success, server.SendPacket("OK")); PacketResult result = client.SendPacketAndReceiveResponseWithOutputSupport( - "qRcmd,test", response, true, + "qRcmd,test", response, g_timeout, [&command_output](llvm::StringRef output) { command_output << output; }); ASSERT_EQ(PacketResult::Success, result); diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index 45e0356c49486..781809297990a 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -384,8 +384,9 @@ TEST_F(GDBRemoteCommunicationClientTest, SendTraceSupportedPacket) { TraceSupportedResponse trace_type; std::string error_message; auto callback = [&] { + std::chrono::seconds timeout(10); if (llvm::Expected trace_type_or_err = - client.SendTraceSupported()) { + client.SendTraceSupported(timeout)) { trace_type = *trace_type_or_err; error_message = ""; return true; diff --git a/lldb/unittests/tools/lldb-server/tests/TestClient.cpp b/lldb/unittests/tools/lldb-server/tests/TestClient.cpp index 752b0bb2600be..0bb60f262191a 100644 --- a/lldb/unittests/tools/lldb-server/tests/TestClient.cpp +++ b/lldb/unittests/tools/lldb-server/tests/TestClient.cpp @@ -193,7 +193,7 @@ Error TestClient::SendMessage(StringRef message, std::string &response_string, PacketResult expected_result) { StringExtractorGDBRemote response; GTEST_LOG_(INFO) << "Send Packet: " << message.str(); - PacketResult result = SendPacketAndWaitForResponse(message, response, false); + PacketResult result = SendPacketAndWaitForResponse(message, response); response.GetEscapedBinaryData(response_string); GTEST_LOG_(INFO) << "Read Packet: " << response_string; if (result != expected_result) diff --git a/llvm-spirv/include/LLVMSPIRVExtensions.inc b/llvm-spirv/include/LLVMSPIRVExtensions.inc index 743b115975286..d6bdcec265a61 100644 --- a/llvm-spirv/include/LLVMSPIRVExtensions.inc +++ b/llvm-spirv/include/LLVMSPIRVExtensions.inc @@ -8,6 +8,7 @@ EXT(SPV_KHR_no_integer_wrap_decoration) EXT(SPV_KHR_float_controls) EXT(SPV_KHR_linkonce_odr) EXT(SPV_KHR_integer_dot_product) +EXT(SPV_KHR_bit_instructions) EXT(SPV_INTEL_subgroups) EXT(SPV_INTEL_media_block_io) EXT(SPV_INTEL_device_side_avc_motion_estimation) diff --git a/llvm-spirv/include/LLVMSPIRVOpts.h b/llvm-spirv/include/LLVMSPIRVOpts.h index 83bb4faab668d..cb424fc965ad9 100644 --- a/llvm-spirv/include/LLVMSPIRVOpts.h +++ b/llvm-spirv/include/LLVMSPIRVOpts.h @@ -172,6 +172,14 @@ class TranslatorOpts { ReplaceLLVMFmulAddWithOpenCLMad = Value; } + bool shouldPreserveOCLKernelArgTypeMetadataThroughString() const noexcept { + return PreserveOCLKernelArgTypeMetadataThroughString; + } + + void setPreserveOCLKernelArgTypeMetadataThroughString(bool Value) noexcept { + PreserveOCLKernelArgTypeMetadataThroughString = Value; + } + private: // Common translation options VersionNumber MaxVersion = VersionNumber::MaximumVersion; @@ -208,6 +216,10 @@ class TranslatorOpts { // Controls whether llvm.fmuladd.* should be replaced with mad from OpenCL // extended instruction set or with a simple fmul + fadd bool ReplaceLLVMFmulAddWithOpenCLMad = true; + + // Add a workaround to preserve OpenCL kernel_arg_type and + // kernel_arg_type_qual metadata through OpString + bool PreserveOCLKernelArgTypeMetadataThroughString = false; }; } // namespace SPIRV diff --git a/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp b/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp index 34221732b9e20..7fb24645a8711 100644 --- a/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp +++ b/llvm-spirv/lib/SPIRV/LLVMToSPIRVDbgTran.cpp @@ -496,7 +496,9 @@ LLVMToSPIRVDbgTran::transDbgCompilationUnit(const DICompileUnit *CU) { Ops[SPIRVDebugInfoVersionIdx] = SPIRVDebug::DebugInfoVersion; Ops[DWARFVersionIdx] = M->getDwarfVersion(); Ops[SourceIdx] = getSource(CU)->getId(); - Ops[LanguageIdx] = CU->getSourceLanguage(); + auto DwarfLang = + static_cast(CU->getSourceLanguage()); + Ops[LanguageIdx] = convertDWARFSourceLangToSPIRV(DwarfLang); BM->addModuleProcessed(SPIRVDebug::ProducerPrefix + CU->getProducer().str()); // Cache CU in a member. SPIRVCU = static_cast( diff --git a/llvm-spirv/lib/SPIRV/OCLUtil.cpp b/llvm-spirv/lib/SPIRV/OCLUtil.cpp index 87f648209f80d..d39e678572dbc 100644 --- a/llvm-spirv/lib/SPIRV/OCLUtil.cpp +++ b/llvm-spirv/lib/SPIRV/OCLUtil.cpp @@ -194,6 +194,7 @@ template <> void SPIRVMap::init() { _SPIRV_OP(cl_khr_mipmap_image_writes) _SPIRV_OP(cl_khr_egl_event) _SPIRV_OP(cl_khr_srgb_image_writes) + _SPIRV_OP(cl_khr_extended_bit_ops) #undef _SPIRV_OP } @@ -206,6 +207,7 @@ template <> void SPIRVMap::init() { add(OclExt::cl_khr_subgroups, CapabilityGroups); add(OclExt::cl_khr_mipmap_image, CapabilityImageMipmap); add(OclExt::cl_khr_mipmap_image_writes, CapabilityImageMipmap); + add(OclExt::cl_khr_extended_bit_ops, CapabilityBitInstructions); } /// Map OpenCL work functions to SPIR-V builtin variables. @@ -414,6 +416,11 @@ template <> void SPIRVMap::init() { // cl_khr_subgroup_shuffle_relative _SPIRV_OP(group_shuffle_up, GroupNonUniformShuffleUp) _SPIRV_OP(group_shuffle_down, GroupNonUniformShuffleDown) + // cl_khr_extended_bit_ops + _SPIRV_OP(bitfield_insert, BitFieldInsert) + _SPIRV_OP(bitfield_extract_signed, BitFieldSExtract) + _SPIRV_OP(bitfield_extract_unsigned, BitFieldUExtract) + _SPIRV_OP(bit_reverse, BitReverse) #undef _SPIRV_OP } @@ -1284,6 +1291,11 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo { } } else if (NameRef.contains("shuffle") || NameRef.contains("clustered")) addUnsignedArg(1); + } else if (NameRef.startswith("bitfield_insert")) { + addUnsignedArgs(2, 3); + } else if (NameRef.startswith("bitfield_extract_signed") || + NameRef.startswith("bitfield_extract_unsigned")) { + addUnsignedArgs(1, 2); } // Store the final version of a function name diff --git a/llvm-spirv/lib/SPIRV/OCLUtil.h b/llvm-spirv/lib/SPIRV/OCLUtil.h index b7b6f71a11738..2fe94073b4f21 100644 --- a/llvm-spirv/lib/SPIRV/OCLUtil.h +++ b/llvm-spirv/lib/SPIRV/OCLUtil.h @@ -353,6 +353,7 @@ enum Kind { _SPIRV_OP(cl_khr_mipmap_image_writes) _SPIRV_OP(cl_khr_egl_event) _SPIRV_OP(cl_khr_srgb_image_writes) + _SPIRV_OP(cl_khr_extended_bit_ops) #undef _SPIRV_OP }; // clang-format on diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp index c138d793f1f0e..f3d16be360135 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp @@ -770,6 +770,8 @@ bool SPIRVToLLVM::isDirectlyTranslatedToOCL(Op OpCode) const { return false; if (isEventOpCode(OpCode)) return false; + if (OpBitFieldInsert <= OpCode && OpCode <= OpBitReverse) + return false; if (OCLSPIRVBuiltinMap::rfind(OpCode, nullptr)) { // Not every spirv opcode which is placed in OCLSPIRVBuiltinMap is // translated directly to OCL builtin. Some of them are translated @@ -3044,7 +3046,6 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { AttrTy = cast(I->getType())->getElementType(); break; case Attribute::AttrKind::StructRet: - case Attribute::AttrKind::ReadOnly: AttrTy = I->getType(); break; default: @@ -4067,9 +4068,13 @@ bool SPIRVToLLVM::transNonTemporalMetadata(Instruction *I) { // generated and 'false' otherwise. static bool transKernelArgTypeMedataFromString(LLVMContext *Ctx, SPIRVModule *BM, - Function *Kernel) { - std::string ArgTypePrefix = std::string(SPIR_MD_KERNEL_ARG_TYPE) + "." + - Kernel->getName().str() + "."; + Function *Kernel, + std::string MDName) { + // Run W/A translation only if the appropriate option is passed + if (!BM->shouldPreserveOCLKernelArgTypeMetadataThroughString()) + return false; + std::string ArgTypePrefix = + std::string(MDName) + "." + Kernel->getName().str() + "."; auto ArgTypeStrIt = std::find_if( BM->getStringVec().begin(), BM->getStringVec().end(), [=](SPIRVString *S) { return S->getStr().find(ArgTypePrefix) == 0; }); @@ -4101,7 +4106,7 @@ static bool transKernelArgTypeMedataFromString(LLVMContext *Ctx, } } - Kernel->setMetadata(SPIR_MD_KERNEL_ARG_TYPE, MDNode::get(*Ctx, TypeMDs)); + Kernel->setMetadata(MDName, MDNode::get(*Ctx, TypeMDs)); return true; } @@ -4227,29 +4232,32 @@ bool SPIRVToLLVM::transOCLMetadata(SPIRVFunction *BF) { return MDString::get(*Context, Qual); }); // Generate metadata for kernel_arg_type - if (!transKernelArgTypeMedataFromString(Context, BM, F)) + if (!transKernelArgTypeMedataFromString(Context, BM, F, + SPIR_MD_KERNEL_ARG_TYPE)) addOCLKernelArgumentMetadata(Context, SPIR_MD_KERNEL_ARG_TYPE, BF, F, [=](SPIRVFunctionParameter *Arg) { return transOCLKernelArgTypeName(Arg); }); // Generate metadata for kernel_arg_type_qual - addOCLKernelArgumentMetadata( - Context, SPIR_MD_KERNEL_ARG_TYPE_QUAL, BF, F, - [=](SPIRVFunctionParameter *Arg) { - std::string Qual; - if (Arg->hasDecorate(DecorationVolatile)) - Qual = kOCLTypeQualifierName::Volatile; - Arg->foreachAttr([&](SPIRVFuncParamAttrKind Kind) { - Qual += Qual.empty() ? "" : " "; - if (Kind == FunctionParameterAttributeNoAlias) - Qual += kOCLTypeQualifierName::Restrict; + if (!transKernelArgTypeMedataFromString(Context, BM, F, + SPIR_MD_KERNEL_ARG_TYPE_QUAL)) + addOCLKernelArgumentMetadata( + Context, SPIR_MD_KERNEL_ARG_TYPE_QUAL, BF, F, + [=](SPIRVFunctionParameter *Arg) { + std::string Qual; + if (Arg->hasDecorate(DecorationVolatile)) + Qual = kOCLTypeQualifierName::Volatile; + Arg->foreachAttr([&](SPIRVFuncParamAttrKind Kind) { + Qual += Qual.empty() ? "" : " "; + if (Kind == FunctionParameterAttributeNoAlias) + Qual += kOCLTypeQualifierName::Restrict; + }); + if (Arg->getType()->isTypePipe()) { + Qual += Qual.empty() ? "" : " "; + Qual += kOCLTypeQualifierName::Pipe; + } + return MDString::get(*Context, Qual); }); - if (Arg->getType()->isTypePipe()) { - Qual += Qual.empty() ? "" : " "; - Qual += kOCLTypeQualifierName::Pipe; - } - return MDString::get(*Context, Qual); - }); // Generate metadata for kernel_arg_base_type addOCLKernelArgumentMetadata(Context, SPIR_MD_KERNEL_ARG_BASE_TYPE, BF, F, [=](SPIRVFunctionParameter *Arg) { diff --git a/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp b/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp index f53cb21a82cac..205dda45ba02a 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVToLLVMDbgTran.cpp @@ -126,7 +126,7 @@ SPIRVToLLVMDbgTran::transCompileUnit(const SPIRVExtInst *DebugInst) { using namespace SPIRVDebug::Operand::CompilationUnit; assert(Ops.size() == OperandCount && "Invalid number of operands"); M->addModuleFlag(llvm::Module::Max, "Dwarf Version", Ops[DWARFVersionIdx]); - unsigned SourceLang = Ops[LanguageIdx]; + unsigned SourceLang = convertSPIRVSourceLangToDWARF(Ops[LanguageIdx]); auto Producer = findModuleProducer(); CU = Builder.createCompileUnit(SourceLang, getFile(Ops[SourceIdx]), Producer, false, "", 0); diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index c1962893dcbc0..60b918a5811d6 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -1400,10 +1400,10 @@ void transAliasingMemAccess(SPIRVModule *BM, MDNode *AliasingListMD, if (!BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_memory_access_aliasing)) return; - MemoryAccess[0] |= MemAccessMask; auto *MemAliasList = addMemAliasingINTELInstructions(BM, AliasingListMD); if (!MemAliasList) return; + MemoryAccess[0] |= MemAccessMask; MemoryAccess.push_back(MemAliasList->getId()); } @@ -3783,6 +3783,16 @@ bool LLVMToSPIRVBase::transMetadata() { return true; } +// Work around to translate kernel_arg_type and kernel_arg_type_qual metadata +static void transKernelArgTypeMD(SPIRVModule *BM, Function *F, MDNode *MD, + std::string MDName) { + std::string KernelArgTypesMDStr = + std::string(MDName) + "." + F->getName().str() + "."; + for (const auto &TyOp : MD->operands()) + KernelArgTypesMDStr += cast(TyOp)->getString().str() + ","; + BM->getString(KernelArgTypesMDStr); +} + bool LLVMToSPIRVBase::transOCLMetadata() { for (auto &F : *M) { if (F.getCallingConv() != CallingConv::SPIR_KERNEL) @@ -3794,13 +3804,9 @@ bool LLVMToSPIRVBase::transOCLMetadata() { // Create 'OpString' as a workaround to store information about // *orignal* (typedef'ed, unsigned integers) type names of kernel arguments. // OpString "kernel_arg_type.%kernel_name%.typename0,typename1,..." - if (auto *KernelArgType = F.getMetadata(SPIR_MD_KERNEL_ARG_TYPE)) { - std::string KernelArgTypesStr = - std::string(SPIR_MD_KERNEL_ARG_TYPE) + "." + F.getName().str() + "."; - for (const auto &TyOp : KernelArgType->operands()) - KernelArgTypesStr += cast(TyOp)->getString().str() + ","; - BM->getString(KernelArgTypesStr); - } + if (auto *KernelArgType = F.getMetadata(SPIR_MD_KERNEL_ARG_TYPE)) + if (BM->shouldPreserveOCLKernelArgTypeMetadataThroughString()) + transKernelArgTypeMD(BM, &F, KernelArgType, SPIR_MD_KERNEL_ARG_TYPE); if (auto *KernelArgTypeQual = F.getMetadata(SPIR_MD_KERNEL_ARG_TYPE_QUAL)) { foreachKernelArgMD( @@ -3813,6 +3819,13 @@ bool LLVMToSPIRVBase::transOCLMetadata() { new SPIRVDecorate(DecorationFuncParamAttr, BA, FunctionParameterAttributeNoAlias)); }); + // Create 'OpString' as a workaround to store information about + // constant qualifiers of pointer kernel arguments. Store empty string + // for a non constant parameter. + // OpString "kernel_arg_type_qual.%kernel_name%.qual0,qual1,..." + if (BM->shouldPreserveOCLKernelArgTypeMetadataThroughString()) + transKernelArgTypeMD(BM, &F, KernelArgTypeQual, + SPIR_MD_KERNEL_ARG_TYPE_QUAL); } if (auto *KernelArgName = F.getMetadata(SPIR_MD_KERNEL_ARG_NAME)) { foreachKernelArgMD( diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h index f09d8cddf922b..763dc19c67e77 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRV.debug.h @@ -1,6 +1,7 @@ #ifndef SPIRV_DEBUG_H #define SPIRV_DEBUG_H #include "SPIRVUtil.h" +#include "spirv.hpp" #include "llvm/BinaryFormat/Dwarf.h" namespace SPIRVDebug { @@ -790,6 +791,44 @@ enum { using namespace llvm; +inline spv::SourceLanguage convertDWARFSourceLangToSPIRV(dwarf::SourceLanguage DwarfLang) { + switch (DwarfLang) { + // When updating this function, make sure to also + // update convertSPIRVSourceLangToDWARF() + + // LLVM does not yet define DW_LANG_C_plus_plus_17 + // case dwarf::SourceLanguage::DW_LANG_C_plus_plus_17: + case dwarf::SourceLanguage::DW_LANG_C_plus_plus_14: + case dwarf::SourceLanguage::DW_LANG_C_plus_plus: + return spv::SourceLanguage::SourceLanguageCPP_for_OpenCL; + case dwarf::SourceLanguage::DW_LANG_C99: + case dwarf::SourceLanguage::DW_LANG_OpenCL: + return spv::SourceLanguage::SourceLanguageOpenCL_C; + default: + return spv::SourceLanguage::SourceLanguageUnknown; + } +} + +inline dwarf::SourceLanguage convertSPIRVSourceLangToDWARF(unsigned SourceLang) { + switch (SourceLang) { + // When updating this function, make sure to also + // update convertDWARFSourceLangToSPIRV() + case spv::SourceLanguage::SourceLanguageOpenCL_CPP: + return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; + case spv::SourceLanguage::SourceLanguageCPP_for_OpenCL: + // LLVM does not yet define DW_LANG_C_plus_plus_17 + // SourceLang = dwarf::SourceLanguage::DW_LANG_C_plus_plus_17; + return dwarf::SourceLanguage::DW_LANG_C_plus_plus_14; + case spv::SourceLanguage::SourceLanguageOpenCL_C: + case spv::SourceLanguage::SourceLanguageESSL: + case spv::SourceLanguage::SourceLanguageGLSL: + case spv::SourceLanguage::SourceLanguageHLSL: + case spv::SourceLanguage::SourceLanguageUnknown: + default: + return dwarf::DW_LANG_OpenCL; + } +} + namespace SPIRV { typedef SPIRVMap DbgEncodingMap; template <> diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h index f03e777cfe110..acb2aab1f4ab4 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEntry.h @@ -1009,9 +1009,6 @@ _SPIRV_OP(IAddCarry) _SPIRV_OP(ISubBorrow) _SPIRV_OP(SMulExtended) _SPIRV_OP(UMulExtended) -_SPIRV_OP(BitFieldInsert) -_SPIRV_OP(BitFieldSExtract) -_SPIRV_OP(BitFieldUExtract) _SPIRV_OP(DPdx) _SPIRV_OP(DPdy) _SPIRV_OP(Fwidth) diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h index 0cdaa40d99329..11e41092895c4 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h @@ -1555,7 +1555,6 @@ _SPIRV_OP(SignBitSet) _SPIRV_OP(Any) _SPIRV_OP(All) _SPIRV_OP(BitCount) -_SPIRV_OP(BitReverse) #undef _SPIRV_OP #define _SPIRV_OP_INTERNAL(x) typedef SPIRVUnaryInst SPIRV##x; _SPIRV_OP_INTERNAL(ArithmeticFenceINTEL) @@ -2900,6 +2899,32 @@ _SPIRV_OP(UDotAccSatKHR, true, 6, true, 3) _SPIRV_OP(SUDotAccSatKHR, true, 6, true, 3) #undef _SPIRV_OP +class SPIRVBitOp : public SPIRVInstTemplateBase { +public: + SPIRVCapVec getRequiredCapability() const override { + if (Module->isAllowedToUseExtension(ExtensionID::SPV_KHR_bit_instructions)) + return getVec(CapabilityBitInstructions); + + return getVec(CapabilityShader); + } + + llvm::Optional getRequiredExtension() const override { + for (auto Cap : getRequiredCapability()) { + if (Cap == CapabilityBitInstructions) + return ExtensionID::SPV_KHR_bit_instructions; + } + return None; + } +}; + +#define _SPIRV_OP(x, ...) \ + typedef SPIRVInstTemplate SPIRV##x; +_SPIRV_OP(BitFieldInsert, true, 7) +_SPIRV_OP(BitFieldSExtract, true, 6) +_SPIRV_OP(BitFieldUExtract, true, 6) +_SPIRV_OP(BitReverse, true, 4) +#undef _SPIRV_OP + class SPIRVSubgroupShuffleINTELInstBase : public SPIRVInstTemplateBase { protected: SPIRVCapVec getRequiredCapability() const override { diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h index 21e25159531b8..acf8ae56559b1 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h @@ -514,6 +514,11 @@ class SPIRVModule { return TranslationOpts.shouldReplaceLLVMFmulAddWithOpenCLMad(); } + bool shouldPreserveOCLKernelArgTypeMetadataThroughString() const noexcept { + return TranslationOpts + .shouldPreserveOCLKernelArgTypeMetadataThroughString(); + } + SPIRVExtInstSetKind getDebugInfoEIS() const { switch (TranslationOpts.getDebugInfoEIS()) { case DebugInfoEIS::SPIRV_Debug: diff --git a/llvm-spirv/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll b/llvm-spirv/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll new file mode 100644 index 0000000000000..f6c381c565a97 --- /dev/null +++ b/llvm-spirv/test/DebugInfo/SourceLanguageLLVMToSPIRV.ll @@ -0,0 +1,43 @@ +; Test checks that DW_LANG_C99 and DW_LANG_OpenCL are mapped to OpenCL C +; in the SourceLanguage enum, and also that DW_LANG_C_plus_plus and +; DW_LANG_C_plus_plus_14 are mapped to C++ for OpenCL. + +; LLVM does not yet define DW_LANG_C_plus_plus_17. A test case that +; checks DW_LANG_C_plus_plus_17 is mapped to C++ for OpenCL should be +; added once this is defined. + +; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C99/' %s | llvm-as - -o %t.bc +; RUN: llvm-spirv -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-OPENCLC + +; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_OpenCL/' %s | llvm-as - -o %t.bc +; RUN: llvm-spirv -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-OPENCLC + +; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus/' %s | llvm-as - -o %t.bc +; RUN: llvm-spirv -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP4OPENCL + +; RUN: sed -e 's/INPUT_LANGUAGE/DW_LANG_C_plus_plus_14/' %s | llvm-as - -o %t.bc +; RUN: llvm-spirv -spirv-text %t.bc -o - | FileCheck %s --check-prefix=CHECK-CPP4OPENCL + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +target triple = "spir64-unknown-unknown" + +define dso_local spir_kernel void @func() local_unnamed_addr !dbg !7 !kernel_arg_addr_space !2 !kernel_arg_access_qual !2 !kernel_arg_type !2 !kernel_arg_base_type !2 !kernel_arg_type_qual !2 { +entry: + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} + +!0 = distinct !DICompileUnit(language: INPUT_LANGUAGE, file: !1) +!1 = !DIFile(filename: "test.cl", directory: "/tmp", checksumkind: CSK_MD5, checksum: "18aa9ce738eaafc7b7b7181c19092815") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 2, i32 0} +!7 = distinct !DISubprogram(name: "func", scope: !8, file: !8, line: 1, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!8 = !DIFile(filename: "test.cl", directory: "/tmp", checksumkind: CSK_MD5, checksum: "18aa9ce738eaafc7b7b7181c19092815") + +; CHECK-OPENCLC: DebugCompileUnit {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 3 +; CHECK-CPP4OPENCL: DebugCompileUnit {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 6 diff --git a/llvm-spirv/test/DebugInfo/SourceLanguageSPIRVToLLVM.spvasm b/llvm-spirv/test/DebugInfo/SourceLanguageSPIRVToLLVM.spvasm new file mode 100644 index 0000000000000..3c8c07d1ca9f3 --- /dev/null +++ b/llvm-spirv/test/DebugInfo/SourceLanguageSPIRVToLLVM.spvasm @@ -0,0 +1,66 @@ +; Test checks that: +; - OpenCL_CPP is mapped to DW_LANG_C_plus_plus_14 +; - CPP_for_OpenCL is mapped to DW_LANG_C_plus_plus_17 +; - OpenCL_C, GLSL, ESSL, HLSL, and Unknown are mapped to DW_LANG_OpenCL + +; LLVM does not yet define DW_LANG_C_plus_plus_17. When it is defined, the +; test case for C++ for OpenCL should be updated to check that CPP_for_OpenCL +; is mapped to DW_LANG_C_plus_plus_17, not DW_LANG_C_plus_plus_14. + +; REQUIRES: spirv-as + +; RUN: sed -e 's/SOURCE_LANGUAGE/OpenCL_CPP/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-CPP14 + +; COM: TODO: Enable this test when the version of SPIRV-Tools used by buildbot is updated to +; COM: recognise CPP_for_OpenCL as a valid source language. +; COM: sed -e 's/SOURCE_LANGUAGE/CPP_for_OpenCL/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; COM: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-CPP14 + +; RUN: sed -e 's/SOURCE_LANGUAGE/OpenCL_C/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-OPENCL + +; RUN: sed -e 's/SOURCE_LANGUAGE/GLSL/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-OPENCL + +; RUN: sed -e 's/SOURCE_LANGUAGE/HLSL/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-OPENCL + +; RUN: sed -e 's/SOURCE_LANGUAGE/ESSL/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-OPENCL + +; RUN: sed -e 's/SOURCE_LANGUAGE/Unknown/' %s | spirv-as --target-env spv1.3 - -o %t.spv +; RUN: llvm-spirv -r %t.spv -o - | llvm-dis | FileCheck %s --check-prefix=CHECK-OPENCL + +; SPIR-V +; Version: 1.1 +; Generator: Khronos LLVM/SPIR-V Translator; 14 +; Bound: 16 +; Schema: 0 + OpCapability Addresses + OpCapability Kernel + %1 = OpExtInstImport "OpenCL.std" + %2 = OpExtInstImport "OpenCL.DebugInfo.100" + OpMemoryModel Physical64 OpenCL + OpEntryPoint Kernel %5 "func" + %7 = OpString "kernel_arg_type.func." + %8 = OpString "/tmp/test.cl" + %9 = OpString "//__CSK_MD5:18aa9ce738eaafc7b7b7181c19092815" + %12 = OpString "func" + %14 = OpString "" + OpSource Unknown 0 + OpName %entry "entry" + OpModuleProcessed "Debug info producer: " + %void = OpTypeVoid + %4 = OpTypeFunction %void + %10 = OpExtInst %void %2 DebugSource %8 %9 + %11 = OpExtInst %void %2 DebugCompilationUnit 65536 5 %10 SOURCE_LANGUAGE + %13 = OpExtInst %void %2 DebugInfoNone + %15 = OpExtInst %void %2 DebugFunction %12 %13 %10 1 0 %11 %14 FlagIsDefinition|FlagPrototyped|FlagIsOptimized 2 %5 %13 + %5 = OpFunction %void None %4 + %entry = OpLabel + OpReturn + OpFunctionEnd + +; CHECK-OPENCL: !DICompileUnit(language: DW_LANG_OpenCL, +; CHECK-CPP14: !DICompileUnit(language: DW_LANG_C_plus_plus_14, diff --git a/llvm-spirv/test/DebugInfo/X86/dbg-file-name.ll b/llvm-spirv/test/DebugInfo/X86/dbg-file-name.ll index c6325ac3369bb..76a4cd8f45a61 100644 --- a/llvm-spirv/test/DebugInfo/X86/dbg-file-name.ll +++ b/llvm-spirv/test/DebugInfo/X86/dbg-file-name.ll @@ -2,7 +2,7 @@ ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: llvm-spirv -r %t.spv -o - | llvm-dis -o %t.ll -; RUN: llc -enable-dwarf-directory -mtriple x86_64-apple-darwin10.0.0 < %t.ll | FileCheck %s +; RUN: llc --dwarf-directory -mtriple x86_64-apple-darwin10.0.0 < %t.ll | FileCheck %s target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" target triple = "spir64-unknown-unknown" diff --git a/llvm-spirv/test/FortranArray.ll b/llvm-spirv/test/FortranArray.ll index 49253dfb7e661..770f76c7eeedc 100644 --- a/llvm-spirv/test/FortranArray.ll +++ b/llvm-spirv/test/FortranArray.ll @@ -5,6 +5,11 @@ ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis %t.rev.bc -o - | FileCheck %s --check-prefix=CHECK-LLVM +; XFAIL: * +; The language ID is not preserved when translating from .ll to .spv +; and back to .ll. This causes the LLVM IR verifier to fail as there +; are different rules for valid DISubRange depending on language ID. + ; CHECK-LLVM: !DISubrange(lowerBound: 1) source_filename = "llvm-link" diff --git a/llvm-spirv/test/kernel-arg-ext_int-ptr.spt b/llvm-spirv/test/kernel-arg-ext_int-ptr.spt index b18c4a816db5b..6e4c9e5e094f8 100644 --- a/llvm-spirv/test/kernel-arg-ext_int-ptr.spt +++ b/llvm-spirv/test/kernel-arg-ext_int-ptr.spt @@ -25,9 +25,13 @@ ; RUN: llvm-spirv %s -to-binary -o %t.spv ; Reverse translation shouldn't crash: +; RUN: llvm-spirv -r -preserve-ocl-kernel-arg-type-metadata-through-string %t.spv -o %t.bc +; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM-STR-WORKAROUND ; RUN: llvm-spirv -r %t.spv -o %t.bc -; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM +; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM-NO-WORKAROUND -; CHECK-LLVM: define spir_kernel void @kernel_func1(i31 addrspace(1)* %_arg_){{.*}} !kernel_arg_type ![[ArgTy:[0-9]+]]{{.*}} !kernel_arg_base_type ![[BaseArgTy:[0-9]+]] -; CHECK-LLVM: ![[ArgTy]] = !{!"_ExtInt(31)*"} -; CHECK-LLVM: ![[BaseArgTy]] = !{!"int31_t*"} +; CHECK-LLVM-STR-WORKAROUND: define spir_kernel void @kernel_func1(i31 addrspace(1)* %_arg_){{.*}} !kernel_arg_type ![[ArgTy:[0-9]+]]{{.*}} !kernel_arg_base_type ![[BaseArgTy:[0-9]+]] +; CHECK-LLVM-STR-WORKAROUND: ![[ArgTy]] = !{!"_ExtInt(31)*"} +; CHECK-LLVM-STR-WORKAROUND: ![[BaseArgTy]] = !{!"int31_t*"} +; CHECK-LLVM-NO-WORKAROUND: define spir_kernel void @kernel_func1(i31 addrspace(1)* %_arg_){{.*}} !kernel_arg_type ![[ArgTy:[0-9]+]]{{.*}} !kernel_arg_base_type ![[ArgTy:[0-9]+]] +; CHECK-LLVM-NO-WORKAROUND: ![[ArgTy]] = !{!"int31_t*"} diff --git a/llvm-spirv/test/transcoding/KernelArgTypeInOpString.ll b/llvm-spirv/test/transcoding/KernelArgTypeInOpString.ll index f6b43e5c45486..790f1c91e4915 100644 --- a/llvm-spirv/test/transcoding/KernelArgTypeInOpString.ll +++ b/llvm-spirv/test/transcoding/KernelArgTypeInOpString.ll @@ -21,21 +21,31 @@ ; OpString "kernel_arg_type.%kernel_name%.typename0,typename1,..." ; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv -preserve-ocl-kernel-arg-type-metadata-through-string %t.bc -spirv-text -o %t.spv.txt +; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV-WORKAROUND ; RUN: llvm-spirv %t.bc -spirv-text -o %t.spv.txt -; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV +; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV-WORKAROUND-NEGATIVE +; RUN: llvm-spirv -preserve-ocl-kernel-arg-type-metadata-through-string %t.bc -o %t.spv +; RUN: spirv-val %t.spv +; RUN: llvm-spirv -r -preserve-ocl-kernel-arg-type-metadata-through-string %t.spv -o %t.rev.bc +; RUN: llvm-dis %t.rev.bc +; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM-WORKAROUND ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: spirv-val %t.spv ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis %t.rev.bc -; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM +; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM-WORKAROUND-NEGATIVE target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir-unknown-unknown" -; CHECK-SPIRV: String 14 "kernel_arg_type.foo.image_kernel_data*,myInt,struct struct_name*," +; CHECK-SPIRV-WORKAROUND: String 14 "kernel_arg_type.foo.image_kernel_data*,myInt,struct struct_name*," +; CHECK-SPIRV-WORKAROUND-NEGATIVE-NOT: String 14 "kernel_arg_type.foo.image_kernel_data*,myInt,struct struct_name*," -; CHECK-LLVM: !kernel_arg_type [[TYPE:![0-9]+]] -; CHECK-LLVM: [[TYPE]] = !{!"image_kernel_data*", !"myInt", !"struct struct_name*"} +; CHECK-LLVM-WORKAROUND: !kernel_arg_type [[TYPE:![0-9]+]] +; CHECK-LLVM-WORKAROUND: [[TYPE]] = !{!"image_kernel_data*", !"myInt", !"struct struct_name*"} +; CHECK-LLVM-WORKAROUND-NEGATIVE: !kernel_arg_type [[TYPE:![0-9]+]] +; CHECK-LLVM-WORKAROUND-NEGATIVE-NOT: [[TYPE]] = !{!"image_kernel_data*", !"myInt", !"struct struct_name*"} %struct.image_kernel_data = type { i32, i32, i32, i32, i32 } %struct.struct_name = type { i32, i32 } diff --git a/llvm-spirv/test/transcoding/KernelArgTypeInOpString2.ll b/llvm-spirv/test/transcoding/KernelArgTypeInOpString2.ll index 3e950c4c2a0ac..4456b935d4bdb 100644 --- a/llvm-spirv/test/transcoding/KernelArgTypeInOpString2.ll +++ b/llvm-spirv/test/transcoding/KernelArgTypeInOpString2.ll @@ -23,21 +23,31 @@ ; OpString "kernel_arg_type.%kernel_name%.typename0,typename1,..." ; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv -preserve-ocl-kernel-arg-type-metadata-through-string %t.bc -spirv-text -o %t.spv.txt +; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV-WORKAROUND ; RUN: llvm-spirv %t.bc -spirv-text -o %t.spv.txt -; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV +; RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV-WORKAROUND-NEGATIVE +; RUN: llvm-spirv -preserve-ocl-kernel-arg-type-metadata-through-string %t.bc -o %t.spv +; RUN: spirv-val %t.spv +; RUN: llvm-spirv -r -preserve-ocl-kernel-arg-type-metadata-through-string %t.spv -o %t.rev.bc +; RUN: llvm-dis %t.rev.bc +; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM-WORKAROUND ; RUN: llvm-spirv %t.bc -o %t.spv ; RUN: spirv-val %t.spv ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: llvm-dis %t.rev.bc -; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM +; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM-WORKAROUND-NEGATIVE target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" target triple = "spir" -; CHECK-SPIRV: String 17 "kernel_arg_type.foo.cl::tt::vec*," +; CHECK-SPIRV-WORKAROUND: String 17 "kernel_arg_type.foo.cl::tt::vec*," +; CHECK-SPIRV-WORKAROUND-NEGATIVE-NOT: String 17 "kernel_arg_type.foo.cl::tt::vec*," -; CHECK-LLVM: !kernel_arg_type [[TYPE:![0-9]+]] -; CHECK-LLVM: [[TYPE]] = !{!"cl::tt::vec*"} +; CHECK-LLVM-WORKAROUND: !kernel_arg_type [[TYPE:![0-9]+]] +; CHECK-LLVM-WORKAROUND: [[TYPE]] = !{!"cl::tt::vec*"} +; CHECK-LLVM-WORKAROUND-NEGATIVE: !kernel_arg_type [[TYPE:![0-9]+]] +; CHECK-LLVM-WORKAROUND-NEGATIVE-NOT: [[TYPE]] = !{!"cl::tt::vec*"} %"class.cl::tt::vec" = type { [4 x float] } diff --git a/llvm-spirv/test/transcoding/SPV_INTEL_memory_access_aliasing/intel-alias-empty-md.ll b/llvm-spirv/test/transcoding/SPV_INTEL_memory_access_aliasing/intel-alias-empty-md.ll new file mode 100644 index 0000000000000..d0ba92e023064 --- /dev/null +++ b/llvm-spirv/test/transcoding/SPV_INTEL_memory_access_aliasing/intel-alias-empty-md.ll @@ -0,0 +1,41 @@ +; Check that the translator doesn't fail on a translation of empty aliasing +; metadata + +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc --spirv-ext=+SPV_INTEL_memory_access_aliasing -o %t.spv +; RUN: llvm-spirv %t.spv -to-text -o %t.spt +; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV + +; CHECK-SPIRV-NOT: Capability MemoryAccessAliasingINTEL +; CHECK-SPIRV-NOT: Extension "SPV_INTEL_memory_access_aliasing" +; CHECK-SPIRV-NOT: AliasDomainDeclINTEL +; CHECK-SPIRV-NOT: AliasScopeDeclINTEL +; CHECK-SPIRV-NOT: AliasScopeListDeclINTEL + +; ModuleID = 'optimized_intel_restrict.bc' +source_filename = "intel_restrict.cpp" +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" +target triple = "spir64-unknown-unknown-sycldevice" + +define dso_local spir_kernel void @_ZTSZ4mainE15kernel_restrict(i32 addrspace(1)* noalias %_arg_, i32 addrspace(1)* noalias %_arg_1, i32 addrspace(1)* noalias %_arg_3) local_unnamed_addr { +entry: + %0 = addrspacecast i32 addrspace(1)* %_arg_ to i32 addrspace(4)* + %1 = addrspacecast i32 addrspace(1)* %_arg_1 to i32 addrspace(4)* + %2 = addrspacecast i32 addrspace(1)* %_arg_3 to i32 addrspace(4)* + %3 = load i32, i32 addrspace(4)* %0, align 4, !alias.scope !4 + %4 = load i32, i32 addrspace(4)* %1, align 4, !alias.scope !4 + %add.i = add nsw i32 %4, %3 + store i32 %add.i, i32 addrspace(4)* %2, align 4, !noalias !4 + ret void +} + +!llvm.module.flags = !{!0} +!opencl.spir.version = !{!1} +!spirv.Source = !{!2} +!llvm.ident = !{!3} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, i32 2} +!2 = !{i32 4, i32 100000} +!3 = !{!"clang version 13.0.0"} +!4 = !{} diff --git a/llvm-spirv/test/transcoding/cl-types.ll b/llvm-spirv/test/transcoding/cl-types.ll index de4fd74f69ec5..66896ea11d166 100644 --- a/llvm-spirv/test/transcoding/cl-types.ll +++ b/llvm-spirv/test/transcoding/cl-types.ll @@ -94,7 +94,7 @@ target triple = "spir-unknown-unknown" ; CHECK-LLVM-SAME: !kernel_arg_access_qual [[AQ:![0-9]+]] ; CHECK-LLVM-SAME: !kernel_arg_type [[TYPE:![0-9]+]] ; CHECK-LLVM-SAME: !kernel_arg_type_qual [[TQ:![0-9]+]] -; CHECK-LLVM-SAME: !kernel_arg_base_type [[BT:![0-9]+]] +; CHECK-LLVM-SAME: !kernel_arg_base_type [[TYPE]] ; Function Attrs: nounwind readnone define spir_kernel void @foo( @@ -138,8 +138,7 @@ attributes #0 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-point ; CHECK-LLVM-DAG: [[AS]] = !{i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 0} ; CHECK-LLVM-DAG: [[AQ]] = !{!"read_only", !"write_only", !"read_only", !"read_only", !"read_only", !"read_only", !"read_only", !"write_only", !"read_write", !"none"} -; CHECK-LLVM-DAG: [[TYPE]] = !{!"int", !"int", !"image1d_t", !"image2d_t", !"image3d_t", !"image2d_array_t", !"image1d_buffer_t", !"image1d_t", !"image2d_t", !"sampler_t"} -; CHECK-LLVM-DAG: [[BT]] = !{!"pipe", !"pipe", !"image1d_t", !"image2d_t", !"image3d_t", !"image2d_array_t", !"image1d_buffer_t", !"image1d_t", !"image2d_t", !"sampler_t"} +; CHECK-LLVM-DAG: [[TYPE]] = !{!"pipe", !"pipe", !"image1d_t", !"image2d_t", !"image3d_t", !"image2d_array_t", !"image1d_buffer_t", !"image1d_t", !"image2d_t", !"sampler_t"} ; CHECK-LLVM-DAG: [[TQ]] = !{!"pipe", !"pipe", !"", !"", !"", !"", !"", !"", !"", !""} !1 = !{i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 0} diff --git a/llvm-spirv/test/transcoding/cl_khr_extended_bit_ops.cl b/llvm-spirv/test/transcoding/cl_khr_extended_bit_ops.cl new file mode 100644 index 0000000000000..e7c1c6633c0f1 --- /dev/null +++ b/llvm-spirv/test/transcoding/cl_khr_extended_bit_ops.cl @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -triple spir-unknown-unknown -O1 -cl-std=CL2.0 -fdeclare-opencl-builtins -finclude-default-header -emit-llvm-bc %s -o %t.bc +// RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_bit_instructions -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV +// RUN: llvm-spirv %t.bc --spirv-ext=+SPV_KHR_bit_instructions -o %t.spv +// RUN: llvm-spirv -r %t.spv -o %t.rev.bc +// RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM + +// TODO: remove prototypes once bit op builtins are available in clang. +#define __ovld __attribute__((overloadable)) + +int2 __ovld bitfield_insert(int2, int2, uint, uint); +short __ovld bitfield_extract_signed(short, uint, uint); +short __ovld bitfield_extract_signed(ushort, uint, uint); +uchar8 __ovld bitfield_extract_unsigned(char8, uint, uint); +uchar8 __ovld bitfield_extract_unsigned(uchar8, uint, uint); +ulong4 __ovld bit_reverse(ulong4); + +// CHECK-SPIRV: Capability BitInstructions +// CHECK-SPIRV: Extension "SPV_KHR_bit_instructions" + +// CHECK-LLVM-LABEL: @testInsert +// CHECK-LLVM: call spir_func <2 x i32> @_Z15bitfield_insertDv2_iS_jj +// CHECK-SPIRV: Function +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[insbase:[0-9]+]] +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[insins:[0-9]+]] +// CHECK-SPIRV: BitFieldInsert {{[0-9]+}} {{[0-9]+}} [[insbase]] [[insins]] +kernel void testInsert(int2 b, int2 i, global int2 *res) { + *res = bitfield_insert(b, i, 4, 2); +} + +// CHECK-LLVM-LABEL: @testExtractS +// CHECK-LLVM: call spir_func i16 @_Z23bitfield_extract_signedsjj +// CHECK-LLVM: call spir_func i16 @_Z23bitfield_extract_signedsjj +// CHECK-SPIRV: Function +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[sextrbase:[0-9]+]] +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[sextrbaseu:[0-9]+]] +// CHECK-SPIRV: BitFieldSExtract {{[0-9]+}} {{[0-9]+}} [[sextrbase]] +// CHECK-SPIRV: BitFieldSExtract {{[0-9]+}} {{[0-9]+}} [[sextrbaseu]] +kernel void testExtractS(short b, ushort bu, global short *res) { + *res = bitfield_extract_signed(b, 5, 4); + *res += bitfield_extract_signed(bu, 5, 4); +} + +// CHECK-LLVM-LABEL: @testExtractU +// CHECK-LLVM: call spir_func <8 x i8> @_Z25bitfield_extract_unsignedDv8_cjj +// CHECK-LLVM: call spir_func <8 x i8> @_Z25bitfield_extract_unsignedDv8_cjj +// CHECK-SPIRV: Function +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[uextrbase:[0-9]+]] +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[uextrbaseu:[0-9]+]] +// CHECK-SPIRV: BitFieldUExtract {{[0-9]+}} {{[0-9]+}} [[uextrbase]] +// CHECK-SPIRV: BitFieldUExtract {{[0-9]+}} {{[0-9]+}} [[uextrbaseu]] +kernel void testExtractU(char8 b, uchar8 bu, global uchar8 *res) { + *res = bitfield_extract_unsigned(b, 3, 4); + *res += bitfield_extract_unsigned(bu, 3, 4); +} + +// CHECK-LLVM-LABEL: @testBitReverse +// CHECK-LLVM: call <4 x i64> @llvm.bitreverse.v4i64 +// CHECK-SPIRV: Function +// CHECK-SPIRV: FunctionParameter {{[0-9]+}} [[revbase:[0-9]+]] +// CHECK-SPIRV: BitReverse {{[0-9]+}} {{[0-9]+}} [[revbase]] +kernel void testBitReverse(ulong4 b, global ulong4 *res) { + *res = bit_reverse(b); +} diff --git a/llvm-spirv/test/transcoding/kernel_arg_name.ll b/llvm-spirv/test/transcoding/kernel_arg_name.ll index 1cda3220fcb7f..4c4476ab173c6 100644 --- a/llvm-spirv/test/transcoding/kernel_arg_name.ll +++ b/llvm-spirv/test/transcoding/kernel_arg_name.ll @@ -5,9 +5,9 @@ ; CHECK: spir_kernel void @unnamed_arg(float{{.*}}) {{.*}} !kernel_arg_name ![[MD_unnamed:[0-9]+]] ; CHECK: spir_kernel void @one_unnamed_arg(i8 %a, i8 %b, i8{{.*}}) {{.*}} !kernel_arg_name ![[MD_one_unnamed:[0-9]+]] -; CHECK: ![[MD_unnamed]] = !{!""} -; CHECK: ![[MD_named]] = !{!"f"} -; CHECK: ![[MD_one_unnamed]] = !{!"a", !"b", !""} +; CHECK-DAG: ![[MD_named]] = !{!"f"} +; CHECK-DAG: ![[MD_unnamed]] = !{!""} +; CHECK-DAG: ![[MD_one_unnamed]] = !{!"a", !"b", !""} ; ModuleID = 'kernel_arg_name.ll' source_filename = "kernel_arg_name.ll" diff --git a/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll b/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll new file mode 100644 index 0000000000000..a8a2d80396463 --- /dev/null +++ b/llvm-spirv/test/transcoding/kernel_arg_type_qual.ll @@ -0,0 +1,43 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv -preserve-ocl-kernel-arg-type-metadata-through-string %t.bc -o - -spirv-text | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llvm-spirv %t.bc -o - -spirv-text | FileCheck %s --check-prefix=CHECK-SPIRV-NEGATIVE +; RUN: llvm-spirv -preserve-ocl-kernel-arg-type-metadata-through-string %t.bc -o %t.spv +; RUN: llvm-spirv -r -preserve-ocl-kernel-arg-type-metadata-through-string %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM-WORKAROUND +; RUN: llvm-spirv %t.bc -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.rev.bc +; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM-WORKAROUND-NEGATIVE + +; ModuleID = 'test.cl' +source_filename = "test.cl" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "spir64-unknown-unknown." + +; CHECK-SPIRV: String 12 "kernel_arg_type_qual.test.volatile,const,," +; CHECK-SPIRV: Name [[ARG:[0-9]+]] "g" +; CHECK-SPIRV: Decorate [[ARG]] Volatile +; CHECK-SPIRV-NEGATIVE-NOT: String 12 "kernel_arg_type_qual.test.volatile,const,," + +; CHECK-LLVM-WORKAROUND: !kernel_arg_type_qual ![[QUAL:[0-9]+]] +; CHECK-LLVM-WORKAROUND: ![[QUAL]] = !{!"volatile", !"const", !""} +; CHECK-LLVM-WORKAROUND-NEGATIVE: !kernel_arg_type_qual + +; Function Attrs: convergent noinline norecurse nounwind optnone +define dso_local spir_kernel void @test(float addrspace(1)* %g, float addrspace(1)* %c, float addrspace(1)* %asd) #0 !kernel_arg_addr_space !3 !kernel_arg_access_qual !4 !kernel_arg_type !5 !kernel_arg_base_type !5 !kernel_arg_type_qual !6 { +entry: + ret void +} + +attributes #1 = { convergent noinline norecurse nounwind optnone } + +!llvm.module.flags = !{!0} +!opencl.ocl.version = !{!1} +!llvm.ident = !{!2} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 1, i32 0} +!2 = !{!"clang version 13.0.0"} +!3 = !{i32 1, i32 1} +!4 = !{!"none", !"none"} +!5 = !{!"float*", !"float*"} +!6 = !{!"volatile", !"const", !""} diff --git a/llvm-spirv/test/transcoding/spirv-types.ll b/llvm-spirv/test/transcoding/spirv-types.ll index 6fdacff7211f5..06a419c9c1d1b 100644 --- a/llvm-spirv/test/transcoding/spirv-types.ll +++ b/llvm-spirv/test/transcoding/spirv-types.ll @@ -100,7 +100,7 @@ target triple = "spir-unknown-unknown" ; CHECK-LLVM-SAME: !kernel_arg_access_qual [[AQ:![0-9]+]] ; CHECK-LLVM-SAME: !kernel_arg_type [[TYPE:![0-9]+]] ; CHECK-LLVM-SAME: !kernel_arg_type_qual [[TQ:![0-9]+]] -; CHECK-LLVM-SAME: !kernel_arg_base_type [[BT:![0-9]+]] +; CHECK-LLVM-SAME: !kernel_arg_base_type [[TYPE]] ; Function Attrs: nounwind readnone define spir_kernel void @foo( @@ -170,8 +170,7 @@ attributes #0 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-point ; CHECK-LLVM-DAG: [[AS]] = !{i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1} ; CHECK-LLVM-DAG: [[AQ]] = !{!"read_only", !"write_only", !"read_only", !"read_only", !"read_only", !"read_only", !"read_only", !"write_only", !"read_write"} -; CHECK-LLVM-DAG: [[TYPE]] = !{!"int", !"int", !"image1d_t", !"image2d_t", !"image3d_t", !"image2d_array_t", !"image1d_buffer_t", !"image1d_t", !"image2d_t"} -; CHECK-LLVM-DAG: [[BT]] = !{!"pipe", !"pipe", !"image1d_t", !"image2d_t", !"image3d_t", !"image2d_array_t", !"image1d_buffer_t", !"image1d_t", !"image2d_t"} +; CHECK-LLVM-DAG: [[TYPE]] = !{!"pipe", !"pipe", !"image1d_t", !"image2d_t", !"image3d_t", !"image2d_array_t", !"image1d_buffer_t", !"image1d_t", !"image2d_t"} ; CHECK-LLVM-DAG: [[TQ]] = !{!"pipe", !"pipe", !"", !"", !"", !"", !"", !"", !""} !1 = !{i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1} diff --git a/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp b/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp index 4529b3676b42c..78d6cefd82ace 100644 --- a/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp +++ b/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp @@ -137,6 +137,12 @@ static cl::opt BIsRepresentation( "SPIR-V Friendly IR")), cl::init(SPIRV::BIsRepresentation::OpenCL12)); +static cl::opt + PreserveOCLKernelArgTypeMetadataThroughString( + "preserve-ocl-kernel-arg-type-metadata-through-string", cl::init(false), + cl::desc("Preserve OpenCL kernel_arg_type and kernel_arg_type_qual " + "metadata through OpString")); + using SPIRV::ExtensionID; #ifdef _SPIRV_SUPPORT_TEXT_FMT @@ -627,6 +633,9 @@ int main(int Ac, char **Av) { } } + if (PreserveOCLKernelArgTypeMetadataThroughString.getNumOccurrences() != 0) + Opts.setPreserveOCLKernelArgTypeMetadataThroughString(true); + #ifdef _SPIRV_SUPPORT_TEXT_FMT if (ToText && (ToBinary || IsReverse || IsRegularization)) { errs() << "Cannot use -to-text with -to-binary, -r, -s\n"; diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 242e44b84cdbb..0a25fda829fd3 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1164,6 +1164,7 @@ The AMDGPU backend uses the following ELF header: *reserved* 0x041 Reserved. ``EF_AMDGPU_MACH_AMDGCN_GFX1013`` 0x042 ``gfx1013`` *reserved* 0x043 Reserved. + *reserved* 0x044 Reserved. ==================================== ========== ============================= Sections @@ -1574,6 +1575,7 @@ The following relocation types are supported: ``R_AMDGPU_REL32_HI`` Static 11 ``word32`` (S + A - P) >> 32 *reserved* 12 ``R_AMDGPU_RELATIVE64`` Dynamic 13 ``word64`` B + A + ``R_AMDGPU_REL16`` Static 14 ``word16`` ((S + A - P) - 4) / 4 ========================== ======= ===== ========== ============================== ``R_AMDGPU_ABS32_LO`` and ``R_AMDGPU_ABS32_HI`` are only supported by @@ -12200,6 +12202,7 @@ This kernel is equivalent to the following HIP program: .. code:: :number-lines: + __global__ void hello_world(float *p) { *p = 3.14159f; } diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index bab0508fdeb3d..74630f3e368a5 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -65,7 +65,10 @@ We use here the command-line, non-interactive CMake interface. itself is the correct one for your development environment. CMake will refuse to build MinGW makefiles if you have a POSIX shell reachable through the PATH environment variable, for instance. You can force CMake to use a given build - tool; for instructions, see the `Usage`_ section, below. + tool; for instructions, see the `Usage`_ section, below. You may + also wish to control which targets LLVM enables, or which LLVM + components are built; see the `Frequently Used LLVM-related + variables`_ below. #. After CMake has finished running, proceed to use IDE project files, or start the build from the build directory: @@ -179,47 +182,85 @@ Frequently-used CMake variables ------------------------------- Here are some of the CMake variables that are used often, along with a -brief explanation and LLVM-specific notes. For full documentation, consult the -CMake manual, or execute ``cmake --help-variable VARIABLE_NAME``. +brief explanation. For full documentation, consult the CMake manual, +or execute ``cmake --help-variable VARIABLE_NAME``. See `Frequently +Used LLVM-related Variables`_ below for information about commonly +used variables that control features of LLVM and enabled subprojects. **CMAKE_BUILD_TYPE**:STRING Sets the build type for ``make``-based generators. Possible values are Release, Debug, RelWithDebInfo and MinSizeRel. If you are using an IDE such as Visual Studio, you should use the IDE settings to set the build type. Be aware that Release and RelWithDebInfo use different optimization levels on - most platforms. + most platforms. Be aware that Release and + RelWithDebInfo use different optimization levels on most + platforms, and that the default value of ``LLVM_ENABLE_ASSERTIONS`` + is affected. **CMAKE_INSTALL_PREFIX**:PATH - Path where LLVM will be installed if "make install" is invoked or the - "install" target is built. + Path where LLVM will be installed when the "install" target is built. -**CMAKE_C_FLAGS**:STRING - Extra flags to use when compiling C source files. +**CMAKE_{C,CXX}_FLAGS**:STRING + Extra flags to use when compiling C and C++ source files respectively. -**CMAKE_CXX_FLAGS**:STRING - Extra flags to use when compiling C++ source files. +**CMAKE_{C,CXX}_COMPILER**:STRING + Specify the C and C++ compilers to use. If you have multiple + compilers installed, CMake might not default to the one you wish to + use. + +.. _Frequently Used LLVM-related variables: + +Frequently Used LLVM-related variables +-------------------------------------- + +The default configuration may not match your requirements. Here are +LLVM variables that are frequently used to control that. The full +description is in `LLVM-related variables`_ below. + +**LLVM_ENABLE_PROJECTS**:STRING + Control which projects are enabled. For example you may want to work on clang + or lldb by specifying ``-DLLVM_ENABLE_PROJECTS="clang;lldb"``. **LLVM_LIBDIR_SUFFIX**:STRING Extra suffix to append to the directory where libraries are to be installed. On a 64-bit architecture, one could use ``-DLLVM_LIBDIR_SUFFIX=64`` to install libraries to ``/usr/lib64``. +**LLVM_PARALLEL_{COMPILE,LINK}_JOBS**:STRING + Building the llvm toolchain can use a lot of resources, particularly + linking. These options, when you use the Ninja generator, allow you + to restrict the parallelism. For example, to avoid OOMs or going + into swap, permit only one link job per 15GB of RAM available on a + 32GB machine, specify ``-G Ninja -DLLVM_PARALLEL_LINK_JOBS=2``. + +**LLVM_TARGETS_TO_BUILD**:STRING + Control which targets are enabled. For example you may only need to enable + your native target with, for example, ``-DLLVM_TARGETS_TO_BUILD=X86``. + +**LLVM_USE_LINKER**:STRING + Override the system's default linker. For instance use ``lld`` with + ``-DLLVM_USE_LINKER=lld``. + Rarely-used CMake variables --------------------------- Here are some of the CMake variables that are rarely used, along with a brief -explanation and LLVM-specific notes. For full documentation, consult the CMake +explanation and LLVM-related notes. For full documentation, consult the CMake manual, or execute ``cmake --help-variable VARIABLE_NAME``. **CMAKE_CXX_STANDARD**:STRING Sets the C++ standard to conform to when building LLVM. Possible values are 14, 17, 20. LLVM Requires C++ 14 or higher. This defaults to 14. -.. _LLVM-specific variables: +.. _LLVM-related variables: -LLVM-specific variables +LLVM-related variables ----------------------- +These variables provide fine control over the build of LLVM and +enabled sub-projects. Nearly all of these variable names begin with +``LLVM_``. + **BUILD_SHARED_LIBS**:BOOL Flag indicating if each LLVM component (e.g. Support) is built as a shared library (ON) or as a static library (OFF). Its default value is OFF. On @@ -733,14 +774,14 @@ For more information about testing, see the :doc:`TestingGuide`. Cross compiling =============== -See `this wiki page `_ for +See `this wiki page `_ for generic instructions on how to cross-compile with CMake. It goes into detailed explanations and may seem daunting, but it is not. On the wiki page there are -several examples including toolchain files. Go directly to `this section -`_ +several examples including toolchain files. Go directly to the +``Information how to set up various cross compiling toolchains`` section for a quick solution. -Also see the `LLVM-specific variables`_ section for variables used when +Also see the `LLVM-related variables`_ section for variables used when cross-compiling. Embedding LLVM in your project diff --git a/llvm/docs/CommandGuide/lit.rst b/llvm/docs/CommandGuide/lit.rst index dc2b57cda8a4e..9c48d3abb8df7 100644 --- a/llvm/docs/CommandGuide/lit.rst +++ b/llvm/docs/CommandGuide/lit.rst @@ -263,6 +263,15 @@ The timing data is stored in the `test_exec_root` in a file named LIT_XFAIL="affinity/kmp-hw-subset.c;libomptarget :: x86_64-pc-linux-gnu :: offloading/memory_manager.cpp" +.. option:: --xfail-not=LIST + + Do not treat the specified tests as ``XFAIL``. The environment variable + ``LIT_XFAIL_NOT`` can also be used in place of this option. The syntax is the + same as for :option:`--xfail` and ``LIT_XFAIL``. :option:`--xfail-not` and + ``LIT_XFAIL_NOT`` always override all other ``XFAIL`` specifications, + including an :option:`--xfail` appearing later on the command line. The + primary purpose is to suppress an ``XPASS`` result without modifying a test + case that uses the ``XFAIL`` directive. ADDITIONAL OPTIONS ------------------ diff --git a/llvm/docs/CommandGuide/llvm-cov.rst b/llvm/docs/CommandGuide/llvm-cov.rst index 98885d4453954..5f4c6e4fb25c7 100644 --- a/llvm/docs/CommandGuide/llvm-cov.rst +++ b/llvm/docs/CommandGuide/llvm-cov.rst @@ -310,6 +310,12 @@ OPTIONS specified). When N=0, llvm-cov auto-detects an appropriate number of threads to use. This is the default. +.. option:: -compilation-dir= + + Directory used as a base for relative coverage mapping paths. Only applicable + when binaries have been compiled with one of `-fcoverage-prefix-map` + `-fcoverage-compilation-dir`, or `-ffile-compilation-dir`. + .. option:: -line-coverage-gt= Show code coverage only for functions with line coverage greater than the @@ -399,6 +405,12 @@ OPTIONS Skip source code files with file paths that match the given regular expression. +.. option:: -compilation-dir= + + Directory used as a base for relative coverage mapping paths. Only applicable + when binaries have been compiled with one of `-fcoverage-prefix-map` + `-fcoverage-compilation-dir`, or `-ffile-compilation-dir`. + .. program:: llvm-cov export .. _llvm-cov-export: @@ -467,3 +479,9 @@ OPTIONS Use N threads to export coverage data. When N=0, llvm-cov auto-detects an appropriate number of threads to use. This is the default. + +.. option:: -compilation-dir= + + Directory used as a base for relative coverage mapping paths. Only applicable + when binaries have been compiled with one of `-fcoverage-prefix-map` + `-fcoverage-compilation-dir`, or `-ffile-compilation-dir`. diff --git a/llvm/docs/CommandGuide/llvm-readelf.rst b/llvm/docs/CommandGuide/llvm-readelf.rst index cf4222f00c549..59a9da60e53da 100644 --- a/llvm/docs/CommandGuide/llvm-readelf.rst +++ b/llvm/docs/CommandGuide/llvm-readelf.rst @@ -22,7 +22,8 @@ OPTIONS .. option:: --all - Equivalent to specifying all the main display options. + Equivalent to specifying all the main display options relevant to the file + format. .. option:: --addrsig @@ -37,10 +38,6 @@ OPTIONS Display the contents of the basic block address map section(s), which contain the address of each function, along with the relative offset of each basic block. -.. option:: --color - - Use colors in the output for warnings and errors. - .. option:: --demangle, -C Display demangled symbol names in the output. @@ -61,7 +58,7 @@ OPTIONS Display the callgraph profile section. -.. option:: --elf-hash-histogram, --histogram, -I +.. option:: --histogram, -I Display a bucket list histogram for dynamic symbol hash tables. @@ -75,7 +72,7 @@ OPTIONS ``GNU``. ``LLVM`` output is an expanded and structured format, whilst ``GNU`` (the default) output mimics the equivalent GNU :program:`readelf` output. -.. option:: --elf-section-groups, --section-groups, -g +.. option:: --section-groups, -g Display section groups. @@ -84,7 +81,7 @@ OPTIONS When used with :option:`--relocations`, display each relocation in an expanded multi-line format. -.. option:: --file-headers, -h +.. option:: --file-header, -h Display file headers. @@ -102,17 +99,13 @@ OPTIONS .. option:: --headers, -e - Equivalent to setting: :option:`--file-headers`, :option:`--program-headers`, + Equivalent to setting: :option:`--file-header`, :option:`--program-headers`, and :option:`--sections`. .. option:: --help Display a summary of command line options. -.. option:: --help-list - - Display an uncategorized summary of command line options. - .. option:: --hex-dump=, -x Display the specified section(s) as hexadecimal bytes. ``section`` may be a diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst index 8c4546bbcefda..2fb639fc30092 100644 --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -56,32 +56,24 @@ file formats. Display the address-significance table. -.. option:: --color - - Use colors in the output for warnings and errors. - .. option:: --expand-relocs - When used with :option:`--relocations`, display each relocation in an expanded + When used with :option:`--relocs`, display each relocation in an expanded multi-line format. -.. option:: --file-headers, -h +.. option:: --file-header, -h Display file headers. .. option:: --headers, -e - Equivalent to setting: :option:`--file-headers`, :option:`--program-headers`, + Equivalent to setting: :option:`--file-header`, :option:`--program-headers`, and :option:`--sections`. .. option:: --help Display a summary of command line options. -.. option:: --help-list - - Display an uncategorized summary of command line options. - .. option:: --hex-dump=, -x Display the specified section(s) as hexadecimal bytes. ``section`` may be a @@ -181,7 +173,7 @@ The following options are implemented only for the ELF file format. Display the callgraph profile section. -.. option:: --elf-hash-histogram, --histogram, -I +.. option:: --histogram, -I Display a bucket list histogram for dynamic symbol hash tables. @@ -195,7 +187,7 @@ The following options are implemented only for the ELF file format. ``GNU``. ``LLVM`` output (the default) is an expanded and structured format, whilst ``GNU`` output mimics the equivalent GNU :program:`readelf` output. -.. option:: --elf-section-groups, --section-groups, -g +.. option:: --section-groups, -g Display section groups. diff --git a/llvm/docs/CommandLine.rst b/llvm/docs/CommandLine.rst index e549d49bd90f5..fef7e39ad86d2 100644 --- a/llvm/docs/CommandLine.rst +++ b/llvm/docs/CommandLine.rst @@ -661,7 +661,7 @@ declared, the command line option ``-help-list`` becomes visible which will print the command line options as uncategorized list. Note that Options that are not explicitly categorized will be placed in the -``cl::GeneralCategory`` category. +``cl::getGeneralCategory()`` category. .. _Reference Guide: diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 6434b0d989064..7dd60be987d8e 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -601,11 +601,29 @@ Non-integral pointer types represent pointers that have an *unspecified* bitwise representation; that is, the integral representation may be target dependent or unstable (not backed by a fixed integer). -``inttoptr`` and ``ptrtoint`` instructions converting integers to non-integral -pointer types or vice versa are implementation defined, and subject to likely -future revision in semantics. Vector versions of said instructions are as well. -Users of non-integral-pointer types are advised not to design around current -semantics as they may very well change in the nearish future. +``inttoptr`` and ``ptrtoint`` instructions have the same semantics as for +integral (i.e. normal) pointers in that they convert integers to and from +corresponding pointer types, but there are additional implications to be +aware of. Because the bit-representation of a non-integral pointer may +not be stable, two identical casts of the same operand may or may not +return the same value. Said differently, the conversion to or from the +non-integral type depends on environmental state in an implementation +defined manner. + +If the frontend wishes to observe a *particular* value following a cast, the +generated IR must fence with the underlying environment in an implementation +defined manner. (In practice, this tends to require ``noinline`` routines for +such operations.) + +From the perspective of the optimizer, ``inttoptr`` and ``ptrtoint`` for +non-integral types are analogous to ones on integral types with one +key exception: the optimizer may not, in general, insert new dynamic +occurrences of such casts. If a new cast is inserted, the optimizer would +need to either ensure that a) all possible values are valid, or b) +appropriate fencing is inserted. Since the appropriate fencing is +implementation defined, the optimizer can't do the latter. The former is +challenging as many commonly expected properties, such as +``ptrtoint(v)-ptrtoint(v) == 0``, don't hold for non-integral types. .. _globalvars: @@ -1165,6 +1183,24 @@ Currently, only the following parameter attributes are defined: The sret type argument specifies the in memory type, which must be the same as the pointee type of the argument. +.. _attr_elementtype: + +``elementtype()`` + + The ``elementtype`` argument attribute can be used to specify a pointer + element type in a way that is compatible with `opaque pointers + `. + + The ``elementtype`` attribute by itself does not carry any specific + semantics. However, certain intrinsics may require this attribute to be + present and assign it particular semantics. This will be documented on + individual intrinsics. + + The attribute may only be applied to pointer typed arguments of intrinsic + calls. It cannot be applied to non-intrinsic calls, and cannot be applied + to parameters on function declarations. For non-opaque pointers, the type + passed to ``elementtype`` must match the pointer element type. + .. _attr_align: ``align `` or ``align()`` @@ -22519,6 +22555,10 @@ The ``base`` is the array base address. The ``dim`` is the array dimension. The ``base`` is a pointer if ``dim`` equals 0. The ``index`` is the last access index into the array or pointer. +The ``base`` argument must be annotated with an :ref:`elementtype +` attribute at the call-site. This attribute specifies the +getelementptr element type. + Semantics: """""""""" @@ -22584,6 +22624,10 @@ Arguments: The ``base`` is the structure base address. The ``gep_index`` is the struct member index based on IR structures. The ``di_index`` is the struct member index based on debuginfo. +The ``base`` argument must be annotated with an :ref:`elementtype +` attribute at the call-site. This attribute specifies the +getelementptr element type. + Semantics: """""""""" diff --git a/llvm/docs/OpaquePointers.rst b/llvm/docs/OpaquePointers.rst index 64cfb6d3b2402..3c179a8272d27 100644 --- a/llvm/docs/OpaquePointers.rst +++ b/llvm/docs/OpaquePointers.rst @@ -137,10 +137,6 @@ particular order: * This is mostly Clang, see ``clang::CodeGen::Address::getElementType()`` -* Figure out how to name overloaded intrinsics with pointer parameters - - * See ``getMangledTypeStr()`` - * Add option to internally treat all pointer types opaque pointers and see what breaks, starting with LLVM tests, then run Clang over large codebases diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst index 652eccb33f077..ff560eb7eee37 100644 --- a/llvm/docs/SourceLevelDebugging.rst +++ b/llvm/docs/SourceLevelDebugging.rst @@ -770,7 +770,9 @@ VirtRegRewriter pass re-inserts DBG_VALUE instructions in their original positions, translating virtual register references into their physical machine locations. To avoid encoding incorrect variable locations, in this pass any DBG_VALUE of a virtual register that is not live, is replaced by -the undefined location. +the undefined location. The LiveDebugVariables may insert redundant DBG_VALUEs +because of virtual register rewriting. These will be subsequently removed by +the RemoveRedundantDebugValues pass. LiveDebugValues expansion of variable locations ----------------------------------------------- diff --git a/llvm/docs/tutorial/BuildingAJIT2.rst b/llvm/docs/tutorial/BuildingAJIT2.rst index ee4e6916ecbc6..48478f3c0cece 100644 --- a/llvm/docs/tutorial/BuildingAJIT2.rst +++ b/llvm/docs/tutorial/BuildingAJIT2.rst @@ -224,9 +224,9 @@ Most layers that derived from IRLayer can rely on this default implementation of the ``add`` method. These two operations, ``add`` and ``emit``, together constitute the layer -concept: A layer is a way to wrap a portion of a compiler pipeline (in this case -the "opt" phase of an LLVM compiler) whose API is is opaque to ORC in an -interface that allows ORC to invoke it when needed. The add method takes an +concept: A layer is a way to wrap a part of a compiler pipeline (in this case +the "opt" phase of an LLVM compiler) whose API is opaque to ORC with an +interface that ORC can call as needed. The add method takes an module in some input program representation (in this case an LLVM IR module) and stores it in the target JITDylib, arranging for it to be passed back to the Layer's emit method when any symbol defined by that module is requested. Layers diff --git a/llvm/examples/BrainF/BrainF.cpp b/llvm/examples/BrainF/BrainF.cpp index ba9184df72ad1..11a752b1a5474 100644 --- a/llvm/examples/BrainF/BrainF.cpp +++ b/llvm/examples/BrainF/BrainF.cpp @@ -114,14 +114,13 @@ void BrainF::header(LLVMContext& C) { //%arrmax = getelementptr i8 *%arr, i32 %d if (comflag & flag_arraybounds) { - ptr_arrmax = builder-> - CreateGEP(ptr_arr, ConstantInt::get(C, APInt(32, memtotal)), "arrmax"); + ptr_arrmax = builder->CreateGEP( + Int8Ty, ptr_arr, ConstantInt::get(C, APInt(32, memtotal)), "arrmax"); } //%head.%d = getelementptr i8 *%arr, i32 %d - curhead = builder->CreateGEP(ptr_arr, - ConstantInt::get(C, APInt(32, memtotal/2)), - headreg); + curhead = builder->CreateGEP( + Int8Ty, ptr_arr, ConstantInt::get(C, APInt(32, memtotal / 2)), headreg); //Function footer @@ -195,6 +194,7 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, char c; int loop; int direction; + Type *Int8Ty = IntegerType::getInt8Ty(C); while(cursym != SYM_EOF && cursym != SYM_ENDLOOP) { // Write out commands @@ -223,8 +223,7 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, case SYM_WRITE: { //%tape.%d = load i8 *%head.%d - LoadInst *tape_0 = - builder->CreateLoad(IntegerType::getInt8Ty(C), curhead, tapereg); + LoadInst *tape_0 = builder->CreateLoad(Int8Ty, curhead, tapereg); //%tape.%d = sext i8 %tape.%d to i32 Value *tape_1 = builder-> @@ -244,9 +243,9 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, case SYM_MOVE: { //%head.%d = getelementptr i8 *%head.%d, i32 %d - curhead = builder-> - CreateGEP(curhead, ConstantInt::get(C, APInt(32, curvalue)), - headreg); + curhead = builder->CreateGEP(Int8Ty, curhead, + ConstantInt::get(C, APInt(32, curvalue)), + headreg); //Error block for array out of bounds if (comflag & flag_arraybounds) @@ -276,8 +275,7 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, case SYM_CHANGE: { //%tape.%d = load i8 *%head.%d - LoadInst *tape_0 = - builder->CreateLoad(IntegerType::getInt8Ty(C), curhead, tapereg); + LoadInst *tape_0 = builder->CreateLoad(Int8Ty, curhead, tapereg); //%tape.%d = add i8 %tape.%d, %d Value *tape_1 = builder-> @@ -300,9 +298,8 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, builder->SetInsertPoint(bb_1); // Make part of PHI instruction now, wait until end of loop to finish - PHINode *phi_0 = - PHINode::Create(PointerType::getUnqual(IntegerType::getInt8Ty(C)), - 2, headreg, testbb); + PHINode *phi_0 = PHINode::Create(PointerType::getUnqual(Int8Ty), 2, + headreg, testbb); phi_0->addIncoming(curhead, bb_0); curhead = phi_0; @@ -441,8 +438,7 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, Value *head_0 = phi; //%tape.%d = load i8 *%head.%d - LoadInst *tape_0 = new LoadInst(IntegerType::getInt8Ty(C), head_0, - tapereg, testbb); + LoadInst *tape_0 = new LoadInst(Int8Ty, head_0, tapereg, testbb); //%test.%d = icmp eq i8 %tape.%d, 0 ICmpInst *test_0 = new ICmpInst(*testbb, ICmpInst::ICMP_EQ, tape_0, @@ -456,9 +452,8 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, builder->SetInsertPoint(bb_0); //%head.%d = phi i8 *[%head.%d, %main.%d] - PHINode *phi_1 = builder-> - CreatePHI(PointerType::getUnqual(IntegerType::getInt8Ty(C)), 1, - headreg); + PHINode *phi_1 = + builder->CreatePHI(PointerType::getUnqual(Int8Ty), 1, headreg); phi_1->addIncoming(head_0, testbb); curhead = phi_1; } diff --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt index 59311f8fbf1c0..d6fa7423df19a 100644 --- a/llvm/examples/OrcV2Examples/CMakeLists.txt +++ b/llvm/examples/OrcV2Examples/CMakeLists.txt @@ -15,6 +15,7 @@ add_subdirectory(OrcV2CBindingsIRTransforms) add_subdirectory(OrcV2CBindingsReflectProcessSymbols) add_subdirectory(OrcV2CBindingsRemovableCode) add_subdirectory(OrcV2CBindingsLazy) +add_subdirectory(OrcV2CBindingsVeryLazy) if(CMAKE_HOST_UNIX) add_subdirectory(LLJITWithRemoteDebugging) diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt new file mode 100644 index 0000000000000..0bc9610b1ad7e --- /dev/null +++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt @@ -0,0 +1,15 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + IRReader + JITLink + MC + OrcJIT + Support + Target + nativecodegen + ) + +add_llvm_example(OrcV2CBindingsVeryLazy + OrcV2CBindingsVeryLazy.c + ) diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c new file mode 100644 index 0000000000000..93d36a40b12f3 --- /dev/null +++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/OrcV2CBindingsVeryLazy.c @@ -0,0 +1,301 @@ +//===-------- BasicOrcV2CBindings.c - Basic OrcV2 C Bindings Demo ---------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Core.h" +#include "llvm-c/Error.h" +#include "llvm-c/IRReader.h" +#include "llvm-c/Initialization.h" +#include "llvm-c/LLJIT.h" +#include "llvm-c/Support.h" +#include "llvm-c/Target.h" + +#include +#include +#include + +int handleError(LLVMErrorRef Err) { + char *ErrMsg = LLVMGetErrorMessage(Err); + fprintf(stderr, "Error: %s\n", ErrMsg); + LLVMDisposeErrorMessage(ErrMsg); + return 1; +} + +// Example IR modules. +// +// Note that in the conditionally compiled modules, FooMod and BarMod, functions +// have been given an _body suffix. This is to ensure that their names do not +// clash with their lazy-reexports. +// For clients who do not wish to rename function bodies (e.g. because they want +// to re-use cached objects between static and JIT compiles) techniques exist to +// avoid renaming. See the lazy-reexports section of the ORCv2 design doc. + +const char FooMod[] = " define i32 @foo_body() { \n" + " entry: \n" + " ret i32 1 \n" + " } \n"; + +const char BarMod[] = " define i32 @bar_body() { \n" + " entry: \n" + " ret i32 2 \n" + " } \n"; + +const char MainMod[] = + " define i32 @entry(i32 %argc) { \n" + " entry: \n" + " %and = and i32 %argc, 1 \n" + " %tobool = icmp eq i32 %and, 0 \n" + " br i1 %tobool, label %if.end, label %if.then \n" + " \n" + " if.then: \n" + " %call = tail call i32 @foo() \n" + " br label %return \n" + " \n" + " if.end: \n" + " %call1 = tail call i32 @bar() \n" + " br label %return \n" + " \n" + " return: \n" + " %retval.0 = phi i32 [ %call, %if.then ], [ %call1, %if.end ] \n" + " ret i32 %retval.0 \n" + " } \n" + " \n" + " declare i32 @foo() \n" + " declare i32 @bar() \n"; + +LLVMErrorRef applyDataLayout(void *Ctx, LLVMModuleRef M) { + LLVMSetDataLayout(M, LLVMOrcLLJITGetDataLayoutStr((LLVMOrcLLJITRef)Ctx)); + return LLVMErrorSuccess; +} + +LLVMErrorRef parseExampleModule(const char *Source, size_t Len, + const char *Name, + LLVMOrcThreadSafeModuleRef *TSM) { + // Create a new ThreadSafeContext and underlying LLVMContext. + LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext(); + + // Get a reference to the underlying LLVMContext. + LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx); + + // Wrap Source in a MemoryBuffer + LLVMMemoryBufferRef MB = + LLVMCreateMemoryBufferWithMemoryRange(Source, Len, Name, 1); + + // Parse the LLVM module. + LLVMModuleRef M; + char *ErrMsg; + if (LLVMParseIRInContext(Ctx, MB, &M, &ErrMsg)) { + LLVMErrorRef Err = LLVMCreateStringError(ErrMsg); + LLVMDisposeMessage(ErrMsg); + return Err; + } + + // Our module is now complete. Wrap it and our ThreadSafeContext in a + // ThreadSafeModule. + *TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx); + + // Dispose of our local ThreadSafeContext value. The underlying LLVMContext + // will be kept alive by our ThreadSafeModule, TSM. + LLVMOrcDisposeThreadSafeContext(TSCtx); + + return LLVMErrorSuccess; +} + +void Destroy(void *Ctx) {} + +void Materialize(void *Ctx, LLVMOrcMaterializationResponsibilityRef MR) { + int MainResult = 0; + + size_t NumSymbols; + LLVMOrcSymbolStringPoolEntryRef *Symbols = + LLVMOrcMaterializationResponsibilityGetRequestedSymbols(MR, &NumSymbols); + + assert(NumSymbols == 1); + + LLVMOrcLLJITRef J = (LLVMOrcLLJITRef)Ctx; + LLVMOrcSymbolStringPoolEntryRef Sym = Symbols[0]; + + LLVMOrcThreadSafeModuleRef TSM = 0; + LLVMErrorRef Err; + + LLVMOrcSymbolStringPoolEntryRef FooBody = + LLVMOrcLLJITMangleAndIntern(J, "foo_body"); + LLVMOrcSymbolStringPoolEntryRef BarBody = + LLVMOrcLLJITMangleAndIntern(J, "bar_body"); + + if (Sym == FooBody) { + if ((Err = parseExampleModule(FooMod, strlen(FooMod), "foo-mod", &TSM))) { + MainResult = handleError(Err); + goto cleanup; + } + } else if (Sym == BarBody) { + if ((Err = parseExampleModule(BarMod, strlen(BarMod), "bar-mod", &TSM))) { + MainResult = handleError(Err); + goto cleanup; + } + } else { + MainResult = 1; + goto cleanup; + } + assert(TSM); + + if ((Err = LLVMOrcThreadSafeModuleWithModuleDo(TSM, &applyDataLayout, Ctx))) { + MainResult = handleError(Err); + goto cleanup; + } + +cleanup: + LLVMOrcReleaseSymbolStringPoolEntry(BarBody); + LLVMOrcReleaseSymbolStringPoolEntry(FooBody); + LLVMOrcDisposeSymbols(Symbols); + if (MainResult == 1) { + LLVMOrcMaterializationResponsibilityFailMaterialization(MR); + LLVMOrcDisposeMaterializationResponsibility(MR); + } else { + LLVMOrcIRTransformLayerRef IRLayer = LLVMOrcLLJITGetIRTransformLayer(J); + LLVMOrcIRTransformLayerEmit(IRLayer, MR, TSM); + } + return; +} + +int main(int argc, char *argv[]) { + + int MainResult = 0; + + // Parse command line arguments and initialize LLVM Core. + LLVMParseCommandLineOptions(argc, (const char **)argv, ""); + LLVMInitializeCore(LLVMGetGlobalPassRegistry()); + + // Initialize native target codegen and asm printer. + LLVMInitializeNativeTarget(); + LLVMInitializeNativeAsmPrinter(); + + // Set up a JIT instance. + LLVMOrcLLJITRef J; + const char *TargetTriple; + { + LLVMErrorRef Err; + if ((Err = LLVMOrcCreateLLJIT(&J, 0))) { + MainResult = handleError(Err); + goto llvm_shutdown; + } + TargetTriple = LLVMOrcLLJITGetTripleString(J); + } + + // Add our main module to the JIT. + { + LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J); + LLVMErrorRef Err; + + LLVMOrcThreadSafeModuleRef MainTSM; + if ((Err = parseExampleModule(MainMod, strlen(MainMod), "main-mod", + &MainTSM))) { + MainResult = handleError(Err); + goto jit_cleanup; + } + + if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, MainTSM))) { + LLVMOrcDisposeThreadSafeModule(MainTSM); + MainResult = handleError(Err); + goto jit_cleanup; + } + } + + LLVMJITSymbolFlags Flags = { + LLVMJITSymbolGenericFlagsExported | LLVMJITSymbolGenericFlagsCallable, 0}; + LLVMOrcCSymbolFlagsMapPair FooSym = { + LLVMOrcLLJITMangleAndIntern(J, "foo_body"), Flags}; + LLVMOrcCSymbolFlagsMapPair BarSym = { + LLVMOrcLLJITMangleAndIntern(J, "bar_body"), Flags}; + + // add custom MaterializationUnit + { + LLVMOrcMaterializationUnitRef FooMU = + LLVMOrcCreateCustomMaterializationUnit("FooMU", J, &FooSym, 1, NULL, + &Materialize, NULL, &Destroy); + + LLVMOrcMaterializationUnitRef BarMU = + LLVMOrcCreateCustomMaterializationUnit("BarMU", J, &BarSym, 1, NULL, + &Materialize, NULL, &Destroy); + + LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J); + LLVMOrcJITDylibDefine(MainJD, FooMU); + LLVMOrcJITDylibDefine(MainJD, BarMU); + } + + // add lazy reexports + LLVMOrcIndirectStubsManagerRef ISM = + LLVMOrcCreateLocalIndirectStubsManager(TargetTriple); + + LLVMOrcLazyCallThroughManagerRef LCTM; + { + LLVMErrorRef Err; + LLVMOrcExecutionSessionRef ES = LLVMOrcLLJITGetExecutionSession(J); + if ((Err = LLVMOrcCreateLocalLazyCallThroughManager(TargetTriple, ES, 0, + &LCTM))) { + LLVMOrcDisposeIndirectStubsManager(ISM); + MainResult = handleError(Err); + goto jit_cleanup; + } + } + + LLVMOrcCSymbolAliasMapPair ReExports[2] = { + {LLVMOrcLLJITMangleAndIntern(J, "foo"), + {LLVMOrcLLJITMangleAndIntern(J, "foo_body"), Flags}}, + {LLVMOrcLLJITMangleAndIntern(J, "bar"), + {LLVMOrcLLJITMangleAndIntern(J, "bar_body"), Flags}}, + }; + + { + LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J); + LLVMOrcMaterializationUnitRef MU = + LLVMOrcLazyReexports(LCTM, ISM, MainJD, ReExports, 2); + LLVMOrcJITDylibDefine(MainJD, MU); + } + + // Look up the address of our demo entry point. + LLVMOrcJITTargetAddress EntryAddr; + { + LLVMErrorRef Err; + if ((Err = LLVMOrcLLJITLookup(J, &EntryAddr, "entry"))) { + MainResult = handleError(Err); + goto cleanup; + } + } + + // If we made it here then everything succeeded. Execute our JIT'd code. + int32_t (*Entry)(int32_t) = (int32_t(*)(int32_t))EntryAddr; + int32_t Result = Entry(argc); + + printf("--- Result ---\n"); + printf("entry(%i) = %i\n", argc, Result); + +cleanup : { + LLVMOrcDisposeIndirectStubsManager(ISM); + LLVMOrcDisposeLazyCallThroughManager(LCTM); +} + +jit_cleanup: + // Destroy our JIT instance. This will clean up any memory that the JIT has + // taken ownership of. This operation is non-trivial (e.g. it may need to + // JIT static destructors) and may also fail. In that case we want to render + // the error to stderr, but not overwrite any existing return value. + { + LLVMErrorRef Err; + if ((Err = LLVMOrcDisposeLLJIT(J))) { + int NewFailureResult = handleError(Err); + if (MainResult == 0) + MainResult = NewFailureResult; + } + } + +llvm_shutdown: + // Shut down LLVM. + LLVMShutdown(); + + return MainResult; +} diff --git a/llvm/include/llvm-c/LLJIT.h b/llvm/include/llvm-c/LLJIT.h index bd98cfbab839c..f689ca0f1cf0b 100644 --- a/llvm/include/llvm-c/LLJIT.h +++ b/llvm/include/llvm-c/LLJIT.h @@ -227,6 +227,14 @@ LLVMOrcLLJITGetObjTransformLayer(LLVMOrcLLJITRef J); */ LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J); +/** + * Get the LLJIT instance's default data layout string. + * + * This string is owned by the LLJIT instance and does not need to be freed + * by the caller. + */ +const char *LLVMOrcLLJITGetDataLayoutStr(LLVMOrcLLJITRef J); + LLVM_C_EXTERN_C_END #endif /* LLVM_C_LLJIT_H */ diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h index 62688d2675d5a..1790afbcecc77 100644 --- a/llvm/include/llvm-c/Orc.h +++ b/llvm/include/llvm-c/Orc.h @@ -145,6 +145,34 @@ typedef struct { */ typedef LLVMOrcCSymbolAliasMapPair *LLVMOrcCSymbolAliasMapPairs; +/** + * A reference to an orc::JITDylib instance. + */ +typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef; + +/** + * Represents a list of LLVMOrcSymbolStringPoolEntryRef and the associated + * length. + */ +typedef struct { + LLVMOrcSymbolStringPoolEntryRef *Symbols; + size_t Length; +} LLVMOrcCSymbolsList; + +/** + * Represents a pair of a JITDylib and LLVMOrcCSymbolsList. + */ +typedef struct { + LLVMOrcJITDylibRef JD; + LLVMOrcCSymbolsList Names; +} LLVMOrcCDependenceMapPair; + +/** + * Represents a list of (JITDylibRef, (LLVMOrcSymbolStringPoolEntryRef*, + * size_t)) pairs that can be used to construct a SymbolDependenceMap. + */ +typedef LLVMOrcCDependenceMapPair *LLVMOrcCDependenceMapPairs; + /** * Lookup kind. This can be used by definition generators when deciding whether * to produce a definition for a requested symbol. @@ -210,11 +238,6 @@ typedef struct LLVMOrcOpaqueMaterializationUnit *LLVMOrcMaterializationUnitRef; typedef struct LLVMOrcOpaqueMaterializationResponsibility *LLVMOrcMaterializationResponsibilityRef; -/** - * A reference to an orc::JITDylib instance. - */ -typedef struct LLVMOrcOpaqueJITDylib *LLVMOrcJITDylibRef; - /** * A MaterializationUnit materialize callback. * @@ -597,6 +620,199 @@ LLVMOrcMaterializationUnitRef LLVMOrcLazyReexports( size_t NumPairs); // TODO: ImplSymbolMad SrcJDLoc +/** + * Disposes of the passed MaterializationResponsibility object. + * + * This should only be done after the symbols covered by the object have either + * been resolved and emitted (via + * LLVMOrcMaterializationResponsibilityNotifyResolved and + * LLVMOrcMaterializationResponsibilityNotifyEmitted) or failed (via + * LLVMOrcMaterializationResponsibilityFailMaterialization). + */ +void LLVMOrcDisposeMaterializationResponsibility( + LLVMOrcMaterializationResponsibilityRef MR); + +/** + * Returns the target JITDylib that these symbols are being materialized into. + */ +LLVMOrcJITDylibRef LLVMOrcMaterializationResponsibilityGetTargetDylib( + LLVMOrcMaterializationResponsibilityRef MR); + +/** + * Returns the ExecutionSession for this MaterializationResponsibility. + */ +LLVMOrcExecutionSessionRef +LLVMOrcMaterializationResponsibilityGetExecutionSession( + LLVMOrcMaterializationResponsibilityRef MR); + +/** + * Returns the symbol flags map for this responsibility instance. + * + * The length of the array is returned in NumPairs and the caller is responsible + * for the returned memory and needs to call LLVMOrcDisposeCSymbolFlagsMap. + * + * To use the returned symbols beyond the livetime of the + * MaterializationResponsibility requires the caller to retain the symbols + * explicitly. + */ +LLVMOrcCSymbolFlagsMapPairs LLVMOrcMaterializationResponsibilityGetSymbols( + LLVMOrcMaterializationResponsibilityRef MR, size_t *NumPairs); + +/** + * Disposes of the passed LLVMOrcCSymbolFlagsMap. + * + * Does not release the entries themselves. + */ +void LLVMOrcDisposeCSymbolFlagsMap(LLVMOrcCSymbolFlagsMapPairs Pairs); + +/** + * Returns the initialization pseudo-symbol, if any. This symbol will also + * be present in the SymbolFlagsMap for this MaterializationResponsibility + * object. + * + * The returned symbol is not retained over any mutating operation of the + * MaterializationResponsbility or beyond the lifetime thereof. + */ +LLVMOrcSymbolStringPoolEntryRef +LLVMOrcMaterializationResponsibilityGetInitializerSymbol( + LLVMOrcMaterializationResponsibilityRef MR); + +/** + * Returns the names of any symbols covered by this + * MaterializationResponsibility object that have queries pending. This + * information can be used to return responsibility for unrequested symbols + * back to the JITDylib via the delegate method. + */ +LLVMOrcSymbolStringPoolEntryRef * +LLVMOrcMaterializationResponsibilityGetRequestedSymbols( + LLVMOrcMaterializationResponsibilityRef MR, size_t *NumSymbols); + +/** + * Disposes of the passed LLVMOrcSymbolStringPoolEntryRef* . + * + * Does not release the symbols themselves. + */ +void LLVMOrcDisposeSymbols(LLVMOrcSymbolStringPoolEntryRef *Symbols); + +/* + * Notifies the target JITDylib that the given symbols have been resolved. + * This will update the given symbols' addresses in the JITDylib, and notify + * any pending queries on the given symbols of their resolution. The given + * symbols must be ones covered by this MaterializationResponsibility + * instance. Individual calls to this method may resolve a subset of the + * symbols, but all symbols must have been resolved prior to calling emit. + * + * This method will return an error if any symbols being resolved have been + * moved to the error state due to the failure of a dependency. If this + * method returns an error then clients should log it and call + * LLVMOrcMaterializationResponsibilityFailMaterialization. If no dependencies + * have been registered for the symbols covered by this + * MaterializationResponsibiility then this method is guaranteed to return + * LLVMErrorSuccess. + */ +LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyResolved( + LLVMOrcMaterializationResponsibilityRef MR, LLVMOrcCSymbolMapPairs Symbols, + size_t NumPairs); + +/** + * Notifies the target JITDylib (and any pending queries on that JITDylib) + * that all symbols covered by this MaterializationResponsibility instance + * have been emitted. + * + * This method will return an error if any symbols being resolved have been + * moved to the error state due to the failure of a dependency. If this + * method returns an error then clients should log it and call + * LLVMOrcMaterializationResponsibilityFailMaterialization. + * If no dependencies have been registered for the symbols covered by this + * MaterializationResponsibiility then this method is guaranteed to return + * LLVMErrorSuccess. + */ +LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyEmitted( + LLVMOrcMaterializationResponsibilityRef MR); + +/** + * Attempt to claim responsibility for new definitions. This method can be + * used to claim responsibility for symbols that are added to a + * materialization unit during the compilation process (e.g. literal pool + * symbols). Symbol linkage rules are the same as for symbols that are + * defined up front: duplicate strong definitions will result in errors. + * Duplicate weak definitions will be discarded (in which case they will + * not be added to this responsibility instance). + * + * This method can be used by materialization units that want to add + * additional symbols at materialization time (e.g. stubs, compile + * callbacks, metadata) + */ +LLVMErrorRef LLVMOrcMaterializationResponsibilityDefineMaterializing( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcCSymbolFlagsMapPairs Pairs, size_t NumPairs); + +/** + * Notify all not-yet-emitted covered by this MaterializationResponsibility + * instance that an error has occurred. + * This will remove all symbols covered by this MaterializationResponsibilty + * from the target JITDylib, and send an error to any queries waiting on + * these symbols. + */ +void LLVMOrcMaterializationResponsibilityFailMaterialization( + LLVMOrcMaterializationResponsibilityRef MR); + +/** + * Transfers responsibility to the given MaterializationUnit for all + * symbols defined by that MaterializationUnit. This allows + * materializers to break up work based on run-time information (e.g. + * by introspecting which symbols have actually been looked up and + * materializing only those). + */ +LLVMErrorRef LLVMOrcMaterializationResponsibilityReplace( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcMaterializationUnitRef MU); + +/** + * Delegates responsibility for the given symbols to the returned + * materialization responsibility. Useful for breaking up work between + * threads, or different kinds of materialization processes. + * + * The caller retains responsibility of the the passed + * MaterializationResponsibility. + */ +LLVMErrorRef LLVMOrcMaterializationResponsibilityDelegate( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcSymbolStringPoolEntryRef *Symbols, size_t NumSymbols, + LLVMOrcMaterializationResponsibilityRef *Result); + +/** + * Adds dependencies to a symbol that the MaterializationResponsibility is + * responsible for. + * + * This function takes ownership of Dependencies struct. The Names + * array have been retained for this function. This allows the following + * pattern... + * + * LLVMOrcSymbolStringPoolEntryRef Names[] = {...}; + * LLVMOrcCDependenceMapPair Dependence = {JD, {Names, sizeof(Names)}} + * LLVMOrcMaterializationResponsibilityAddDependencies(JD, Name, &Dependence, + * 1); + * + * ... without requiring cleanup of the elements of the Names array afterwards. + * + * The client is still responsible for deleting the Dependencies.Names array + * itself. + */ +void LLVMOrcMaterializationResponsibilityAddDependencies( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcSymbolStringPoolEntryRef Name, + LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs); + +/** + * Adds dependencies to all symbols that the MaterializationResponsibility is + * responsible for. See LLVMOrcMaterializationResponsibilityAddDependencies for + * notes about memory responsibility. + */ +void LLVMOrcMaterializationResponsibilityAddDependenciesForAll( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs); + /** * Create a "bare" JITDylib. * @@ -845,6 +1061,10 @@ void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer, */ void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer); +void LLVMOrcIRTransformLayerEmit(LLVMOrcIRTransformLayerRef IRTransformLayer, + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcThreadSafeModuleRef TSM); + /** * Set the transform function of the provided transform layer, passing through a * pointer to user provided context. diff --git a/llvm/include/llvm-c/Transforms/PassBuilder.h b/llvm/include/llvm-c/Transforms/PassBuilder.h index 4e32900142f2d..5635f10d68770 100644 --- a/llvm/include/llvm-c/Transforms/PassBuilder.h +++ b/llvm/include/llvm-c/Transforms/PassBuilder.h @@ -80,9 +80,6 @@ void LLVMPassBuilderOptionsSetLoopUnrolling(LLVMPassBuilderOptionsRef Options, void LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll( LLVMPassBuilderOptionsRef Options, LLVMBool ForgetAllSCEVInLoopUnroll); -void LLVMPassBuilderOptionsSetCoroutines(LLVMPassBuilderOptionsRef Options, - LLVMBool Coroutines); - void LLVMPassBuilderOptionsSetLicmMssaOptCap(LLVMPassBuilderOptionsRef Options, unsigned LicmMssaOptCap); diff --git a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 268377db9507a..f581b18bff176 100644 --- a/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -455,12 +455,6 @@ class BlockFrequencyInfoImplBase { bool addToDist(Distribution &Dist, const LoopData *OuterLoop, const BlockNode &Pred, const BlockNode &Succ, uint64_t Weight); - LoopData &getLoopPackage(const BlockNode &Head) { - assert(Head.Index < Working.size()); - assert(Working[Head.Index].isLoopHeader()); - return *Working[Head.Index].Loop; - } - /// Analyze irreducible SCCs. /// /// Separate irreducible SCCs from \c G, which is an explicit graph of \c diff --git a/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/llvm/include/llvm/Analysis/BranchProbabilityInfo.h index 6a286236a80e8..e2099eba0f65b 100644 --- a/llvm/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/llvm/include/llvm/Analysis/BranchProbabilityInfo.h @@ -168,12 +168,6 @@ class BranchProbabilityInfo { /// as having a relative probability >= 80%. bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const; - /// Retrieve the hot successor of a block if one exists. - /// - /// Given a basic block, look through its successors and if one exists for - /// which \see isEdgeHot would return true, return that successor block. - const BasicBlock *getHotSucc(const BasicBlock *BB) const; - /// Print an edge's probability. /// /// Retrieves an edge's probability similarly to \see getEdgeProbability, but diff --git a/llvm/include/llvm/Analysis/DivergenceAnalysis.h b/llvm/include/llvm/Analysis/DivergenceAnalysis.h index 0b36ef35aa591..6f759a81fdef6 100644 --- a/llvm/include/llvm/Analysis/DivergenceAnalysis.h +++ b/llvm/include/llvm/Analysis/DivergenceAnalysis.h @@ -112,13 +112,6 @@ class DivergenceAnalysisImpl { bool isTemporalDivergent(const BasicBlock &ObservingBlock, const Value &Val) const; - /// \brief Whether \p Block is join divergent - /// - /// (see markBlockJoinDivergent). - bool isJoinDivergent(const BasicBlock &Block) const { - return DivergentJoinBlocks.contains(&Block); - } - private: const Function &F; // If regionLoop != nullptr, analysis is only performed within \p RegionLoop. @@ -140,9 +133,6 @@ class DivergenceAnalysisImpl { // Set of known-uniform values. DenseSet UniformOverrides; - // Blocks with joining divergent control from different predecessors. - DenseSet DivergentJoinBlocks; // FIXME Deprecated - // Detected/marked divergent values. DenseSet DivergentValues; diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h index 9a560a14ca6fb..ae9c73fede961 100644 --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -643,6 +643,16 @@ class ScalarEvolution { SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, unsigned Depth = 0); + /// Compute ceil(N / D). N and D are treated as unsigned values. + /// + /// Since SCEV doesn't have native ceiling division, this generates a + /// SCEV expression of the following form: + /// + /// umin(N, 1) + floor((N - umin(N, 1)) / D) + /// + /// A denominator of zero or poison is handled the same way as getUDivExpr(). + const SCEV *getUDivCeilSCEV(const SCEV *N, const SCEV *D); + /// Return a SCEV corresponding to a conversion of the input value to the /// specified type. If the type must be extended, it is zero extended. const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty, @@ -2022,13 +2032,6 @@ class ScalarEvolution { Optional>> createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI); - /// Compute the backedge taken count knowing the interval difference, and - /// the stride for an inequality. Result takes the form: - /// (Delta + (Stride - 1)) udiv Stride. - /// Caller must ensure that this expression either does not overflow or - /// that the result is undefined if it does. - const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride); - /// Compute the maximum backedge count based on the range of values /// permitted by Start, End, and Stride. This is for loops of the form /// {Start, +, Stride} LT End. diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index b4b3736c36d57..208f0fcd3178e 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -1535,7 +1535,7 @@ class TargetTransformInfo::Concept { Type *Ty = nullptr) const = 0; virtual const char *getRegisterClassName(unsigned ClassID) const = 0; virtual TypeSize getRegisterBitWidth(RegisterKind K) const = 0; - virtual unsigned getMinVectorRegisterBitWidth() = 0; + virtual unsigned getMinVectorRegisterBitWidth() const = 0; virtual Optional getMaxVScale() const = 0; virtual bool shouldMaximizeVectorBandwidth() const = 0; virtual ElementCount getMinimumVF(unsigned ElemWidth, @@ -1982,7 +1982,7 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { TypeSize getRegisterBitWidth(RegisterKind K) const override { return Impl.getRegisterBitWidth(K); } - unsigned getMinVectorRegisterBitWidth() override { + unsigned getMinVectorRegisterBitWidth() const override { return Impl.getMinVectorRegisterBitWidth(); } Optional getMaxVScale() const override { diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index cba501f2bb6d1..fd9ffb58c0329 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -258,8 +258,15 @@ namespace llvm { return parseOptionalAddrSpace( AddrSpace, M->getDataLayout().getProgramAddressSpace()); }; - bool parseOptionalParamAttrs(AttrBuilder &B); - bool parseOptionalReturnAttrs(AttrBuilder &B); + bool parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, + bool InAttrGroup); + bool parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam); + bool parseOptionalParamAttrs(AttrBuilder &B) { + return parseOptionalParamOrReturnAttrs(B, true); + } + bool parseOptionalReturnAttrs(AttrBuilder &B) { + return parseOptionalParamOrReturnAttrs(B, false); + } bool parseOptionalLinkage(unsigned &Res, bool &HasLinkage, unsigned &Visibility, unsigned &DLLStorageClass, bool &DSOLocal); diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 7aed41e241aa3..50cad74d6974a 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -190,6 +190,7 @@ enum Kind { kw_convergent, kw_dereferenceable, kw_dereferenceable_or_null, + kw_elementtype, kw_inaccessiblememonly, kw_inaccessiblemem_or_argmemonly, kw_inlinehint, diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index b8135ffcd7a2a..8660d40ca039b 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -744,10 +744,11 @@ enum : unsigned { EF_AMDGPU_MACH_AMDGCN_RESERVED_0X41 = 0x041, EF_AMDGPU_MACH_AMDGCN_GFX1013 = 0x042, EF_AMDGPU_MACH_AMDGCN_RESERVED_0X43 = 0x043, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X44 = 0x044, // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, - EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_RESERVED_0X43, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_RESERVED_0X44, // Indicates if the "xnack" target feature is enabled for all code contained // in the object. diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AMDGPU.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AMDGPU.def index 00b19c4161d08..0ff7b4c766cc1 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AMDGPU.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AMDGPU.def @@ -15,3 +15,4 @@ ELF_RELOC(R_AMDGPU_GOTPCREL32_HI, 9) ELF_RELOC(R_AMDGPU_REL32_LO, 10) ELF_RELOC(R_AMDGPU_REL32_HI, 11) ELF_RELOC(R_AMDGPU_RELATIVE64, 13) +ELF_RELOC(R_AMDGPU_REL16, 14) diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index da591f4183b08..28870afb2fcb3 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -670,6 +670,7 @@ enum AttributeKindCodes { ATTR_KIND_VSCALE_RANGE = 74, ATTR_KIND_SWIFT_ASYNC = 75, ATTR_KIND_NO_SANITIZE_COVERAGE = 76, + ATTR_KIND_ELEMENTTYPE = 77, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h index f5010c6b8bc5d..1fd07ca2c8d42 100644 --- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h +++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h @@ -869,6 +869,8 @@ Error CodeGenPassBuilder::addMachinePasses( // Run post-ra passes. derived().addPostRegAlloc(addPass); + addPass(RemoveRedundantDebugValuesPass()); + // Insert prolog/epilog code. Eliminate abstract frame index references... if (getOptLevel() != CodeGenOpt::None) { addPass(PostRAMachineSinkingPass()); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 2559cb3392ff2..6bdaddd9c6f54 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -252,7 +252,8 @@ class CallLowering { /// This is overridable primarily for targets to maintain compatibility with /// hacks around the existing DAG call lowering infrastructure. virtual LLT getStackValueStoreType(const DataLayout &DL, - const CCValAssign &VA) const; + const CCValAssign &VA, + ISD::ArgFlagsTy Flags) const; /// The specified value has been assigned to a physical register, /// handle the appropriate COPY (either to or from) and mark any @@ -281,7 +282,7 @@ class CallLowering { /// \return The number of \p VAs that have been assigned after the first /// one, and which should therefore be skipped from further /// processing. - virtual unsigned assignCustomValue(const ArgInfo &Arg, + virtual unsigned assignCustomValue(ArgInfo &Arg, ArrayRef VAs) { // This is not a pure virtual method because not all targets need to worry // about custom values. @@ -354,17 +355,13 @@ class CallLowering { /// Break \p OrigArgInfo into one or more pieces the calling convention can /// process, returned in \p SplitArgs. For example, this should break structs /// down into individual fields. + /// + /// If \p Offsets is non-null, it points to a vector to be filled in + /// with the in-memory offsets of each of the individual values. void splitToValueTypes(const ArgInfo &OrigArgInfo, SmallVectorImpl &SplitArgs, - const DataLayout &DL, CallingConv::ID CallConv) const; - - /// Generate instructions for unpacking \p SrcReg into the \p DstRegs - /// corresponding to the aggregate type \p PackedTy. - /// - /// \param DstRegs should contain one virtual register for each base type in - /// \p PackedTy, as returned by computeValueLLTs. - void unpackRegs(ArrayRef DstRegs, Register SrcReg, Type *PackedTy, - MachineIRBuilder &MIRBuilder) const; + const DataLayout &DL, CallingConv::ID CallConv, + SmallVectorImpl *Offsets = nullptr) const; /// Analyze the argument list in \p Args, using \p Assigner to populate \p /// CCInfo. This will determine the types and locations to use for passed or diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 0988fe793176d..0ce9d8e5299e1 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -19,6 +19,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/Register.h" #include "llvm/Support/Alignment.h" @@ -596,7 +597,7 @@ class CombinerHelper { /// \param [in] MemSizeInBits - The number of bits each load should produce. /// /// \returns The lowest-index load found and the lowest index on success. - Optional> findLoadOffsetsForLoadOrCombine( + Optional> findLoadOffsetsForLoadOrCombine( SmallDenseMap &MemOffset2Idx, const SmallVector &RegsToVisit, const unsigned MemSizeInBits); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h new file mode 100644 index 0000000000000..eef6ff7a23a48 --- /dev/null +++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h @@ -0,0 +1,141 @@ +//===- llvm/CodeGen/GlobalISel/GenericMachineInstrs.h -----------*- C++ -*-===// +// +// 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 +/// Declares convenience wrapper classes for interpreting MachineInstr instances +/// as specific generic operations. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H +#define LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +/// A base class for all GenericMachineInstrs. +class GenericMachineInstr : public MachineInstr { +public: + GenericMachineInstr() = delete; + + /// Access the Idx'th operand as a register and return it. + /// This assumes that the Idx'th operand is a Register type. + Register getReg(unsigned Idx) { return getOperand(Idx).getReg(); } + + static bool classof(const MachineInstr *MI) { + return isPreISelGenericOpcode(MI->getOpcode()); + } +}; + +/// Represents any type of generic load or store. +/// G_LOAD, G_STORE, G_ZEXTLOAD, G_SEXTLOAD. +class GLoadStore : public GenericMachineInstr { +public: + /// Get the source register of the pointer value. + Register getPointerReg() const { return getOperand(1).getReg(); } + + /// Get the MachineMemOperand on this instruction. + MachineMemOperand &getMMO() const { return **memoperands_begin(); } + + /// Returns true if the attached MachineMemOperand has the atomic flag set. + bool isAtomic() const { return getMMO().isAtomic(); } + /// Returns true if the attached MachineMemOpeand as the volatile flag set. + bool isVolatile() const { return getMMO().isVolatile(); } + /// Returns true if the memory operation is neither atomic or volatile. + bool isSimple() const { return !isAtomic() && !isVolatile(); } + /// Returns true if this memory operation doesn't have any ordering + /// constraints other than normal aliasing. Volatile and (ordered) atomic + /// memory operations can't be reordered. + bool isUnordered() const { return getMMO().isUnordered(); } + + /// Returns the size in bytes of the memory access. + uint64_t getMemSize() { return getMMO().getSize(); + } /// Returns the size in bits of the memory access. + uint64_t getMemSizeInBits() { return getMMO().getSizeInBits(); } + + static bool classof(const MachineInstr *MI) { + switch (MI->getOpcode()) { + case TargetOpcode::G_LOAD: + case TargetOpcode::G_STORE: + case TargetOpcode::G_ZEXTLOAD: + case TargetOpcode::G_SEXTLOAD: + return true; + default: + return false; + } + } +}; + +/// Represents any generic load, including sign/zero extending variants. +class GAnyLoad : public GLoadStore { +public: + /// Get the definition register of the loaded value. + Register getDstReg() const { return getOperand(0).getReg(); } + + static bool classof(const MachineInstr *MI) { + switch (MI->getOpcode()) { + case TargetOpcode::G_LOAD: + case TargetOpcode::G_ZEXTLOAD: + case TargetOpcode::G_SEXTLOAD: + return true; + default: + return false; + } + } +}; + +/// Represents a G_LOAD. +class GLoad : public GAnyLoad { +public: + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_LOAD; + } +}; + +/// Represents either a G_SEXTLOAD or G_ZEXTLOAD. +class GExtLoad : public GAnyLoad { +public: + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_SEXTLOAD || + MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; + } +}; + +/// Represents a G_SEXTLOAD. +class GSExtLoad : public GExtLoad { +public: + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_SEXTLOAD; + } +}; + +/// Represents a G_ZEXTLOAD. +class GZExtLoad : public GExtLoad { +public: + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_ZEXTLOAD; + } +}; + +/// Represents a G_STORE. +class GStore : public GLoadStore { +public: + /// Get the stored value register. + Register getValueReg() const { return getOperand(0).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_STORE; + } +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H \ No newline at end of file diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 051d3f251f196..67141f3a63260 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -21,6 +21,7 @@ #define LLVM_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H #include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -308,8 +309,8 @@ class LegalizerHelper { LegalizeResult fewerElementsVectorMulo(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); - LegalizeResult - reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, + LLT NarrowTy); /// Legalize an instruction by reducing the operation width, either by /// narrowing the type of the operation or by reducing the number of elements @@ -357,8 +358,8 @@ class LegalizerHelper { LLT CastTy); LegalizeResult lowerBitcast(MachineInstr &MI); - LegalizeResult lowerLoad(MachineInstr &MI); - LegalizeResult lowerStore(MachineInstr &MI); + LegalizeResult lowerLoad(GAnyLoad &MI); + LegalizeResult lowerStore(GStore &MI); LegalizeResult lowerBitCount(MachineInstr &MI); LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI); LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h index 5bb36ad0a477b..e151c65dcee6d 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -230,6 +230,16 @@ MachineInstr *getDefIgnoringCopies(Register Reg, /// Also walks through hints such as G_ASSERT_ZEXT. Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); +// Templated variant of getOpcodeDef returning a MachineInstr derived T. +/// See if Reg is defined by an single def instruction of type T +/// Also try to do trivial folding if it's a COPY with +/// same types. Returns null otherwise. +template +T *getOpcodeDef(Register Reg, const MachineRegisterInfo &MRI) { + MachineInstr *DefMI = getDefIgnoringCopies(Reg, MRI); + return dyn_cast_or_null(DefMI); +} + /// Returns an APFloat from Val converted to the appropriate size. APFloat getAPFloatFromSize(double Val, unsigned Size); @@ -384,9 +394,5 @@ int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP); bool shouldOptForSize(const MachineBasicBlock &MBB, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI); -/// \returns the intrinsic ID for a G_INTRINSIC or G_INTRINSIC_W_SIDE_EFFECTS -/// instruction \p MI. -unsigned getIntrinsicID(const MachineInstr &MI); - } // End namespace llvm. #endif diff --git a/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index cde3bc08692b9..7e7e0a9c477a8 100644 --- a/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -55,10 +55,6 @@ class MachineBranchProbabilityInfo : public ImmutablePass { bool isEdgeHot(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const; - // Return a hot successor for the block BB or null if there isn't one. - // NB: This routine's complexity is linear on the number of successors. - MachineBasicBlock *getHotSucc(MachineBasicBlock *MBB) const; - // Print value between 0 (0% probability) and 1 (100% probability), // however the value is never equal to 0, and can be 1 only iff SRC block // has only one successor. diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index 42bf0af58958a..757907f6d8879 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -468,6 +468,12 @@ class MachineInstr /// deserializing this information. void setDebugInstrNum(unsigned Num) { DebugInstrNum = Num; } + /// Drop any variable location debugging information associated with this + /// instruction. Use when an instruction is modified in such a way that it no + /// longer defines the value it used to. Variable locations using that value + /// will be dropped. + void dropDebugNumber() { DebugInstrNum = 0; } + /// Emit an error referring to the source location of this instruction. /// This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much diff --git a/llvm/include/llvm/CodeGen/MachinePassRegistry.def b/llvm/include/llvm/CodeGen/MachinePassRegistry.def index f77bce5a9c287..d79303c771d63 100644 --- a/llvm/include/llvm/CodeGen/MachinePassRegistry.def +++ b/llvm/include/llvm/CodeGen/MachinePassRegistry.def @@ -155,6 +155,7 @@ DUMMY_MACHINE_FUNCTION_PASS("reg-usage-propagation", RegUsageInfoPropagationPass DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass, ()) DUMMY_MACHINE_FUNCTION_PASS("funclet-layout", FuncletLayoutPass, ()) DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass, ()) +DUMMY_MACHINE_FUNCTION_PASS("removeredundantdebugvalues", RemoveRedundantDebugValuesPass, ()) DUMMY_MACHINE_FUNCTION_PASS("livedebugvalues", LiveDebugValuesPass, ()) DUMMY_MACHINE_FUNCTION_PASS("early-tailduplication", EarlyTailDuplicatePass, ()) DUMMY_MACHINE_FUNCTION_PASS("opt-phis", OptimizePHIsPass, ()) diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index 76667eac051dd..da1bab7189488 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -16,6 +16,8 @@ #include "llvm/Support/CodeGen.h" #include "llvm/Support/Discriminator.h" +#include "llvm/CodeGen/RegAllocCommon.h" + #include #include @@ -173,16 +175,20 @@ namespace llvm { /// possible. It is best suited for debug code where live ranges are short. /// FunctionPass *createFastRegisterAllocator(); + FunctionPass *createFastRegisterAllocator(RegClassFilterFunc F, + bool ClearVirtRegs); /// BasicRegisterAllocation Pass - This pass implements a degenerate global /// register allocator using the basic regalloc framework. /// FunctionPass *createBasicRegisterAllocator(); + FunctionPass *createBasicRegisterAllocator(RegClassFilterFunc F); /// Greedy register allocation pass - This pass implements a global register /// allocator for optimized builds. /// FunctionPass *createGreedyRegisterAllocator(); + FunctionPass *createGreedyRegisterAllocator(RegClassFilterFunc F); /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean /// Quadratic Prograaming (PBQP) based register allocator. @@ -394,6 +400,9 @@ namespace llvm { /// the intrinsic for later emission to the StackMap. extern char &StackMapLivenessID; + /// RemoveRedundantDebugValues pass. + extern char &RemoveRedundantDebugValuesID; + /// LiveDebugValues pass extern char &LiveDebugValuesID; diff --git a/llvm/include/llvm/CodeGen/RegAllocCommon.h b/llvm/include/llvm/CodeGen/RegAllocCommon.h new file mode 100644 index 0000000000000..39b77d9193703 --- /dev/null +++ b/llvm/include/llvm/CodeGen/RegAllocCommon.h @@ -0,0 +1,32 @@ +//===- RegAllocCommon.h - Utilities shared between allocators ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGALLOCCOMMON_H +#define LLVM_CODEGEN_REGALLOCCOMMON_H + +#include + +namespace llvm { + +class TargetRegisterClass; +class TargetRegisterInfo; + +typedef std::function RegClassFilterFunc; + +/// Default register class filter function for register allocation. All virtual +/// registers should be allocated. +static inline bool allocateAllRegClasses(const TargetRegisterInfo &, + const TargetRegisterClass &) { + return true; +} + +} + +#endif // LLVM_CODEGEN_REGALLOCCOMMON_H diff --git a/llvm/include/llvm/CodeGen/RegAllocRegistry.h b/llvm/include/llvm/CodeGen/RegAllocRegistry.h index 9a63674689b30..e33d16c636277 100644 --- a/llvm/include/llvm/CodeGen/RegAllocRegistry.h +++ b/llvm/include/llvm/CodeGen/RegAllocRegistry.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_REGALLOCREGISTRY_H #define LLVM_CODEGEN_REGALLOCREGISTRY_H +#include "llvm/CodeGen/RegAllocCommon.h" #include "llvm/CodeGen/MachinePassRegistry.h" namespace llvm { diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index 5e12da6791add..4b10d6ea9ff3a 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -837,6 +837,10 @@ class SelectionDAG { /// <0, Step, Step * 2, Step * 3, ...> SDValue getStepVector(const SDLoc &DL, EVT ResVT, SDValue Step); + /// Returns a vector of type ResVT whose elements contain the linear sequence + /// <0, 1, 2, 3, ...> + SDValue getStepVector(const SDLoc &DL, EVT ResVT); + /// Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to /// the shuffle node in input but with swapped operands. /// @@ -1707,11 +1711,6 @@ class SelectionDAG { bool MaskedValueIsZero(SDValue Op, const APInt &Mask, const APInt &DemandedElts, unsigned Depth = 0) const; - /// Return true if the DemandedElts of the vector Op are all zero. We - /// use this predicate to simplify operations downstream. - bool MaskedElementsAreZero(SDValue Op, const APInt &DemandedElts, - unsigned Depth = 0) const; - /// Return true if '(Op & Mask) == Mask'. /// Op and Mask are known to be the same type. bool MaskedValueIsAllOnes(SDValue Op, const APInt &Mask, diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 929bcb4bd5f10..a9bf215e7c4a6 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -2717,16 +2717,6 @@ namespace ISD { St->getAddressingMode() == ISD::UNINDEXED; } - /// Returns true if the specified node is a non-truncating store. - inline bool isNON_TRUNCStore(const SDNode *N) { - return isa(N) && !cast(N)->isTruncatingStore(); - } - - /// Returns true if the specified node is a truncating store. - inline bool isTRUNCStore(const SDNode *N) { - return isa(N) && cast(N)->isTruncatingStore(); - } - /// Returns true if the specified node is an unindexed store. inline bool isUNINDEXEDStore(const SDNode *N) { return isa(N) && diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index 21758e0cfc2ac..05d0591f1e5da 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -129,6 +129,12 @@ class TargetInstrInfo : public MCInstrInfo { isReallyTriviallyReMaterializableGeneric(MI, AA))); } + /// Given \p MO is a PhysReg use return if it can be ignored for the purpose + /// of instruction rematerialization. + virtual bool isIgnorableUse(const MachineOperand &MO) const { + return false; + } + protected: /// For instructions with opcodes for which the M_REMATERIALIZABLE flag is /// set, this hook lets the target specify whether the instruction is actually @@ -459,6 +465,13 @@ class TargetInstrInfo : public MCInstrInfo { unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const; + /// Returns true if the target has a preference on the operands order of + /// the given machine instruction. And specify if \p Commute is required to + /// get the desired operands order. + virtual bool hasCommutePreference(MachineInstr &MI, bool &Commute) const { + return false; + } + /// A pair composed of a register and a sub-register index. /// Used to give some type checking when modeling Reg:SubReg. struct RegSubRegPair { diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h b/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h index cda32633ce657..17eb06c242a95 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -11,8 +11,6 @@ #include "llvm/Support/Error.h" -#include - namespace llvm { namespace codeview { enum class cv_error_code { diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h index fd225c3c10d0a..d029556c9d89c 100644 --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -56,9 +56,7 @@ struct DILineInfo { Discriminator == RHS.Discriminator; } - bool operator!=(const DILineInfo &RHS) const { - return !(*this == RHS); - } + bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); } bool operator<(const DILineInfo &RHS) const { return std::tie(FileName, FunctionName, StartFileName, Line, Column, @@ -92,7 +90,7 @@ class DIInliningInfo { public: DIInliningInfo() = default; - const DILineInfo & getFrame(unsigned Index) const { + const DILineInfo &getFrame(unsigned Index) const { assert(Index < Frames.size()); return Frames[Index]; } @@ -102,17 +100,11 @@ class DIInliningInfo { return &Frames[Index]; } - uint32_t getNumberOfFrames() const { - return Frames.size(); - } + uint32_t getNumberOfFrames() const { return Frames.size(); } - void addFrame(const DILineInfo &Frame) { - Frames.push_back(Frame); - } + void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); } - void resize(unsigned i) { - Frames.resize(i); - } + void resize(unsigned i) { Frames.resize(i); } }; /// Container for description of a global variable. @@ -175,7 +167,7 @@ static_assert(DIDT_ID_Count <= 32, "section types overflow storage"); /// Selects which debug sections get dumped. enum DIDumpType : unsigned { DIDT_Null, - DIDT_All = ~0U, + DIDT_All = ~0U, #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \ DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME, #include "llvm/BinaryFormat/Dwarf.def" @@ -224,10 +216,7 @@ struct DIDumpOptions { class DIContext { public: - enum DIContextKind { - CK_DWARF, - CK_PDB - }; + enum DIContextKind { CK_DWARF, CK_PDB }; DIContext(DIContextKind K) : Kind(K) {} virtual ~DIContext() = default; @@ -311,7 +300,7 @@ struct LoadedObjectInfoHelper : Base { public: template - LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward(Args)...) {} + LoadedObjectInfoHelper(Ts &&...Args) : Base(std::forward(Args)...) {} std::unique_ptr clone() const override { return std::make_unique(static_cast(*this)); diff --git a/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h b/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h index da49b4592ee8d..872ccd4a0b6ab 100644 --- a/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h +++ b/llvm/include/llvm/DebugInfo/GSYM/GsymCreator.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "llvm/ADT/ArrayRef.h" diff --git a/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h b/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h index 1865fe78260b5..4ad9990c372fb 100644 --- a/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h +++ b/llvm/include/llvm/DebugInfo/GSYM/GsymReader.h @@ -9,7 +9,6 @@ #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H #define LLVM_DEBUGINFO_GSYM_GSYMREADER_H - #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/GSYM/FileEntry.h" #include "llvm/DebugInfo/GSYM/FunctionInfo.h" @@ -19,11 +18,9 @@ #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorOr.h" - #include #include #include -#include #include namespace llvm { diff --git a/llvm/include/llvm/DebugInfo/GSYM/LookupResult.h b/llvm/include/llvm/DebugInfo/GSYM/LookupResult.h index 79ef7b22111b9..211a352595fde 100644 --- a/llvm/include/llvm/DebugInfo/GSYM/LookupResult.h +++ b/llvm/include/llvm/DebugInfo/GSYM/LookupResult.h @@ -9,8 +9,8 @@ #ifndef LLVM_DEBUGINFO_GSYM_LOOKUPRESULT_H #define LLVM_DEBUGINFO_GSYM_LOOKUPRESULT_H -#include "llvm/DebugInfo/GSYM/Range.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/GSYM/Range.h" #include #include @@ -20,27 +20,25 @@ namespace gsym { struct FileEntry; struct SourceLocation { - StringRef Name; ///< Function or symbol name. - StringRef Dir; ///< Line entry source file directory path. - StringRef Base; ///< Line entry source file basename. - uint32_t Line = 0; ///< Source file line number. + StringRef Name; ///< Function or symbol name. + StringRef Dir; ///< Line entry source file directory path. + StringRef Base; ///< Line entry source file basename. + uint32_t Line = 0; ///< Source file line number. uint32_t Offset = 0; ///< Byte size offset within the named function. }; inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) { - return LHS.Name == RHS.Name && LHS.Dir == RHS.Dir && - LHS.Base == RHS.Base && LHS.Line == RHS.Line && - LHS.Offset == RHS.Offset; + return LHS.Name == RHS.Name && LHS.Dir == RHS.Dir && LHS.Base == RHS.Base && + LHS.Line == RHS.Line && LHS.Offset == RHS.Offset; } raw_ostream &operator<<(raw_ostream &OS, const SourceLocation &R); using SourceLocations = std::vector; - struct LookupResult { uint64_t LookupAddr = 0; ///< The address that this lookup pertains to. - AddressRange FuncRange; ///< The concrete function address range. + AddressRange FuncRange; ///< The concrete function address range. StringRef FuncName; ///< The concrete function name that contains LookupAddr. /// The source locations that match this address. This information will only /// be filled in if the FunctionInfo contains a line table. If an address is diff --git a/llvm/include/llvm/DebugInfo/MSF/MSFError.h b/llvm/include/llvm/DebugInfo/MSF/MSFError.h index 67962fbd50285..0ef30f10bc686 100644 --- a/llvm/include/llvm/DebugInfo/MSF/MSFError.h +++ b/llvm/include/llvm/DebugInfo/MSF/MSFError.h @@ -11,8 +11,6 @@ #include "llvm/Support/Error.h" -#include - namespace llvm { namespace msf { enum class msf_error_code { diff --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h index baff2fa724844..4ec333422c4bf 100644 --- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -15,8 +15,8 @@ #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" #include "llvm/Object/Binary.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" #include #include @@ -54,9 +54,7 @@ class LLVMSymbolizer { LLVMSymbolizer() = default; LLVMSymbolizer(const Options &Opts) : Opts(Opts) {} - ~LLVMSymbolizer() { - flush(); - } + ~LLVMSymbolizer() { flush(); } // Overloads accepting ObjectFile does not support COFF currently Expected symbolizeCode(const ObjectFile &Obj, @@ -115,8 +113,7 @@ class LLVMSymbolizer { Expected getOrCreateModuleInfo(const ObjectFile &Obj); Expected - createModuleInfo(const ObjectFile *Obj, - std::unique_ptr Context, + createModuleInfo(const ObjectFile *Obj, std::unique_ptr Context, StringRef ModuleName); ObjectFile *lookUpDsymFile(const std::string &Path, @@ -131,13 +128,13 @@ class LLVMSymbolizer { /// Returns pair of pointers to object and debug object. Expected getOrCreateObjectPair(const std::string &Path, - const std::string &ArchName); + const std::string &ArchName); /// Return a pointer to object file at specified path, for a specified /// architecture (e.g. if path refers to a Mach-O universal binary, only one /// object file from it will be returned). Expected getOrCreateObject(const std::string &Path, - const std::string &ArchName); + const std::string &ArchName); std::map, std::less<>> Modules; diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index 15b5286b869a6..81d8dbee48001 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -916,6 +916,12 @@ class LinkGraph { const char *getEdgeKindName(Edge::Kind K) const { return GetEdgeKindName(K); } + /// Allocate a mutable buffer of the given size using the LinkGraph's + /// allocator. + MutableArrayRef allocateBuffer(size_t Size) { + return {Allocator.Allocate(Size), Size}; + } + /// Allocate a copy of the given string using the LinkGraph's allocator. /// This can be useful when renaming symbols or adding new content to the /// graph. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 91b12fd2277a7..30544e8a17486 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -47,7 +47,6 @@ #include #include #include -#include #include #include diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h index 42bcffd36b25a..159553b5559f4 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -792,7 +792,7 @@ reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, /// Build a SymbolAliasMap for the common case where you want to re-export /// symbols from another JITDylib with the same linkage/flags. Expected -buildSimpleReexportsAAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); +buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); /// Represents the state that a symbol has reached during materialization. enum class SymbolState : uint8_t { @@ -1224,9 +1224,19 @@ class Platform { /// A utility function for looking up initializer symbols. Performs a blocking /// lookup for the given symbols in each of the given JITDylibs. + /// + /// Note: This function is deprecated and will be removed in the near future. static Expected> lookupInitSymbols(ExecutionSession &ES, const DenseMap &InitSyms); + + /// Performs an async lookup for the the given symbols in each of the given + /// JITDylibs, calling the given handler with the compound result map once + /// all lookups have completed. + static void + lookupInitSymbolsAsync(unique_function OnComplete, + ExecutionSession &ES, + const DenseMap &InitSyms); }; /// Represents an abstract task for ORC to run. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index fdddc9694d0bc..1946aed9733ed 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -24,7 +24,6 @@ #include "llvm/Support/DynamicLibrary.h" #include #include -#include #include #include diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h index 566637e104456..f8d6192706a1d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" #include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h" #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" #include "llvm/Support/DynamicLibrary.h" @@ -113,6 +114,13 @@ class ExecutorProcessControl { const SymbolLookupSet &Symbols; }; + /// Contains the address of the dispatch function and context that the ORC + /// runtime can use to call functions in the JIT. + struct JITDispatchInfo { + ExecutorAddress JITDispatchFunctionAddress; + ExecutorAddress JITDispatchContextAddress; + }; + virtual ~ExecutorProcessControl(); /// Intern a symbol name in the SymbolStringPool. @@ -127,6 +135,9 @@ class ExecutorProcessControl { /// Get the page size for the target process. unsigned getPageSize() const { return PageSize; } + /// Get the JIT dispatch function and context address for the executor. + const JITDispatchInfo &getJITDispatchInfo() const { return JDI; } + /// Return a MemoryAccess object for the target process. MemoryAccess &getMemoryAccess() const { return *MemAccess; } @@ -198,14 +209,17 @@ class ExecutorProcessControl { /// Run a wrapper function using SPS to serialize the arguments and /// deserialize the results. - template - Error runSPSWrapper(JITTargetAddress WrapperFnAddr, RetT &RetVal, - const ArgTs &...Args) { + /// + /// If SPSSignature is a non-void function signature then the second argument + /// (the first in the Args list) should be a reference to a return value. + template + Error runSPSWrapper(JITTargetAddress WrapperFnAddr, + WrapperCallArgTs &&...WrapperCallArgs) { return shared::WrapperFunction::call( [this, WrapperFnAddr](const char *ArgData, size_t ArgSize) { return runWrapper(WrapperFnAddr, ArrayRef(ArgData, ArgSize)); }, - RetVal, Args...); + std::forward(WrapperCallArgs)...); } /// Wrap a handler that takes concrete argument types (and a sender for a @@ -223,6 +237,15 @@ class ExecutorProcessControl { }; } + template + static AsyncWrapperFunction + wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) { + return wrapAsyncWithSPS( + [Instance, Method](MethodArgTs &&...MethodArgs) { + (Instance->*Method)(std::forward(MethodArgs)...); + }); + } + /// For each symbol name, associate the AsyncWrapperFunction implementation /// value with the address of that symbol. /// @@ -250,6 +273,7 @@ class ExecutorProcessControl { std::shared_ptr SSP; Triple TargetTriple; unsigned PageSize = 0; + JITDispatchInfo JDI; MemoryAccess *MemAccess = nullptr; jitlink::JITLinkMemoryManager *MemMgr = nullptr; @@ -318,6 +342,10 @@ class SelfExecutorProcessControl void writeBuffers(ArrayRef Ws, WriteResultFn OnWriteComplete) override; + static shared::detail::CWrapperFunctionResult + jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag, + const char *Data, size_t Size); + std::unique_ptr OwnedMemMgr; char GlobalManglingPrefix = 0; std::vector> DynamicLibraries; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index be8526bf4353f..f493d63a7c8a9 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -18,8 +18,9 @@ #include "llvm/ExecutionEngine/Orc/Layer.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" +#include #include -#include +#include namespace llvm { diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 66966a0f87626..f368c92b37021 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -17,7 +17,6 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Layer.h" #include -#include namespace llvm { class Module; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h index 50a2d95624c3c..cc23147aac388 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -442,20 +442,6 @@ class LLLazyJITBuilder /// should be preferred where available. void setUpGenericLLVMIRPlatform(LLJIT &J); -/// Configure the LLJIT instance to use MachOPlatform support. -/// -/// Warning: MachOPlatform *requires* that LLJIT be configured to use -/// ObjectLinkingLayer (default on platforms supported by JITLink). If -/// MachOPlatform is used with RTDyldObjectLinkingLayer it will result in -/// undefined behavior). -/// -/// MachOPlatform installs an ObjectLinkingLayer plugin to scrape initializers -/// from the __mod_inits section. It also provides interposes for the dlfcn -/// functions (dlopen, dlclose, dlsym, dlerror) that work for JITDylibs as -/// well as regular libraries (JITDylibs will be preferenced, so make sure -/// your JITDylib names do not shadow any real library paths). -Error setUpMachOPlatform(LLJIT &J); - /// Configure the LLJIT instance to disable platform support explicitly. This is /// useful in two cases: for platforms that don't have such requirements and for /// platforms, that we have no explicit support yet and that don't work well diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLVMSPSSerializers.h b/llvm/include/llvm/ExecutionEngine/Orc/LLVMSPSSerializers.h new file mode 100644 index 0000000000000..f3d616deae8f8 --- /dev/null +++ b/llvm/include/llvm/ExecutionEngine/Orc/LLVMSPSSerializers.h @@ -0,0 +1,69 @@ +//===-- LLVMSPSSerializers.h - SPS serialization for LLVM types -*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// SPS Serialization for common LLVM types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LLVMSPSSERIALIZERS_H +#define LLVM_EXECUTIONENGINE_ORC_LLVMSPSSERIALIZERS_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" + +namespace llvm { +namespace orc { +namespace shared { + +template +class SPSSerializationTraits>, + StringMap> { +public: + static size_t size(const StringMap &M) { + size_t Sz = SPSArgList::size(static_cast(M.size())); + for (auto &E : M) + Sz += SPSArgList::size(E.first(), E.second); + return Sz; + } + + static bool serialize(SPSOutputBuffer &OB, const StringMap &M) { + if (!SPSArgList::serialize(OB, static_cast(M.size()))) + return false; + + for (auto &E : M) + if (!SPSArgList::serialize(OB, E.first(), E.second)) + return false; + + return true; + } + + static bool deserialize(SPSInputBuffer &IB, StringMap &M) { + uint64_t Size; + assert(M.empty() && "M already contains elements"); + + if (!SPSArgList::deserialize(IB, Size)) + return false; + + while (Size--) { + StringRef S; + ValueT V; + if (!SPSArgList::deserialize(IB, S, V)) + return false; + if (!M.insert(std::make_pair(S, V)).second) + return false; + } + + return true; + } +}; + +} // end namespace shared +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_LLVMSPSSERIALIZERS_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h index e708604a19e10..50f26b399a69c 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h @@ -15,7 +15,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/Orc/Core.h" -#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" +#include "llvm/ExecutionEngine/Orc/LLVMSPSSerializers.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" @@ -26,86 +27,106 @@ namespace llvm { namespace orc { -/// Enable registration of JIT'd ObjC classes and selectors. -Error enableObjCRegistration(const char *PathToLibObjC); -bool objCRegistrationEnabled(); - -class MachOJITDylibInitializers { -public: - using RawPointerSectionList = std::vector; - - void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) { - this->ObjCImageInfoAddr = ObjCImageInfoAddr; - } - - void addModInitsSection(ExecutorAddressRange ModInit) { - ModInitSections.push_back(std::move(ModInit)); - } - - const RawPointerSectionList &getModInitsSections() const { - return ModInitSections; - } - - void addObjCSelRefsSection(ExecutorAddressRange ObjCSelRefs) { - ObjCSelRefsSections.push_back(std::move(ObjCSelRefs)); - } +struct MachOPerObjectSectionsToRegister { + ExecutorAddressRange EHFrameSection; +}; - const RawPointerSectionList &getObjCSelRefsSections() const { - return ObjCSelRefsSections; - } +struct MachOJITDylibInitializers { + using SectionList = std::vector; - void addObjCClassListSection(ExecutorAddressRange ObjCClassList) { - ObjCClassListSections.push_back(std::move(ObjCClassList)); - } - - const RawPointerSectionList &getObjCClassListSections() const { - return ObjCClassListSections; - } + MachOJITDylibInitializers(std::string Name, + ExecutorAddress MachOHeaderAddress) + : Name(std::move(Name)), + MachOHeaderAddress(std::move(MachOHeaderAddress)) {} - void runModInits() const; - void registerObjCSelectors() const; - Error registerObjCClasses() const; + std::string Name; + ExecutorAddress MachOHeaderAddress; -private: - - JITTargetAddress ObjCImageInfoAddr; - RawPointerSectionList ModInitSections; - RawPointerSectionList ObjCSelRefsSections; - RawPointerSectionList ObjCClassListSections; + StringMap InitSections; }; class MachOJITDylibDeinitializers {}; +using MachOJITDylibInitializerSequence = std::vector; + +using MachOJITDylibDeinitializerSequence = + std::vector; + /// Mediates between MachO initialization and ExecutionSession state. class MachOPlatform : public Platform { public: - using InitializerSequence = - std::vector>; - - using DeinitializerSequence = - std::vector>; - - MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, - std::unique_ptr StandardSymbolsObject); + /// Try to create a MachOPlatform instance, adding the ORC runtime to the + /// given JITDylib. + /// + /// The ORC runtime requires access to a number of symbols in libc++, and + /// requires access to symbols in libobjc, and libswiftCore to support + /// Objective-C and Swift code. It is up to the caller to ensure that the + /// requried symbols can be referenced by code added to PlatformJD. The + /// standard way to achieve this is to first attach dynamic library search + /// generators for either the given process, or for the specific required + /// libraries, to PlatformJD, then to create the platform instance: + /// + /// \code{.cpp} + /// auto &PlatformJD = ES.createBareJITDylib("stdlib"); + /// PlatformJD.addGenerator( + /// ExitOnErr(EPCDynamicLibrarySearchGenerator + /// ::GetForTargetProcess(EPC))); + /// ES.setPlatform( + /// ExitOnErr(MachOPlatform::Create(ES, ObjLayer, EPC, PlatformJD, + /// "/path/to/orc/runtime"))); + /// \endcode + /// + /// Alternatively, these symbols could be added to another JITDylib that + /// PlatformJD links against. + /// + /// Clients are also responsible for ensuring that any JIT'd code that + /// depends on runtime functions (including any code using TLV or static + /// destructors) can reference the runtime symbols. This is usually achieved + /// by linking any JITDylibs containing regular code against + /// PlatformJD. + /// + /// By default, MachOPlatform will add the set of aliases returned by the + /// standardPlatformAliases function. This includes both required aliases + /// (e.g. __cxa_atexit -> __orc_rt_macho_cxa_atexit for static destructor + /// support), and optional aliases that provide JIT versions of common + /// functions (e.g. dlopen -> __orc_rt_macho_jit_dlopen). Clients can + /// override these defaults by passing a non-None value for the + /// RuntimeAliases function, in which case the client is responsible for + /// setting up all aliases (including the required ones). + static Expected> + Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + ExecutorProcessControl &EPC, JITDylib &PlatformJD, + const char *OrcRuntimePath, + Optional RuntimeAliases = None); ExecutionSession &getExecutionSession() const { return ES; } + ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; } + ExecutorProcessControl &getExecutorProcessControl() const { return EPC; } Error setupJITDylib(JITDylib &JD) override; Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) override; Error notifyRemoving(ResourceTracker &RT) override; - Expected getInitializerSequence(JITDylib &JD); + /// Returns an AliasMap containing the default aliases for the MachOPlatform. + /// This can be modified by clients when constructing the platform to add + /// or remove aliases. + static SymbolAliasMap standardPlatformAliases(ExecutionSession &ES); - Expected getDeinitializerSequence(JITDylib &JD); + /// Returns the array of required CXX aliases. + static ArrayRef> requiredCXXAliases(); + + /// Returns the array of standard runtime utility aliases for MachO. + static ArrayRef> + standardRuntimeUtilityAliases(); private: - // This ObjectLinkingLayer plugin scans JITLink graphs for __mod_init_func, - // __objc_classlist and __sel_ref sections and records their extents so that - // they can be run in the target process. - class InitScraperPlugin : public ObjectLinkingLayer::Plugin { + // The MachOPlatformPlugin scans/modifies LinkGraphs to support MachO + // platform features including initializers, exceptions, TLV, and language + // runtime registration. + class MachOPlatformPlugin : public ObjectLinkingLayer::Plugin { public: - InitScraperPlugin(MachOPlatform &MP) : MP(MP) {} + MachOPlatformPlugin(MachOPlatform &MP) : MP(MP) {} void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, @@ -131,36 +152,173 @@ class MachOPlatform : public Platform { using InitSymbolDepMap = DenseMap; - void preserveInitSectionIfPresent(JITLinkSymbolSet &Symbols, - jitlink::LinkGraph &G, - StringRef SectionName); + void addInitializerSupportPasses(MaterializationResponsibility &MR, + jitlink::PassConfiguration &Config); + + void addMachOHeaderSupportPasses(MaterializationResponsibility &MR, + jitlink::PassConfiguration &Config); - Error processObjCImageInfo(jitlink::LinkGraph &G, + void addEHSupportPasses(MaterializationResponsibility &MR, + jitlink::PassConfiguration &Config); + + Error preserveInitSections(jitlink::LinkGraph &G, MaterializationResponsibility &MR); - std::mutex InitScraperMutex; + Error registerInitSections(jitlink::LinkGraph &G, JITDylib &JD); + + std::mutex PluginMutex; MachOPlatform &MP; - DenseMap> ObjCImageInfos; InitSymbolDepMap InitSymbolDeps; }; - void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr, - ExecutorAddressRange ModInits, - ExecutorAddressRange ObjCSelRefs, - ExecutorAddressRange ObjCClassList); + using SendInitializerSequenceFn = + unique_function)>; + + using SendDeinitializerSequenceFn = + unique_function)>; + + using SendSymbolAddressFn = unique_function)>; + + static bool supportedTarget(const Triple &TT); + + MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + ExecutorProcessControl &EPC, JITDylib &PlatformJD, + std::unique_ptr OrcRuntimeGenerator, + Error &Err); + + // Associate MachOPlatform JIT-side runtime support functions with handlers. + Error associateRuntimeSupportFunctions(JITDylib &PlatformJD); + + void getInitializersBuildSequencePhase(SendInitializerSequenceFn SendResult, + JITDylib &JD, + std::vector DFSLinkOrder); + + void getInitializersLookupPhase(SendInitializerSequenceFn SendResult, + JITDylib &JD); + + void rt_getInitializers(SendInitializerSequenceFn SendResult, + StringRef JDName); + + void rt_getDeinitializers(SendDeinitializerSequenceFn SendResult, + ExecutorAddress Handle); + + void rt_lookupSymbol(SendSymbolAddressFn SendResult, ExecutorAddress Handle, + StringRef SymbolName); + + // Records the addresses of runtime symbols used by the platform. + Error bootstrapMachORuntime(JITDylib &PlatformJD); + + Error registerInitInfo(JITDylib &JD, + ArrayRef InitSections); + + Error registerPerObjectSections(const MachOPerObjectSectionsToRegister &POSR); ExecutionSession &ES; ObjectLinkingLayer &ObjLinkingLayer; - std::unique_ptr StandardSymbolsObject; + ExecutorProcessControl &EPC; + + SymbolStringPtr MachOHeaderStartSymbol; + std::atomic RuntimeBootstrapped{false}; + + ExecutorAddress orc_rt_macho_platform_bootstrap; + ExecutorAddress orc_rt_macho_platform_shutdown; + ExecutorAddress orc_rt_macho_register_object_sections; DenseMap RegisteredInitSymbols; // InitSeqs gets its own mutex to avoid locking the whole session when // aggregating data from the jitlink. - std::mutex InitSeqsMutex; + std::mutex PlatformMutex; DenseMap InitSeqs; + std::vector BootstrapPOSRs; + + DenseMap HeaderAddrToJITDylib; +}; + +namespace shared { + +using SPSMachOPerObjectSectionsToRegister = SPSTuple; + +template <> +class SPSSerializationTraits { + +public: + static size_t size(const MachOPerObjectSectionsToRegister &MOPOSR) { + return SPSMachOPerObjectSectionsToRegister::AsArgList::size( + MOPOSR.EHFrameSection); + } + + static bool serialize(SPSOutputBuffer &OB, + const MachOPerObjectSectionsToRegister &MOPOSR) { + return SPSMachOPerObjectSectionsToRegister::AsArgList::serialize( + OB, MOPOSR.EHFrameSection); + } + + static bool deserialize(SPSInputBuffer &IB, + MachOPerObjectSectionsToRegister &MOPOSR) { + return SPSMachOPerObjectSectionsToRegister::AsArgList::deserialize( + IB, MOPOSR.EHFrameSection); + } +}; + +using SPSNamedExecutorAddressRangeSequenceMap = + SPSSequence>; + +using SPSMachOJITDylibInitializers = + SPSTuple; + +using SPSMachOJITDylibInitializerSequence = + SPSSequence; + +/// Serialization traits for MachOJITDylibInitializers. +template <> +class SPSSerializationTraits { +public: + static size_t size(const MachOJITDylibInitializers &MOJDIs) { + return SPSMachOJITDylibInitializers::AsArgList::size( + MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.InitSections); + } + + static bool serialize(SPSOutputBuffer &OB, + const MachOJITDylibInitializers &MOJDIs) { + return SPSMachOJITDylibInitializers::AsArgList::serialize( + OB, MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.InitSections); + } + + static bool deserialize(SPSInputBuffer &IB, + MachOJITDylibInitializers &MOJDIs) { + return SPSMachOJITDylibInitializers::AsArgList::deserialize( + IB, MOJDIs.Name, MOJDIs.MachOHeaderAddress, MOJDIs.InitSections); + } +}; + +using SPSMachOJITDylibDeinitializers = SPSEmpty; + +using SPSMachOJITDylibDeinitializerSequence = + SPSSequence; + +template <> +class SPSSerializationTraits { +public: + static size_t size(const MachOJITDylibDeinitializers &MOJDDs) { return 0; } + + static bool serialize(SPSOutputBuffer &OB, + const MachOJITDylibDeinitializers &MOJDDs) { + return true; + } + + static bool deserialize(SPSInputBuffer &IB, + MachOJITDylibDeinitializers &MOJDDs) { + MOJDDs = MachOJITDylibDeinitializers(); + return true; + } }; +} // end namespace shared } // end namespace orc } // end namespace llvm diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 3bb83342dcdbb..4737fe80ba3ea 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index 46c6ed3063efa..9fc5fc0b902b6 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -17,7 +17,6 @@ #include "llvm/ExecutionEngine/Orc/Layer.h" #include #include -#include namespace llvm { namespace orc { diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h index 69e37f9af9e43..fedd79c93146e 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h @@ -283,7 +283,11 @@ class OrcRPCExecutorProcessControlBase : public ExecutorProcessControl { OrcRPCExecutorProcessControlBase(std::shared_ptr SSP, RPCEndpointT &EP, ErrorReporter ReportError) : ExecutorProcessControl(std::move(SSP)), - ReportError(std::move(ReportError)), EP(EP) {} + ReportError(std::move(ReportError)), EP(EP) { + using ThisT = OrcRPCExecutorProcessControlBase; + EP.template addAsyncHandler(*this, + &ThisT::runWrapperInJIT); + } void reportError(Error Err) { ReportError(std::move(Err)); } @@ -396,20 +400,32 @@ class OrcRPCExecutorProcessControlBase : public ExecutorProcessControl { /// Subclasses must call this during construction to initialize the /// TargetTriple and PageSize members. Error initializeORCRPCEPCBase() { - if (auto TripleOrErr = EP.template callB()) - TargetTriple = Triple(*TripleOrErr); - else - return TripleOrErr.takeError(); - - if (auto PageSizeOrErr = EP.template callB()) - PageSize = *PageSizeOrErr; - else - return PageSizeOrErr.takeError(); + if (auto EPI = EP.template callB()) { + this->TargetTriple = Triple(EPI->Triple); + this->PageSize = PageSize; + this->JDI = {ExecutorAddress(EPI->DispatchFuncAddr), + ExecutorAddress(EPI->DispatchCtxAddr)}; + return Error::success(); + } else + return EPI.takeError(); + } +private: + Error runWrapperInJIT( + std::function)> SendResult, + JITTargetAddress FunctionTag, std::vector ArgBuffer) { + + runJITSideWrapperFunction( + [this, SendResult = std::move(SendResult)]( + Expected R) { + if (auto Err = SendResult(std::move(R))) + ReportError(std::move(Err)); + }, + FunctionTag, + {reinterpret_cast(ArgBuffer.data()), ArgBuffer.size()}); return Error::success(); } -private: ErrorReporter ReportError; RPCEndpointT &EP; }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index c36c8bb2c1da3..78f85e827c053 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h index a2ad84647d266..854f1098d5af5 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h @@ -85,6 +85,7 @@ class SPSInputBuffer { bool skip(size_t Size) { if (Size > Remaining) return false; + Buffer += Size; Remaining -= Size; return true; } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h index ceaea1d2b20f2..2f14a1c763327 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h @@ -298,7 +298,7 @@ class WrapperFunctionAsyncHandlerHelper::serialize(std::move(Result))); }; - callAsync(std::forward(H), std::move(SendResult), Args, + callAsync(std::forward(H), std::move(SendResult), std::move(Args), ArgIndices{}); } @@ -314,9 +314,9 @@ class WrapperFunctionAsyncHandlerHelper static void callAsync(HandlerT &&H, SerializeAndSendResultT &&SerializeAndSendResult, - ArgTupleT &Args, std::index_sequence) { + ArgTupleT Args, std::index_sequence) { return std::forward(H)(std::move(SerializeAndSendResult), - std::get(Args)...); + std::move(std::get(Args))...); } }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h index 458947cc4d443..96e4341fce688 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h @@ -41,6 +41,13 @@ enum WireProtectionFlags : uint8_t { LLVM_MARK_AS_BITMASK_ENUM(WPF_Exec) }; +struct ExecutorProcessInfo { + std::string Triple; + unsigned PageSize; + JITTargetAddress DispatchFuncAddr; + JITTargetAddress DispatchCtxAddr; +}; + /// Convert from sys::Memory::ProtectionFlags inline WireProtectionFlags toWireProtectionFlags(sys::Memory::ProtectionFlags PF) { @@ -95,6 +102,41 @@ using ReleaseOrFinalizeMemRequest = namespace shared { +template <> class SerializationTypeName { +public: + static const char *getName() { return "WrapperFunctionResult"; } +}; + +template +class SerializationTraits< + ChannelT, WrapperFunctionResult, WrapperFunctionResult, + std::enable_if_t::value>> { +public: + static Error serialize(ChannelT &C, const WrapperFunctionResult &E) { + if (auto Err = serializeSeq(C, static_cast(E.size()))) + return Err; + if (E.size() == 0) + return Error::success(); + return C.appendBytes(E.data(), E.size()); + } + + static Error deserialize(ChannelT &C, WrapperFunctionResult &E) { + uint64_t Size; + if (auto Err = deserializeSeq(C, Size)) + return Err; + + WrapperFunctionResult Tmp; + char *Data = WrapperFunctionResult::allocate(Tmp, Size); + + if (auto Err = C.readBytes(Data, Size)) + return Err; + + E = std::move(Tmp); + + return Error::success(); + } +}; + template <> class SerializationTypeName { public: static const char *getName() { return "UInt8Write"; } @@ -136,9 +178,9 @@ class SerializationTypeName { static const char *getName() { return "ReleaseOrFinalizeMemRequestElement"; } }; -template <> class SerializationTypeName { +template <> class SerializationTypeName { public: - static const char *getName() { return "WrapperFunctionResult"; } + static const char *getName() { return "ExecutorProcessInfo"; } }; template @@ -234,26 +276,17 @@ class SerializationTraits -class SerializationTraits< - ChannelT, shared::WrapperFunctionResult, shared::WrapperFunctionResult, - std::enable_if_t::value>> { +class SerializationTraits { public: - static Error serialize(ChannelT &C, const shared::WrapperFunctionResult &E) { - if (auto Err = serializeSeq(C, static_cast(E.size()))) - return Err; - if (E.size() == 0) - return Error::success(); - return C.appendBytes(E.data(), E.size()); + static Error serialize(ChannelT &C, + const orcrpctpc::ExecutorProcessInfo &EPI) { + return serializeSeq(C, EPI.Triple, EPI.PageSize, EPI.DispatchFuncAddr, + EPI.DispatchCtxAddr); } - static Error deserialize(ChannelT &C, shared::WrapperFunctionResult &E) { - - uint64_t Size; - if (auto Err = deserializeSeq(C, Size)) - return Err; - - char *DataPtr = shared::WrapperFunctionResult::allocate(E, Size); - return C.readBytes(DataPtr, E.size()); + static Error deserialize(ChannelT &C, orcrpctpc::ExecutorProcessInfo &EPI) { + return deserializeSeq(C, EPI.Triple, EPI.PageSize, EPI.DispatchFuncAddr, + EPI.DispatchCtxAddr); } }; @@ -265,15 +298,11 @@ using RemoteSymbolLookupSet = std::vector>; using RemoteLookupRequest = std::pair; -class GetTargetTriple - : public shared::RPCFunction { -public: - static const char *getName() { return "GetTargetTriple"; } -}; - -class GetPageSize : public shared::RPCFunction { +class GetExecutorProcessInfo + : public shared::RPCFunction { public: - static const char *getName() { return "GetPageSize"; } + static const char *getName() { return "GetJITDispatchInfo"; } }; class ReserveMem @@ -349,7 +378,7 @@ class LookupSymbols class RunMain : public shared::RPCFunction Args)> { public: static const char *getName() { return "RunMain"; } @@ -372,18 +401,18 @@ class CloseConnection : public shared::RPCFunction { /// TargetProcessControl for a process connected via an ORC RPC Endpoint. template class OrcRPCTPCServer { +private: + using ThisT = OrcRPCTPCServer; + public: /// Create an OrcRPCTPCServer from the given endpoint. OrcRPCTPCServer(RPCEndpointT &EP) : EP(EP) { - using ThisT = OrcRPCTPCServer; TripleStr = sys::getProcessTriple(); PageSize = sys::Process::getPageSizeEstimate(); - EP.template addHandler(*this, - &ThisT::getTargetTriple); - EP.template addHandler(*this, &ThisT::getPageSize); - + EP.template addHandler( + *this, &ThisT::getExecutorProcessInfo); EP.template addHandler(*this, &ThisT::reserveMemory); EP.template addHandler(*this, &ThisT::finalizeMemory); @@ -428,9 +457,34 @@ template class OrcRPCTPCServer { return Error::success(); } + Expected + runWrapperInJIT(JITTargetAddress FunctionId, ArrayRef ArgBuffer) { + return EP.template callB( + FunctionId, + ArrayRef(reinterpret_cast(ArgBuffer.data()), + ArgBuffer.size())); + } + private: - std::string getTargetTriple() { return TripleStr; } - uint64_t getPageSize() { return PageSize; } + static shared::detail::CWrapperFunctionResult + jitDispatchViaOrcRPCTPCServer(void *Ctx, const void *FnTag, const char *Data, + size_t Size) { + assert(Ctx && "Attempt to dispatch with null context ptr"); + auto R = static_cast(Ctx)->runWrapperInJIT( + pointerToJITTargetAddress(FnTag), {Data, Size}); + if (!R) { + auto ErrMsg = toString(R.takeError()); + return shared::WrapperFunctionResult::createOutOfBandError(ErrMsg.data()) + .release(); + } + return R->release(); + } + + orcrpctpc::ExecutorProcessInfo getExecutorProcessInfo() { + return {TripleStr, static_cast(PageSize), + pointerToJITTargetAddress(jitDispatchViaOrcRPCTPCServer), + pointerToJITTargetAddress(this)}; + } template static void handleWriteUInt(const std::vector &Ws) { @@ -569,7 +623,7 @@ template class OrcRPCTPCServer { return Result; } - int32_t runMain(JITTargetAddress MainFnAddr, + int64_t runMain(JITTargetAddress MainFnAddr, const std::vector &Args) { Optional ProgramNameOverride; if (ProgramName) diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index 4118fd5566823..165e50e833eb5 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -71,14 +71,29 @@ class Attribute { enum AttrKind { // IR-Level Attributes None, ///< No attributes have been set - #define GET_ATTR_NAMES - #define ATTRIBUTE_ENUM(ENUM_NAME, OTHER) ENUM_NAME, + #define GET_ATTR_ENUM #include "llvm/IR/Attributes.inc" EndAttrKinds, ///< Sentinal value useful for loops EmptyKey, ///< Use as Empty key for DenseMap of AttrKind TombstoneKey, ///< Use as Tombstone key for DenseMap of AttrKind }; + static const unsigned NumTypeAttrKinds = LastTypeAttr - FirstTypeAttr + 1; + + static bool isEnumAttrKind(AttrKind Kind) { + return Kind >= FirstEnumAttr && Kind <= LastEnumAttr; + } + static bool isIntAttrKind(AttrKind Kind) { + return Kind >= FirstIntAttr && Kind <= LastIntAttr; + } + static bool isTypeAttrKind(AttrKind Kind) { + return Kind >= FirstTypeAttr && Kind <= LastTypeAttr; + } + + static bool canUseAsFnAttr(AttrKind Kind); + static bool canUseAsParamAttr(AttrKind Kind); + static bool canUseAsRetAttr(AttrKind Kind); + private: AttributeImpl *pImpl = nullptr; @@ -127,9 +142,6 @@ class Attribute { static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind); - /// Return true if and only if the attribute has an Argument. - static bool doesAttrKindHaveArgument(Attribute::AttrKind AttrKind); - /// Return true if the provided string matches the IR name of an attribute. /// example: "noalias" return true but not "NoAlias" static bool isExistingAttribute(StringRef Name); @@ -334,6 +346,7 @@ class AttributeSet { Type *getByRefType() const; Type *getPreallocatedType() const; Type *getInAllocaType() const; + Type *getElementType() const; std::pair> getAllocSizeArgs() const; std::pair getVScaleRangeArgs() const; std::string getAsString(bool InAttrGrp = false) const; @@ -702,6 +715,9 @@ class AttributeList { /// Return the inalloca type for the specified function parameter. Type *getParamInAllocaType(unsigned ArgNo) const; + /// Return the elementtype type for the specified function parameter. + Type *getParamElementType(unsigned ArgNo) const; + /// Get the stack alignment. MaybeAlign getStackAlignment(unsigned Index) const; @@ -802,16 +818,6 @@ template <> struct DenseMapInfo { /// value, however, is not. So this can be used as a quick way to test for /// equality, presence of attributes, etc. class AttrBuilder { - // Indices into the TypeAttrs array. - enum : unsigned { - ByValTypeIndex = 0, - StructRetTypeIndex = 1, - ByRefTypeIndex = 2, - PreallocatedTypeIndex = 3, - InAllocaTypeIndex = 4, - NumTypeIndices = 5, - }; - std::bitset Attrs; std::map, SmallString<32>, std::less<>> TargetDepAttrs; MaybeAlign Alignment; @@ -820,7 +826,7 @@ class AttrBuilder { uint64_t DerefOrNullBytes = 0; uint64_t AllocSizeArgs = 0; uint64_t VScaleRangeArgs = 0; - std::array TypeAttrs = {}; + std::array TypeAttrs = {}; Optional kindToTypeIndex(Attribute::AttrKind Kind) const; @@ -840,7 +846,8 @@ class AttrBuilder { AttrBuilder &addAttribute(Attribute::AttrKind Val) { assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); - assert(!Attribute::doesAttrKindHaveArgument(Val) && + // TODO: This should really assert isEnumAttrKind(). + assert(!Attribute::isIntAttrKind(Val) && "Adding integer attribute without adding a value!"); Attrs[Val] = true; return *this; @@ -905,20 +912,25 @@ class AttrBuilder { /// dereferenceable_or_null attribute exists (zero is returned otherwise). uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// Retrieve type for the given type attribute. + Type *getTypeAttr(Attribute::AttrKind Kind) const; + /// Retrieve the byval type. - Type *getByValType() const { return TypeAttrs[ByValTypeIndex]; } + Type *getByValType() const { return getTypeAttr(Attribute::ByVal); } /// Retrieve the sret type. - Type *getStructRetType() const { return TypeAttrs[StructRetTypeIndex]; } + Type *getStructRetType() const { return getTypeAttr(Attribute::StructRet); } /// Retrieve the byref type. - Type *getByRefType() const { return TypeAttrs[ByRefTypeIndex]; } + Type *getByRefType() const { return getTypeAttr(Attribute::ByRef); } /// Retrieve the preallocated type. - Type *getPreallocatedType() const { return TypeAttrs[PreallocatedTypeIndex]; } + Type *getPreallocatedType() const { + return getTypeAttr(Attribute::Preallocated); + } /// Retrieve the inalloca type. - Type *getInAllocaType() const { return TypeAttrs[InAllocaTypeIndex]; } + Type *getInAllocaType() const { return getTypeAttr(Attribute::InAlloca); } /// Retrieve the allocsize args, if the allocsize attribute exists. If it /// doesn't exist, pair(0, 0) is returned. diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 9f44f7960607d..99b474161df7a 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -10,228 +10,246 @@ // //===----------------------------------------------------------------------===// +/// Attribute property base class. +class AttrProperty; + +/// Can be used as function attribute. +def FnAttr : AttrProperty; + +/// Can be used as parameter attribute. +def ParamAttr : AttrProperty; + +/// Can be used as return attribute. +def RetAttr : AttrProperty; + /// Attribute base class. -class Attr { +class Attr P> { // String representation of this attribute in the IR. string AttrString = S; + list Properties = P; } /// Enum attribute. -class EnumAttr : Attr; +class EnumAttr P> : Attr; /// Int attribute. -class IntAttr : Attr; - -/// StringBool attribute. -class StrBoolAttr : Attr; +class IntAttr P> : Attr; /// Type attribute. -class TypeAttr : Attr; +class TypeAttr P> : Attr; + +/// StringBool attribute. +class StrBoolAttr : Attr; /// Target-independent enum attributes. /// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias. /// 0 means unaligned (different from align(1)). -def Alignment : IntAttr<"align">; +def Alignment : IntAttr<"align", [ParamAttr, RetAttr]>; /// The result of the function is guaranteed to point to a number of bytes that /// we can determine if we know the value of the function's arguments. -def AllocSize : IntAttr<"allocsize">; +def AllocSize : IntAttr<"allocsize", [FnAttr]>; /// inline=always. -def AlwaysInline : EnumAttr<"alwaysinline">; +def AlwaysInline : EnumAttr<"alwaysinline", [FnAttr]>; /// Function can access memory only using pointers based on its arguments. -def ArgMemOnly : EnumAttr<"argmemonly">; +def ArgMemOnly : EnumAttr<"argmemonly", [FnAttr]>; /// Callee is recognized as a builtin, despite nobuiltin attribute on its /// declaration. -def Builtin : EnumAttr<"builtin">; +def Builtin : EnumAttr<"builtin", [FnAttr]>; /// Pass structure by value. -def ByVal : TypeAttr<"byval">; +def ByVal : TypeAttr<"byval", [ParamAttr]>; /// Mark in-memory ABI type. -def ByRef : TypeAttr<"byref">; +def ByRef : TypeAttr<"byref", [ParamAttr]>; /// Parameter or return value may not contain uninitialized or poison bits. -def NoUndef : EnumAttr<"noundef">; +def NoUndef : EnumAttr<"noundef", [ParamAttr, RetAttr]>; /// Marks function as being in a cold path. -def Cold : EnumAttr<"cold">; +def Cold : EnumAttr<"cold", [FnAttr]>; /// Can only be moved to control-equivalent blocks. -def Convergent : EnumAttr<"convergent">; +def Convergent : EnumAttr<"convergent", [FnAttr]>; /// Marks function as being in a hot path and frequently called. -def Hot: EnumAttr<"hot">; +def Hot: EnumAttr<"hot", [FnAttr]>; /// Pointer is known to be dereferenceable. -def Dereferenceable : IntAttr<"dereferenceable">; +def Dereferenceable : IntAttr<"dereferenceable", [ParamAttr, RetAttr]>; /// Pointer is either null or dereferenceable. -def DereferenceableOrNull : IntAttr<"dereferenceable_or_null">; +def DereferenceableOrNull : IntAttr<"dereferenceable_or_null", + [ParamAttr, RetAttr]>; + +/// Provide pointer element type to intrinsic. +def ElementType : TypeAttr<"elementtype", [ParamAttr]>; /// Function may only access memory that is inaccessible from IR. -def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly">; +def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", [FnAttr]>; /// Function may only access memory that is either inaccessible from the IR, /// or pointed to by its pointer arguments. -def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly">; +def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly", + [FnAttr]>; /// Pass structure in an alloca. -def InAlloca : TypeAttr<"inalloca">; +def InAlloca : TypeAttr<"inalloca", [ParamAttr]>; /// Source said inlining was desirable. -def InlineHint : EnumAttr<"inlinehint">; +def InlineHint : EnumAttr<"inlinehint", [FnAttr]>; /// Force argument to be passed in register. -def InReg : EnumAttr<"inreg">; +def InReg : EnumAttr<"inreg", [ParamAttr, RetAttr]>; /// Build jump-instruction tables and replace refs. -def JumpTable : EnumAttr<"jumptable">; +def JumpTable : EnumAttr<"jumptable", [FnAttr]>; /// Function must be optimized for size first. -def MinSize : EnumAttr<"minsize">; +def MinSize : EnumAttr<"minsize", [FnAttr]>; /// Naked function. -def Naked : EnumAttr<"naked">; +def Naked : EnumAttr<"naked", [FnAttr]>; /// Nested function static chain. -def Nest : EnumAttr<"nest">; +def Nest : EnumAttr<"nest", [ParamAttr]>; /// Considered to not alias after call. -def NoAlias : EnumAttr<"noalias">; +def NoAlias : EnumAttr<"noalias", [ParamAttr, RetAttr]>; /// Callee isn't recognized as a builtin. -def NoBuiltin : EnumAttr<"nobuiltin">; +def NoBuiltin : EnumAttr<"nobuiltin", [FnAttr]>; /// Function cannot enter into caller's translation unit. -def NoCallback : EnumAttr<"nocallback">; +def NoCallback : EnumAttr<"nocallback", [FnAttr]>; /// Function creates no aliases of pointer. -def NoCapture : EnumAttr<"nocapture">; +def NoCapture : EnumAttr<"nocapture", [ParamAttr]>; /// Call cannot be duplicated. -def NoDuplicate : EnumAttr<"noduplicate">; +def NoDuplicate : EnumAttr<"noduplicate", [FnAttr]>; /// Function does not deallocate memory. -def NoFree : EnumAttr<"nofree">; +def NoFree : EnumAttr<"nofree", [FnAttr, ParamAttr]>; /// Disable implicit floating point insts. -def NoImplicitFloat : EnumAttr<"noimplicitfloat">; +def NoImplicitFloat : EnumAttr<"noimplicitfloat", [FnAttr]>; /// inline=never. -def NoInline : EnumAttr<"noinline">; +def NoInline : EnumAttr<"noinline", [FnAttr]>; /// Function is called early and/or often, so lazy binding isn't worthwhile. -def NonLazyBind : EnumAttr<"nonlazybind">; +def NonLazyBind : EnumAttr<"nonlazybind", [FnAttr]>; /// Disable merging for specified functions or call sites. -def NoMerge : EnumAttr<"nomerge">; +def NoMerge : EnumAttr<"nomerge", [FnAttr]>; /// Pointer is known to be not null. -def NonNull : EnumAttr<"nonnull">; +def NonNull : EnumAttr<"nonnull", [ParamAttr, RetAttr]>; /// The function does not recurse. -def NoRecurse : EnumAttr<"norecurse">; +def NoRecurse : EnumAttr<"norecurse", [FnAttr]>; /// Disable redzone. -def NoRedZone : EnumAttr<"noredzone">; +def NoRedZone : EnumAttr<"noredzone", [FnAttr]>; /// Mark the function as not returning. -def NoReturn : EnumAttr<"noreturn">; +def NoReturn : EnumAttr<"noreturn", [FnAttr]>; /// Function does not synchronize. -def NoSync : EnumAttr<"nosync">; +def NoSync : EnumAttr<"nosync", [FnAttr]>; /// Disable Indirect Branch Tracking. -def NoCfCheck : EnumAttr<"nocf_check">; +def NoCfCheck : EnumAttr<"nocf_check", [FnAttr]>; /// Function should not be instrumented. -def NoProfile : EnumAttr<"noprofile">; +def NoProfile : EnumAttr<"noprofile", [FnAttr]>; /// Function doesn't unwind stack. -def NoUnwind : EnumAttr<"nounwind">; +def NoUnwind : EnumAttr<"nounwind", [FnAttr]>; /// No SanitizeCoverage instrumentation. -def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage">; +def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage", [FnAttr]>; /// Null pointer in address space zero is valid. -def NullPointerIsValid : EnumAttr<"null_pointer_is_valid">; +def NullPointerIsValid : EnumAttr<"null_pointer_is_valid", [FnAttr]>; /// Select optimizations for best fuzzing signal. -def OptForFuzzing : EnumAttr<"optforfuzzing">; +def OptForFuzzing : EnumAttr<"optforfuzzing", [FnAttr]>; /// opt_size. -def OptimizeForSize : EnumAttr<"optsize">; +def OptimizeForSize : EnumAttr<"optsize", [FnAttr]>; /// Function must not be optimized. -def OptimizeNone : EnumAttr<"optnone">; +def OptimizeNone : EnumAttr<"optnone", [FnAttr]>; /// Similar to byval but without a copy. -def Preallocated : TypeAttr<"preallocated">; +def Preallocated : TypeAttr<"preallocated", [FnAttr, ParamAttr]>; /// Function does not access memory. -def ReadNone : EnumAttr<"readnone">; +def ReadNone : EnumAttr<"readnone", [FnAttr, ParamAttr]>; /// Function only reads from memory. -def ReadOnly : EnumAttr<"readonly">; +def ReadOnly : EnumAttr<"readonly", [FnAttr, ParamAttr]>; /// Return value is always equal to this argument. -def Returned : EnumAttr<"returned">; +def Returned : EnumAttr<"returned", [ParamAttr]>; /// Parameter is required to be a trivial constant. -def ImmArg : EnumAttr<"immarg">; +def ImmArg : EnumAttr<"immarg", [ParamAttr]>; /// Function can return twice. -def ReturnsTwice : EnumAttr<"returns_twice">; +def ReturnsTwice : EnumAttr<"returns_twice", [FnAttr]>; /// Safe Stack protection. -def SafeStack : EnumAttr<"safestack">; +def SafeStack : EnumAttr<"safestack", [FnAttr]>; /// Shadow Call Stack protection. -def ShadowCallStack : EnumAttr<"shadowcallstack">; +def ShadowCallStack : EnumAttr<"shadowcallstack", [FnAttr]>; /// Sign extended before/after call. -def SExt : EnumAttr<"signext">; +def SExt : EnumAttr<"signext", [ParamAttr, RetAttr]>; /// Alignment of stack for function (3 bits) stored as log2 of alignment with /// +1 bias 0 means unaligned (different from alignstack=(1)). -def StackAlignment : IntAttr<"alignstack">; +def StackAlignment : IntAttr<"alignstack", [FnAttr, ParamAttr]>; /// Function can be speculated. -def Speculatable : EnumAttr<"speculatable">; +def Speculatable : EnumAttr<"speculatable", [FnAttr]>; /// Stack protection. -def StackProtect : EnumAttr<"ssp">; +def StackProtect : EnumAttr<"ssp", [FnAttr]>; /// Stack protection required. -def StackProtectReq : EnumAttr<"sspreq">; +def StackProtectReq : EnumAttr<"sspreq", [FnAttr]>; /// Strong Stack protection. -def StackProtectStrong : EnumAttr<"sspstrong">; +def StackProtectStrong : EnumAttr<"sspstrong", [FnAttr]>; /// Function was called in a scope requiring strict floating point semantics. -def StrictFP : EnumAttr<"strictfp">; +def StrictFP : EnumAttr<"strictfp", [FnAttr]>; /// Hidden pointer to structure to return. -def StructRet : TypeAttr<"sret">; +def StructRet : TypeAttr<"sret", [ParamAttr]>; /// AddressSanitizer is on. -def SanitizeAddress : EnumAttr<"sanitize_address">; +def SanitizeAddress : EnumAttr<"sanitize_address", [FnAttr]>; /// ThreadSanitizer is on. -def SanitizeThread : EnumAttr<"sanitize_thread">; +def SanitizeThread : EnumAttr<"sanitize_thread", [FnAttr]>; /// MemorySanitizer is on. -def SanitizeMemory : EnumAttr<"sanitize_memory">; +def SanitizeMemory : EnumAttr<"sanitize_memory", [FnAttr]>; /// HWAddressSanitizer is on. -def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">; +def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress", [FnAttr]>; /// MemTagSanitizer is on. -def SanitizeMemTag : EnumAttr<"sanitize_memtag">; +def SanitizeMemTag : EnumAttr<"sanitize_memtag", [FnAttr]>; /// Speculative Load Hardening is enabled. /// @@ -239,34 +257,35 @@ def SanitizeMemTag : EnumAttr<"sanitize_memtag">; /// inlining) and a conservative merge strategy where inlining an attributed /// body will add the attribute to the caller. This ensures that code carrying /// this attribute will always be lowered with hardening enabled. -def SpeculativeLoadHardening : EnumAttr<"speculative_load_hardening">; +def SpeculativeLoadHardening : EnumAttr<"speculative_load_hardening", + [FnAttr]>; /// Argument is swift error. -def SwiftError : EnumAttr<"swifterror">; +def SwiftError : EnumAttr<"swifterror", [ParamAttr]>; /// Argument is swift self/context. -def SwiftSelf : EnumAttr<"swiftself">; +def SwiftSelf : EnumAttr<"swiftself", [ParamAttr]>; /// Argument is swift async context. -def SwiftAsync : EnumAttr<"swiftasync">; +def SwiftAsync : EnumAttr<"swiftasync", [ParamAttr]>; /// Function must be in a unwind table. -def UWTable : EnumAttr<"uwtable">; +def UWTable : EnumAttr<"uwtable", [FnAttr]>; /// Minimum/Maximum vscale value for function. -def VScaleRange : IntAttr<"vscale_range">; +def VScaleRange : IntAttr<"vscale_range", [FnAttr]>; /// Function always comes back to callsite. -def WillReturn : EnumAttr<"willreturn">; +def WillReturn : EnumAttr<"willreturn", [FnAttr]>; /// Function only writes to memory. -def WriteOnly : EnumAttr<"writeonly">; +def WriteOnly : EnumAttr<"writeonly", [FnAttr, ParamAttr]>; /// Zero extended before/after call. -def ZExt : EnumAttr<"zeroext">; +def ZExt : EnumAttr<"zeroext", [ParamAttr, RetAttr]>; /// Function is required to make Forward Progress. -def MustProgress : EnumAttr<"mustprogress">; +def MustProgress : EnumAttr<"mustprogress", [FnAttr]>; /// Target-independent string attributes. def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">; diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index bd7fa7f0caff3..8998ad0f94a95 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -1784,8 +1784,10 @@ class IRBuilderBase { return Insert(new AtomicRMWInst(Op, Ptr, Val, *Align, Ordering, SSID)); } - Value *CreateGEP(Value *Ptr, ArrayRef IdxList, - const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateGEP(Value *Ptr, ArrayRef IdxList, + const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateGEP(Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, IdxList, Name); } @@ -1804,8 +1806,10 @@ class IRBuilderBase { return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } - Value *CreateInBoundsGEP(Value *Ptr, ArrayRef IdxList, - const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateInBoundsGEP(Value *Ptr, ArrayRef IdxList, + const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateInBoundsGEP( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, IdxList, Name); @@ -1826,11 +1830,6 @@ class IRBuilderBase { return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } - Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { - return CreateGEP(Ptr->getType()->getScalarType()->getPointerElementType(), - Ptr, Idx, Name); - } - Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { if (auto *PC = dyn_cast(Ptr)) if (auto *IC = dyn_cast(Idx)) @@ -1846,7 +1845,10 @@ class IRBuilderBase { return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, + const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateConstGEP1_32( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, Idx0, Name); @@ -1908,7 +1910,10 @@ class IRBuilderBase { return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, + const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateConstGEP1_64( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, Idx0, Name); @@ -1924,8 +1929,10 @@ class IRBuilderBase { return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, - const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, + const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateConstInBoundsGEP1_64( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, Idx0, Name); @@ -1944,8 +1951,10 @@ class IRBuilderBase { return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } - Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, - const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateConstGEP2_64( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, Idx0, Idx1, Name); @@ -1964,8 +1973,10 @@ class IRBuilderBase { return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } - Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, - const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, + uint64_t Idx1, const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateConstInBoundsGEP2_64( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, Idx0, Idx1, Name); @@ -1976,7 +1987,9 @@ class IRBuilderBase { return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { + LLVM_ATTRIBUTE_DEPRECATED( + Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = ""), + "Use the version with explicit element type instead") { return CreateConstInBoundsGEP2_32( Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, 0, Idx, Name); diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h index 15275001ab4c6..80a2f5a8cd3e4 100644 --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -244,6 +244,8 @@ namespace Intrinsic { // Checks if the intrinsic name matches with its signature and if not // returns the declaration with the same signature and remangled name. + // An existing GlobalValue with the wanted name but with a wrong prototype + // or of the wrong kind will be renamed by adding ".renamed" to the name. llvm::Optional remangleIntrinsicFunction(Function *F); } // End Intrinsic namespace diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 7799321f2b160..28fcc13266b12 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -364,7 +364,7 @@ class Intrinsic ret_types, bit isTarget = false; } -// Intrinisic with default attributes (disable_default_attributes = false). +// Intrinsic with default attributes (disable_default_attributes = false). class DefaultAttrsIntrinsic ret_types, list param_types = [], list intr_properties = [], diff --git a/llvm/include/llvm/IR/IntrinsicsNVVM.td b/llvm/include/llvm/IR/IntrinsicsNVVM.td index fbee97e57c97a..5e7627843c309 100644 --- a/llvm/include/llvm/IR/IntrinsicsNVVM.td +++ b/llvm/include/llvm/IR/IntrinsicsNVVM.td @@ -225,12 +225,13 @@ class MMA_SIGNATURE { string ret = !foldl("", id_frags, a, b, !strconcat(a, ".", b.ptx_elt_type)); } -class WMMA_NAME { string signature = MMA_SIGNATURE.ret; string llvm = "llvm.nvvm.wmma." # A.geom # ".mma" + # b1op # "." # ALayout # "." # BLayout # !if(!ne(Rnd, ""), !strconcat(".", Rnd), "") @@ -241,11 +242,12 @@ class WMMA_NAME { string signature = MMA_SIGNATURE.ret; - string llvm = "llvm.nvvm.mma." - # A.geom + string llvm = "llvm.nvvm.mma" + # b1op + # "." # A.geom # "." # ALayout # "." # BLayout # !if(Satfinite, ".satfinite", "") @@ -430,6 +432,13 @@ class NVVM_WMMA_SUPPORTED frags, string layout_a, string layout_ ); } +class NVVM_MMA_B1OPS frags> { + list ret = !cond( + !eq(frags[0].ptx_elt_type, "b1") : [".xor.popc", ".and.popc"], + true: [""] + ); +} + // Returns true if this combination of layout/satf for MMA ops is supported; // false otherwise. // E.g. @@ -4460,25 +4469,27 @@ foreach layout = ["row", "col"] in { } // WMMA.MMA -class NVVM_WMMA_MMA : Intrinsic.llvm>; + WMMA_NAME.llvm>; foreach layout_a = ["row", "col"] in { foreach layout_b = ["row", "col"] in { foreach satf = [0, 1] in { foreach rnd = ["", "rn", "rz", "rm", "rp"] in { foreach op = NVVM_MMA_OPS.all_wmma_ops in { - if NVVM_WMMA_SUPPORTED.ret then { - def WMMA_NAME.record - : NVVM_WMMA_MMA; - } + foreach b1op = NVVM_MMA_B1OPS.ret in { + if NVVM_WMMA_SUPPORTED.ret then { + def WMMA_NAME.record + : NVVM_WMMA_MMA; + } + } // b1op } // op } // rnd } // satf @@ -4486,21 +4497,23 @@ foreach layout_a = ["row", "col"] in { } // layout_a // MMA -class NVVM_MMA : Intrinsic.llvm>; + MMA_NAME.llvm>; foreach layout_a = ["row", "col"] in { foreach layout_b = ["row", "col"] in { foreach satf = [0, 1] in { foreach op = NVVM_MMA_OPS.all_mma_ops in { - if NVVM_MMA_SUPPORTED.ret then { - def MMA_NAME.record - : NVVM_MMA; - } + foreach b1op = NVVM_MMA_B1OPS.ret in { + if NVVM_MMA_SUPPORTED.ret then { + def MMA_NAME.record + : NVVM_MMA; + } + } // b1op } // op } // satf } // layout_b diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td index ad6a1e8d1a7a7..f494da3944344 100644 --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -112,9 +112,45 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". : GCCBuiltin<"__builtin_vsx_scalar_insert_exp_qp">, Intrinsic <[llvm_f128_ty], [llvm_f128_ty, llvm_i64_ty], [IntrNoMem]>; + // Intrinsics defined to maintain XL compatibility + def int_ppc_tdw + : GCCBuiltin<"__builtin_ppc_tdw">, + Intrinsic <[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [ImmArg>]>; + def int_ppc_tw + : GCCBuiltin<"__builtin_ppc_tw">, + Intrinsic <[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg>]>; + def int_ppc_trapd + : GCCBuiltin<"__builtin_ppc_trapd">, + Intrinsic <[], [llvm_i64_ty], []>; + def int_ppc_trap + : GCCBuiltin<"__builtin_ppc_trap">, + Intrinsic <[], [llvm_i32_ty], []>; + def int_ppc_fcfid + : GCCBuiltin<"__builtin_ppc_fcfid">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fcfud + : GCCBuiltin<"__builtin_ppc_fcfud">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fctid + : GCCBuiltin<"__builtin_ppc_fctid">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fctidz + : GCCBuiltin<"__builtin_ppc_fctidz">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fctiw + : GCCBuiltin<"__builtin_ppc_fctiw">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fctiwz + : GCCBuiltin<"__builtin_ppc_fctiwz">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fctudz + : GCCBuiltin<"__builtin_ppc_fctudz">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fctuwz + : GCCBuiltin<"__builtin_ppc_fctuwz">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; } - let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. class PowerPC_Vec_Intrinsic ret_types, @@ -1498,12 +1534,12 @@ let TargetPrefix = "ppc" in { [IntrArgMemOnly, NoCapture>]>; def int_ppc_dcbz : GCCBuiltin<"__builtin_ppc_dcbz">, Intrinsic<[], [llvm_ptr_ty], []>; +// FIXME: __icbt is only valid for pwr8 and up. def int_ppc_icbt : GCCBuiltin<"__builtin_ppc_icbt">, Intrinsic<[], [llvm_ptr_ty], []>; // Population Count in each Byte. - def int_ppc_popcntb : GCCBuiltin<"__builtin_ppc_popcntb">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>; + def int_ppc_popcntb : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty], [IntrNoMem]>; // sync instruction (i.e. sync 0, a.k.a hwsync) def int_ppc_sync : GCCBuiltin<"__builtin_ppc_sync">, @@ -1529,9 +1565,140 @@ let TargetPrefix = "ppc" in { def int_ppc_stwcx : GCCBuiltin<"__builtin_ppc_stwcx">, Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrWriteMem]>; - def int_ppc_lwarx : GCCBuiltin<"__builtin_ppc_lwarx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; - def int_ppc_ldarx : GCCBuiltin<"__builtin_ppc_ldarx">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrNoMem]>; + // compare + def int_ppc_cmpeqb + : GCCBuiltin<"__builtin_ppc_cmpeqb">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_ppc_cmprb + : GCCBuiltin<"__builtin_ppc_cmprb">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg>]>; + def int_ppc_setb + : GCCBuiltin<"__builtin_ppc_setb">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + // multiply + def int_ppc_mulhd + : GCCBuiltin<"__builtin_ppc_mulhd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_ppc_mulhdu + : GCCBuiltin<"__builtin_ppc_mulhdu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_ppc_mulhw + : GCCBuiltin<"__builtin_ppc_mulhw">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_ppc_mulhwu + : GCCBuiltin<"__builtin_ppc_mulhwu">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_ppc_maddhd + : GCCBuiltin<"__builtin_ppc_maddhd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_ppc_maddhdu + : GCCBuiltin<"__builtin_ppc_maddhdu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + def int_ppc_maddld + : GCCBuiltin<"__builtin_ppc_maddld">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + // load + def int_ppc_load2r + : GCCBuiltin<"__builtin_ppc_load2r">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; + def int_ppc_load4r + : GCCBuiltin<"__builtin_ppc_load4r">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; + def int_ppc_load8r + : GCCBuiltin<"__builtin_ppc_load8r">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; + // store + def int_ppc_store2r + : GCCBuiltin<"__builtin_ppc_store2r">, + Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_store4r + : GCCBuiltin<"__builtin_ppc_store4r">, + Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_store8r + : GCCBuiltin<"__builtin_ppc_store8r">, + Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_insert_exp + : GCCBuiltin<"__builtin_ppc_insert_exp">, + Intrinsic <[llvm_double_ty], [llvm_double_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_ppc_extract_exp + : GCCBuiltin<"__builtin_ppc_extract_exp">, + Intrinsic <[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_extract_sig + : GCCBuiltin<"__builtin_ppc_extract_sig">, + Intrinsic <[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_mtfsb0 + : GCCBuiltin<"__builtin_ppc_mtfsb0">, + Intrinsic <[], [llvm_i32_ty], + [IntrNoMem, IntrHasSideEffects, ImmArg>]>; + def int_ppc_mtfsb1 + : GCCBuiltin<"__builtin_ppc_mtfsb1">, + Intrinsic <[], [llvm_i32_ty], + [IntrNoMem, IntrHasSideEffects, ImmArg>]>; + def int_ppc_mtfsf : + Intrinsic <[], [llvm_i32_ty, llvm_double_ty], + [IntrNoMem, IntrHasSideEffects, ImmArg>]>; + def int_ppc_mtfsfi + : GCCBuiltin<"__builtin_ppc_mtfsfi">, + Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrHasSideEffects, + ImmArg>,ImmArg>]>; + def int_ppc_fmsub + : GCCBuiltin<"__builtin_ppc_fmsub">, + Intrinsic <[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; + def int_ppc_fmsubs + : GCCBuiltin<"__builtin_ppc_fmsubs">, + Intrinsic <[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem]>; + def int_ppc_fnmadd + : GCCBuiltin<"__builtin_ppc_fnmadd">, + Intrinsic <[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; + def int_ppc_fnmadds + : GCCBuiltin<"__builtin_ppc_fnmadds">, + Intrinsic <[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem]>; + def int_ppc_fnmsub + : GCCBuiltin<"__builtin_ppc_fnmsub">, + Intrinsic <[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty], + [IntrNoMem]>; + def int_ppc_fnmsubs + : GCCBuiltin<"__builtin_ppc_fnmsubs">, + Intrinsic <[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty], + [IntrNoMem]>; + def int_ppc_fre + : GCCBuiltin<"__builtin_ppc_fre">, + Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_fres + : GCCBuiltin<"__builtin_ppc_fres">, + Intrinsic <[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; } +//===----------------------------------------------------------------------===// +// PowerPC Atomic Intrinsic Definitions. +let TargetPrefix = "ppc" in { + class AtomicRMW128Intrinsic + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_ptr_ty, llvm_i64_ty, llvm_i64_ty], + [IntrArgMemOnly, NoCapture>]>; + def int_ppc_atomicrmw_xchg_i128 : AtomicRMW128Intrinsic; + def int_ppc_atomicrmw_add_i128 : AtomicRMW128Intrinsic; + def int_ppc_atomicrmw_sub_i128 : AtomicRMW128Intrinsic; + def int_ppc_atomicrmw_and_i128 : AtomicRMW128Intrinsic; + def int_ppc_atomicrmw_or_i128 : AtomicRMW128Intrinsic; + def int_ppc_atomicrmw_xor_i128 : AtomicRMW128Intrinsic; + def int_ppc_atomicrmw_nand_i128 : AtomicRMW128Intrinsic; + def int_ppc_cmpxchg_i128 : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_ptr_ty, + llvm_i64_ty, llvm_i64_ty, + llvm_i64_ty, llvm_i64_ty], + [IntrArgMemOnly, NoCapture>]>; +} diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td index 0bd10f1b369b0..99e7ecea59374 100644 --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -186,52 +186,6 @@ def int_wasm_load64_zero : [IntrReadMem, IntrArgMemOnly], "", [SDNPMemOperand]>; -// These intrinsics do not mark their lane index arguments as immediate because -// that changes the corresponding SDNode from ISD::Constant to -// ISD::TargetConstant, which would require extra complications in the ISel -// tablegen patterns. TODO: Replace these intrinsic with normal ISel patterns -// once the load_lane instructions are merged to the proposal. -def int_wasm_load8_lane : - Intrinsic<[llvm_v16i8_ty], - [LLVMPointerType, llvm_v16i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_load16_lane : - Intrinsic<[llvm_v8i16_ty], - [LLVMPointerType, llvm_v8i16_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_load32_lane : - Intrinsic<[llvm_v4i32_ty], - [LLVMPointerType, llvm_v4i32_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_load64_lane : - Intrinsic<[llvm_v2i64_ty], - [LLVMPointerType, llvm_v2i64_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_store8_lane : - Intrinsic<[], - [LLVMPointerType, llvm_v16i8_ty, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_store16_lane : - Intrinsic<[], - [LLVMPointerType, llvm_v8i16_ty, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_store32_lane : - Intrinsic<[], - [LLVMPointerType, llvm_v4i32_ty, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; -def int_wasm_store64_lane : - Intrinsic<[], - [LLVMPointerType, llvm_v2i64_ty, llvm_i32_ty], - [IntrWriteMem, IntrArgMemOnly], - "", [SDNPMemOperand]>; - // TODO: Replace this intrinsic with normal ISel patterns once popcnt is merged // to the proposal. def int_wasm_popcnt : @@ -263,11 +217,6 @@ def int_wasm_extadd_pairwise_unsigned : [LLVMSubdivide2VectorType<0>], [IntrNoMem, IntrSpeculatable]>; -// TODO: Remove this if possible. -def int_wasm_demote_zero : - Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty], - [IntrNoMem, IntrSpeculatable]>; - //===----------------------------------------------------------------------===// // Thread-local storage intrinsics //===----------------------------------------------------------------------===// diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 035f56a72f45b..5c7e95ac45e57 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -383,6 +383,7 @@ void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); +void initializeRemoveRedundantDebugValuesPass(PassRegistry&); void initializeRenameIndependentSubregsPass(PassRegistry&); void initializeReplaceWithVeclibLegacyPass(PassRegistry &); void initializeResetMachineFunctionPass(PassRegistry&); diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h index b1d6b7fb7fd34..355f569861d8c 100644 --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -390,6 +390,10 @@ class MCAsmInfo { /// for ELF targets. Defaults to true. bool HasSingleParameterDotFile = true; + /// True if the target has a four strings .file directive, strings seperated + /// by comma. Defaults to false. + bool HasFourStringsDotFile = false; + /// True if the target has a .ident directive, this is true for ELF targets. /// Defaults to false. bool HasIdentDirective = false; @@ -729,6 +733,7 @@ class MCAsmInfo { bool hasFunctionAlignment() const { return HasFunctionAlignment; } bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasFourStringsDotFile() const { return HasFourStringsDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } bool hasAltEntry() const { return HasAltEntry; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index a0169c4c82280..dcdee2b5774b1 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -184,6 +184,8 @@ class MCObjectStreamer : public MCStreamer { void emitNops(int64_t NumBytes, int64_t ControlledNopLength, SMLoc Loc) override; void emitFileDirective(StringRef Filename) override; + void emitFileDirective(StringRef Filename, StringRef CompilerVerion, + StringRef TimeStamp, StringRef Description) override; void emitAddrsig() override; void emitAddrsigSym(const MCSymbol *Sym) override; diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h index 56188b7ebaec7..c9b3ab3256da8 100644 --- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -202,8 +202,8 @@ class MCAsmParser { /// Parse MS-style inline assembly. virtual bool parseMSInlineAsm( - void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, - unsigned &NumInputs, SmallVectorImpl> &OpDecls, + std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, + SmallVectorImpl> &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index d6ed2111ce8b4..fd326ff187124 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -854,6 +854,10 @@ class MCStreamer { /// "foo.c"' assembler directive. virtual void emitFileDirective(StringRef Filename); + /// Emit ".file assembler diretive with additioal info. + virtual void emitFileDirective(StringRef Filename, StringRef CompilerVerion, + StringRef TimeStamp, StringRef Description); + /// Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. virtual void emitIdent(StringRef IdentString) {} diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 4aabd93dbaffd..fae3e2cd2e0bd 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -107,12 +107,6 @@ class PipelineTuningOptions { /// is that of the flag: `-forget-scev-loop-unroll`. bool ForgetAllSCEVInLoopUnroll; - /// Tuning option to enable/disable coroutine intrinsic lowering. Its default - /// value is false. Frontends such as Clang may enable this conditionally. For - /// example, Clang enables this option if the flags `-std=c++2a` or above, or - /// `-fcoroutines-ts`, have been specified. - bool Coroutines; - /// Tuning option to cap the number of calls to retrive clobbering accesses in /// MemorySSA, in LICM. unsigned LicmMssaOptCap; diff --git a/llvm/include/llvm/Support/AArch64TargetParser.def b/llvm/include/llvm/Support/AArch64TargetParser.def index eb333f299d4fc..ae2fc673c54ef 100644 --- a/llvm/include/llvm/Support/AArch64TargetParser.def +++ b/llvm/include/llvm/Support/AArch64TargetParser.def @@ -110,6 +110,9 @@ AARCH64_ARCH_EXT_NAME("ls64", AArch64::AEK_LS64, "+ls64", "-ls64 AARCH64_ARCH_EXT_NAME("brbe", AArch64::AEK_BRBE, "+brbe", "-brbe") AARCH64_ARCH_EXT_NAME("pauth", AArch64::AEK_PAUTH, "+pauth", "-pauth") AARCH64_ARCH_EXT_NAME("flagm", AArch64::AEK_FLAGM, "+flagm", "-flagm") +AARCH64_ARCH_EXT_NAME("sme", AArch64::AEK_SME, "+sme", "-sme") +AARCH64_ARCH_EXT_NAME("sme-f64", AArch64::AEK_SMEF64, "+sme-f64", "-sme-f64") +AARCH64_ARCH_EXT_NAME("sme-i64", AArch64::AEK_SMEI64, "+sme-i64", "-sme-i64") #undef AARCH64_ARCH_EXT_NAME #ifndef AARCH64_CPU_NAME diff --git a/llvm/include/llvm/Support/AArch64TargetParser.h b/llvm/include/llvm/Support/AArch64TargetParser.h index 5772c03b0956d..131a58412db65 100644 --- a/llvm/include/llvm/Support/AArch64TargetParser.h +++ b/llvm/include/llvm/Support/AArch64TargetParser.h @@ -66,6 +66,9 @@ enum ArchExtKind : uint64_t { AEK_BRBE = 1ULL << 34, AEK_PAUTH = 1ULL << 35, AEK_FLAGM = 1ULL << 36, + AEK_SME = 1ULL << 37, + AEK_SMEF64 = 1ULL << 38, + AEK_SMEI64 = 1ULL << 39, }; enum class ArchKind { diff --git a/llvm/include/llvm/Support/ARMAttributeParser.h b/llvm/include/llvm/Support/ARMAttributeParser.h index bf85ea14cfe33..5d12b7e08d580 100644 --- a/llvm/include/llvm/Support/ARMAttributeParser.h +++ b/llvm/include/llvm/Support/ARMAttributeParser.h @@ -71,9 +71,9 @@ class ARMAttributeParser : public ELFAttributeParser { public: ARMAttributeParser(ScopedPrinter *sw) - : ELFAttributeParser(sw, ARMBuildAttrs::ARMAttributeTags, "aeabi") {} + : ELFAttributeParser(sw, ARMBuildAttrs::getARMAttributeTags(), "aeabi") {} ARMAttributeParser() - : ELFAttributeParser(ARMBuildAttrs::ARMAttributeTags, "aeabi") {} + : ELFAttributeParser(ARMBuildAttrs::getARMAttributeTags(), "aeabi") {} }; } diff --git a/llvm/include/llvm/Support/ARMBuildAttributes.h b/llvm/include/llvm/Support/ARMBuildAttributes.h index 5a06fd6ca7be7..37c37522fd266 100644 --- a/llvm/include/llvm/Support/ARMBuildAttributes.h +++ b/llvm/include/llvm/Support/ARMBuildAttributes.h @@ -23,7 +23,7 @@ namespace llvm { namespace ARMBuildAttrs { -extern const TagNameMap ARMAttributeTags; +const TagNameMap &getARMAttributeTags(); enum SpecialAttr { // This is for the .cpu asm attr. It translates into one or more diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h index bcbc4f993d513..14d7e21f78b23 100644 --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -202,7 +202,7 @@ class OptionCategory { }; // The general Option Category (used as default category). -extern OptionCategory GeneralCategory; +OptionCategory &getGeneralCategory(); //===----------------------------------------------------------------------===// // SubCommand class @@ -342,7 +342,7 @@ class Option { : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), FullyInitialized(false), Position(0), AdditionalVals(0) { - Categories.push_back(&GeneralCategory); + Categories.push_back(&getGeneralCategory()); } inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } diff --git a/llvm/include/llvm/Support/RISCVAttributeParser.h b/llvm/include/llvm/Support/RISCVAttributeParser.h index 3e629419a7e9b..305adffbe851e 100644 --- a/llvm/include/llvm/Support/RISCVAttributeParser.h +++ b/llvm/include/llvm/Support/RISCVAttributeParser.h @@ -27,9 +27,9 @@ class RISCVAttributeParser : public ELFAttributeParser { public: RISCVAttributeParser(ScopedPrinter *sw) - : ELFAttributeParser(sw, RISCVAttrs::RISCVAttributeTags, "riscv") {} + : ELFAttributeParser(sw, RISCVAttrs::getRISCVAttributeTags(), "riscv") {} RISCVAttributeParser() - : ELFAttributeParser(RISCVAttrs::RISCVAttributeTags, "riscv") {} + : ELFAttributeParser(RISCVAttrs::getRISCVAttributeTags(), "riscv") {} }; } // namespace llvm diff --git a/llvm/include/llvm/Support/RISCVAttributes.h b/llvm/include/llvm/Support/RISCVAttributes.h index caded9519b668..a8ce8f4d8daf4 100644 --- a/llvm/include/llvm/Support/RISCVAttributes.h +++ b/llvm/include/llvm/Support/RISCVAttributes.h @@ -22,7 +22,7 @@ namespace llvm { namespace RISCVAttrs { -extern const TagNameMap RISCVAttributeTags; +const TagNameMap &getRISCVAttributeTags(); enum AttrType : unsigned { // Attribute types in ELF/.riscv.attributes. diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h index fe800e3240470..0dfe1245f7d6e 100644 --- a/llvm/include/llvm/Support/ScopedPrinter.h +++ b/llvm/include/llvm/Support/ScopedPrinter.h @@ -32,8 +32,9 @@ template struct EnumEntry { // "Advanced Micro Devices X86-64" on GNU style StringRef AltName; T Value; - EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {} - EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {} + constexpr EnumEntry(StringRef N, StringRef A, T V) + : Name(N), AltName(A), Value(V) {} + constexpr EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {} }; struct HexNumber { diff --git a/llvm/include/llvm/Support/WithColor.h b/llvm/include/llvm/Support/WithColor.h index 1908c6eb8ea32..e772ea667f4f6 100644 --- a/llvm/include/llvm/Support/WithColor.h +++ b/llvm/include/llvm/Support/WithColor.h @@ -20,7 +20,7 @@ namespace cl { class OptionCategory; } -extern cl::OptionCategory ColorCategory; +extern cl::OptionCategory &getColorCategory(); // Symbolic names for various syntax elements. enum class HighlightColor { diff --git a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h index db8206cf2e3d9..757a3c0c8a712 100644 --- a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h +++ b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h @@ -116,6 +116,8 @@ enum attributeBits { ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \ ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \ ENUM_ENTRY(IC_VEX_OPSIZE, 2, "requires VEX and the OpSize prefix") \ + ENUM_ENTRY(IC_64BIT_VEX_OPSIZE, 4, "requires 64-bit mode and VEX") \ + ENUM_ENTRY(IC_64BIT_VEX_OPSIZE_ADSIZE, 5, "requires 64-bit mode, VEX, and AdSize")\ ENUM_ENTRY(IC_VEX_W, 3, "requires VEX and the W prefix") \ ENUM_ENTRY(IC_VEX_W_XS, 4, "requires VEX, W, and XS prefix") \ ENUM_ENTRY(IC_VEX_W_XD, 4, "requires VEX, W, and XD prefix") \ diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 7d10464e59a3c..6829f6c231744 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -177,7 +177,9 @@ enum class ChangeStatus { }; ChangeStatus operator|(ChangeStatus l, ChangeStatus r); +ChangeStatus &operator|=(ChangeStatus &l, ChangeStatus r); ChangeStatus operator&(ChangeStatus l, ChangeStatus r); +ChangeStatus &operator&=(ChangeStatus &l, ChangeStatus r); enum class DepClassTy { REQUIRED, ///< The target cannot be valid if the source is not. @@ -1585,7 +1587,13 @@ struct Attributor { Function *F = I->getFunction(); auto &ORE = OREGetter.getValue()(F); - ORE.emit([&]() { return RemarkCB(RemarkKind(PassName, RemarkName, I)); }); + if (RemarkName.startswith("OMP")) + ORE.emit([&]() { + return RemarkCB(RemarkKind(PassName, RemarkName, I)) + << " [" << RemarkName << "]"; + }); + else + ORE.emit([&]() { return RemarkCB(RemarkKind(PassName, RemarkName, I)); }); } /// Emit a remark on a function. @@ -1597,7 +1605,13 @@ struct Attributor { auto &ORE = OREGetter.getValue()(F); - ORE.emit([&]() { return RemarkCB(RemarkKind(PassName, RemarkName, F)); }); + if (RemarkName.startswith("OMP")) + ORE.emit([&]() { + return RemarkCB(RemarkKind(PassName, RemarkName, F)) + << " [" << RemarkName << "]"; + }); + else + ORE.emit([&]() { return RemarkCB(RemarkKind(PassName, RemarkName, F)); }); } /// Helper struct used in the communication between an abstract attribute (AA) @@ -4186,9 +4200,12 @@ struct AACallEdges : public StateWrapper, /// Get the optimistic edges. virtual const SetVector &getOptimisticEdges() const = 0; - /// Is there in this function call with a unknown Callee. + /// Is there any call with a unknown callee. virtual bool hasUnknownCallee() const = 0; + /// Is there any call with a unknown callee, excluding any inline asm. + virtual bool hasNonAsmUnknownCallee() const = 0; + /// Iterator for exploring the call graph. AACallEdgeIterator optimisticEdgesBegin() const override { return AACallEdgeIterator(A, getOptimisticEdges().begin()); diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h index 7da0bf8c441fa..56cc889221036 100644 --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h @@ -14,6 +14,9 @@ #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERCOMMON_H #define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERCOMMON_H +#include "llvm/Analysis/CFG.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Module.h" @@ -44,6 +47,47 @@ class InterestingMemoryOperand { Value *getPtr() { return PtrUse->get(); } }; +// For an alloca valid between lifetime markers Start and End, call the +// Callback for all possible exits out of the lifetime in the containing +// function, which can return from the instructions in RetVec. +// +// Returns whether End was the only possible exit. If it wasn't, the caller +// should remove End to ensure that work done at the other exits does not +// happen outside of the lifetime. +template +bool forAllReachableExits(DominatorTree *DT, PostDominatorTree *PDT, + const Instruction *Start, Instruction *End, + const SmallVectorImpl &RetVec, + F Callback) { + // We need to ensure that if we tag some object, we certainly untag it + // before the function exits. + if (PDT != nullptr && PDT->dominates(End, Start)) { + Callback(End); + } else { + SmallVector ReachableRetVec; + unsigned NumCoveredExits = 0; + for (auto &RI : RetVec) { + if (!isPotentiallyReachable(Start, RI, nullptr, DT)) + continue; + ReachableRetVec.push_back(RI); + if (DT != nullptr && DT->dominates(End, RI)) + ++NumCoveredExits; + } + // If there's a mix of covered and non-covered exits, just put the untag + // on exits, so we avoid the redundancy of untagging twice. + if (NumCoveredExits == ReachableRetVec.size()) { + Callback(End); + } else { + for (auto &RI : ReachableRetVec) + Callback(RI); + // We may have inserted untag outside of the lifetime interval. + // Signal the caller to remove the lifetime end call for this alloca. + return false; + } + } + return true; +} + } // namespace llvm #endif diff --git a/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h index 33c1faaeee0bb..c1a9ab475eadd 100644 --- a/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h +++ b/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h @@ -61,9 +61,11 @@ namespace llvm { /// not currently implement that in any mode. class SimpleLoopUnswitchPass : public PassInfoMixin { bool NonTrivial; + bool Trivial; public: - SimpleLoopUnswitchPass(bool NonTrivial = false) : NonTrivial(NonTrivial) {} + SimpleLoopUnswitchPass(bool NonTrivial = false, bool Trivial = true) + : NonTrivial(NonTrivial), Trivial(Trivial) {} PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U); diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h index 929db306e4ba2..3e5f3d5313bb3 100644 --- a/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -185,8 +185,7 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl &Returns, const char *NameSuffix = "", - ClonedCodeInfo *CodeInfo = nullptr, - Instruction *TheCall = nullptr); + ClonedCodeInfo *CodeInfo = nullptr); /// This class captures the data input to the InlineFunction call, and records /// the auxiliary results produced by it. diff --git a/llvm/lib/Analysis/AssumeBundleQueries.cpp b/llvm/lib/Analysis/AssumeBundleQueries.cpp index 519d27aa3fb7a..dee044346f025 100644 --- a/llvm/lib/Analysis/AssumeBundleQueries.cpp +++ b/llvm/lib/Analysis/AssumeBundleQueries.cpp @@ -44,7 +44,7 @@ bool llvm::hasAttributeInAssume(AssumeInst &Assume, Value *IsOn, StringRef AttrName, uint64_t *ArgVal) { assert(Attribute::isExistingAttribute(AttrName) && "this attribute doesn't exist"); - assert((ArgVal == nullptr || Attribute::doesAttrKindHaveArgument( + assert((ArgVal == nullptr || Attribute::isIntAttrKind( Attribute::getAttrKindFromName(AttrName))) && "requested value for an attribute that has no argument"); if (Assume.bundle_op_infos().empty()) diff --git a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp index 037f0091f0848..e4e45b3076beb 100644 --- a/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp +++ b/llvm/lib/Analysis/BlockFrequencyInfoImpl.cpp @@ -48,7 +48,7 @@ cl::opt CheckBFIUnknownBlockQueries( "for debugging missed BFI updates")); cl::opt UseIterativeBFIInference( - "use-iterative-bfi-inference", cl::init(false), cl::Hidden, + "use-iterative-bfi-inference", cl::init(false), cl::Hidden, cl::ZeroOrMore, cl::desc("Apply an iterative post-processing to infer correct BFI counts")); cl::opt IterativeBFIMaxIterationsPerBlock( diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp index 798d0785de010..aa6b93fe3f07c 100644 --- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp +++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp @@ -1105,26 +1105,6 @@ isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const { return getEdgeProbability(Src, Dst) > BranchProbability(4, 5); } -const BasicBlock * -BranchProbabilityInfo::getHotSucc(const BasicBlock *BB) const { - auto MaxProb = BranchProbability::getZero(); - const BasicBlock *MaxSucc = nullptr; - - for (const auto *Succ : successors(BB)) { - auto Prob = getEdgeProbability(BB, Succ); - if (Prob > MaxProb) { - MaxProb = Prob; - MaxSucc = Succ; - } - } - - // Hot probability is at least 4/5 = 80% - if (MaxProb > BranchProbability(4, 5)) - return MaxSucc; - - return nullptr; -} - /// Get the raw edge probability for the edge. If can't find it, return a /// default probability 1/N where N is the number of successors. Here an edge is /// specified using PredBlock and an diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index f11cce38406ad..9564cfb2aa454 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -3553,6 +3553,16 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst, const SCEV *DstSCEV = SE->getSCEV(DstPtr); LLVM_DEBUG(dbgs() << " SrcSCEV = " << *SrcSCEV << "\n"); LLVM_DEBUG(dbgs() << " DstSCEV = " << *DstSCEV << "\n"); + if (SE->getPointerBase(SrcSCEV) != SE->getPointerBase(DstSCEV)) { + // If two pointers have different bases, trying to analyze indexes won't + // work; we can't compare them to each other. This can happen, for example, + // if one is produced by an LCSSA PHI node. + // + // We check this upfront so we don't crash in cases where getMinusSCEV() + // returns a SCEVCouldNotCompute. + LLVM_DEBUG(dbgs() << "can't analyze SCEV with different pointer base\n"); + return std::make_unique(Src, Dst); + } Pair[0].Src = SrcSCEV; Pair[0].Dst = DstSCEV; diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index 13411267c58f7..0a0122d8ceda2 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -199,9 +199,9 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr, const SCEV *ScStart; const SCEV *ScEnd; - if (SE->isLoopInvariant(Sc, Lp)) + if (SE->isLoopInvariant(Sc, Lp)) { ScStart = ScEnd = Sc; - else { + } else { const SCEVAddRecExpr *AR = dyn_cast(Sc); assert(AR && "Invalid addrec expression"); const SCEV *Ex = PSE.getBackedgeTakenCount(); @@ -222,13 +222,13 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr, ScStart = SE->getUMinExpr(ScStart, ScEnd); ScEnd = SE->getUMaxExpr(AR->getStart(), ScEnd); } - // Add the size of the pointed element to ScEnd. - auto &DL = Lp->getHeader()->getModule()->getDataLayout(); - Type *IdxTy = DL.getIndexType(Ptr->getType()); - const SCEV *EltSizeSCEV = - SE->getStoreSizeOfExpr(IdxTy, Ptr->getType()->getPointerElementType()); - ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV); } + // Add the size of the pointed element to ScEnd. + auto &DL = Lp->getHeader()->getModule()->getDataLayout(); + Type *IdxTy = DL.getIndexType(Ptr->getType()); + const SCEV *EltSizeSCEV = + SE->getStoreSizeOfExpr(IdxTy, Ptr->getType()->getPointerElementType()); + ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV); Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, Sc); } diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index c9612ec54e0a9..cb37958aca4dd 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -533,8 +533,7 @@ bool SCEVUnknown::isSizeOf(Type *&AllocTy) const { CE->getNumOperands() == 2) if (ConstantInt *CI = dyn_cast(CE->getOperand(1))) if (CI->isOne()) { - AllocTy = cast(CE->getOperand(0)->getType()) - ->getElementType(); + AllocTy = cast(CE)->getSourceElementType(); return true; } @@ -547,8 +546,7 @@ bool SCEVUnknown::isAlignOf(Type *&AllocTy) const { if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) if (CE->getOpcode() == Instruction::GetElementPtr && CE->getOperand(0)->isNullValue()) { - Type *Ty = - cast(CE->getOperand(0)->getType())->getElementType(); + Type *Ty = cast(CE)->getSourceElementType(); if (StructType *STy = dyn_cast(Ty)) if (!STy->isPacked() && CE->getNumOperands() == 3 && @@ -574,8 +572,7 @@ bool SCEVUnknown::isOffsetOf(Type *&CTy, Constant *&FieldNo) const { CE->getNumOperands() == 3 && CE->getOperand(0)->isNullValue() && CE->getOperand(1)->isNullValue()) { - Type *Ty = - cast(CE->getOperand(0)->getType())->getElementType(); + Type *Ty = cast(CE)->getSourceElementType(); // Ignore vector types here so that ScalarEvolutionExpander doesn't // emit getelementptrs that index into vectors. if (Ty->isStructTy() || Ty->isArrayTy()) { @@ -8795,13 +8792,12 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) { if (C2->getType()->isPointerTy()) return nullptr; - if (PointerType *PTy = dyn_cast(C->getType())) { - if (PTy->getElementType()->isStructTy()) - C2 = ConstantExpr::getIntegerCast( - C2, Type::getInt32Ty(C->getContext()), true); - C = ConstantExpr::getGetElementPtr(PTy->getElementType(), C, C2); - } else + if (C->getType()->isPointerTy()) { + C = ConstantExpr::getGetElementPtr(Type::getInt8Ty(C->getContext()), + C, C2); + } else { C = ConstantExpr::getAdd(C, C2); + } } return C; } @@ -9822,7 +9818,7 @@ bool ScalarEvolution::isKnownNonPositive(const SCEV *S) { } bool ScalarEvolution::isKnownNonZero(const SCEV *S) { - return isKnownNegative(S) || isKnownPositive(S); + return getUnsignedRangeMin(S) != 0; } std::pair @@ -11519,11 +11515,13 @@ bool ScalarEvolution::canIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, return (std::move(MinValue) + MaxStrideMinusOne).ugt(MinRHS); } -const SCEV *ScalarEvolution::computeBECount(const SCEV *Delta, - const SCEV *Step) { - const SCEV *One = getOne(Step->getType()); - Delta = getAddExpr(Delta, getMinusSCEV(Step, One)); - return getUDivExpr(Delta, Step); +const SCEV *ScalarEvolution::getUDivCeilSCEV(const SCEV *N, const SCEV *D) { + // umin(N, 1) + floor((N - umin(N, 1)) / D) + // This is equivalent to "1 + floor((N - 1) / D)" for N != 0. The umin + // expression fixes the case of N=0. + const SCEV *MinNOne = getUMinExpr(N, getOne(N->getType())); + const SCEV *NMinusOne = getMinusSCEV(N, MinNOne); + return getAddExpr(MinNOne, getUDivExpr(NMinusOne, D)); } const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start, @@ -11562,8 +11560,8 @@ const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start, APInt MaxEnd = IsSigned ? APIntOps::smin(getSignedRangeMax(End), Limit) : APIntOps::umin(getUnsignedRangeMax(End), Limit); - MaxBECount = computeBECount(getConstant(MaxEnd - MinStart) /* Delta */, - getConstant(StrideForMaxBECount) /* Step */); + MaxBECount = getUDivCeilSCEV(getConstant(MaxEnd - MinStart) /* Delta */, + getConstant(StrideForMaxBECount) /* Step */); return MaxBECount; } @@ -11644,6 +11642,36 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, if (PredicatedIV || !NoWrap || isKnownNonPositive(Stride) || !loopIsFiniteByAssumption(L)) return getCouldNotCompute(); + + // We allow a potentially zero stride, but we need to divide by stride + // below. Since the loop can't be infinite and this check must control + // the sole exit, we can infer the exit must be taken on the first + // iteration (e.g. backedge count = 0) if the stride is zero. Given that, + // we know the numerator in the divides below must be zero, so we can + // pick an arbitrary non-zero value for the denominator (e.g. stride) + // and produce the right result. + // FIXME: Handle the case where Stride is poison? + auto wouldZeroStrideBeUB = [&]() { + // If RHS isn't loop invariant, bail out for now. This isn't necessary + // for the proof, but isLoopEntryGuardedByCond only works on + // loop-invariant values. + if (!isLoopInvariant(RHS, L)) + return false; + + // Proof by contradiction. Suppose the stride were zero. If we can + // prove that the backedge *is* taken on the first iteration, then since + // we know this condition controls the sole exit, we must have an + // infinite loop. We can't have a (well defined) infinite loop per + // check just above. + // Note: The (Start - Stride) term is used to get the start' term from + // (start' + stride,+,stride). Remember that we only care about the + // result of this expression when stride == 0 at runtime. + auto *StartIfZero = getMinusSCEV(IV->getStart(), Stride); + return isLoopEntryGuardedByCond(L, Cond, StartIfZero, RHS); + }; + if (!isKnownNonZero(Stride) && !wouldZeroStrideBeUB()) { + Stride = getUMaxExpr(Stride, getOne(Stride->getType())); + } } else if (!Stride->isOne() && !NoWrap) { auto isUBOnWrap = [&]() { // Can we prove this loop *must* be UB if overflow of IV occurs? @@ -11704,7 +11732,6 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, return RHS; } - const SCEV *End = RHS; // When the RHS is not invariant, we do not know the end bound of the loop and // cannot calculate the ExactBECount needed by ExitLimit. However, we can // calculate the MaxBECount, given the start, stride and max value for the end @@ -11716,38 +11743,172 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS, return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount, false /*MaxOrZero*/, Predicates); } - // If the backedge is taken at least once, then it will be taken - // (End-Start)/Stride times (rounded up to a multiple of Stride), where Start - // is the LHS value of the less-than comparison the first time it is evaluated - // and End is the RHS. - const SCEV *BECountIfBackedgeTaken = - computeBECount(getMinusSCEV(End, Start), Stride); - // If the loop entry is guarded by the result of the backedge test of the - // first loop iteration, then we know the backedge will be taken at least - // once and so the backedge taken count is as above. If not then we use the - // expression (max(End,Start)-Start)/Stride to describe the backedge count, - // as if the backedge is taken at least once max(End,Start) is End and so the - // result is as above, and if not max(End,Start) is Start so we get a backedge - // count of zero. - const SCEV *BECount; - if (isLoopEntryGuardedByCond(L, Cond, getMinusSCEV(OrigStart, Stride), OrigRHS)) - BECount = BECountIfBackedgeTaken; - else { + + // We use the expression (max(End,Start)-Start)/Stride to describe the + // backedge count, as if the backedge is taken at least once max(End,Start) + // is End and so the result is as above, and if not max(End,Start) is Start + // so we get a backedge count of zero. + const SCEV *BECount = nullptr; + auto *StartMinusStride = getMinusSCEV(OrigStart, Stride); + // Can we prove (max(RHS,Start) > Start - Stride? + if (isLoopEntryGuardedByCond(L, Cond, StartMinusStride, Start) && + isLoopEntryGuardedByCond(L, Cond, StartMinusStride, RHS)) { + // In this case, we can use a refined formula for computing backedge taken + // count. The general formula remains: + // "End-Start /uceiling Stride" where "End = max(RHS,Start)" + // We want to use the alternate formula: + // "((End - 1) - (Start - Stride)) /u Stride" + // Let's do a quick case analysis to show these are equivalent under + // our precondition that max(RHS,Start) > Start - Stride. + // * For RHS <= Start, the backedge-taken count must be zero. + // "((End - 1) - (Start - Stride)) /u Stride" reduces to + // "((Start - 1) - (Start - Stride)) /u Stride" which simplies to + // "Stride - 1 /u Stride" which is indeed zero for all non-zero values + // of Stride. For 0 stride, we've use umin(1,Stride) above, reducing + // this to the stride of 1 case. + // * For RHS >= Start, the backedge count must be "RHS-Start /uceil Stride". + // "((End - 1) - (Start - Stride)) /u Stride" reduces to + // "((RHS - 1) - (Start - Stride)) /u Stride" reassociates to + // "((RHS - (Start - Stride) - 1) /u Stride". + // Our preconditions trivially imply no overflow in that form. + const SCEV *MinusOne = getMinusOne(Stride->getType()); + const SCEV *Numerator = + getMinusSCEV(getAddExpr(RHS, MinusOne), StartMinusStride); + if (!isa(Numerator)) { + BECount = getUDivExpr(Numerator, Stride); + } + } + + const SCEV *BECountIfBackedgeTaken = nullptr; + if (!BECount) { + auto canProveRHSGreaterThanEqualStart = [&]() { + auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; + if (isLoopEntryGuardedByCond(L, CondGE, OrigRHS, OrigStart)) + return true; + + // (RHS > Start - 1) implies RHS >= Start. + // * "RHS >= Start" is trivially equivalent to "RHS > Start - 1" if + // "Start - 1" doesn't overflow. + // * For signed comparison, if Start - 1 does overflow, it's equal + // to INT_MAX, and "RHS >s INT_MAX" is trivially false. + // * For unsigned comparison, if Start - 1 does overflow, it's equal + // to UINT_MAX, and "RHS >u UINT_MAX" is trivially false. + // + // FIXME: Should isLoopEntryGuardedByCond do this for us? + auto CondGT = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; + auto *StartMinusOne = getAddExpr(OrigStart, + getMinusOne(OrigStart->getType())); + return isLoopEntryGuardedByCond(L, CondGT, OrigRHS, StartMinusOne); + }; + // If we know that RHS >= Start in the context of loop, then we know that // max(RHS, Start) = RHS at this point. - if (isLoopEntryGuardedByCond( - L, IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, OrigRHS, OrigStart)) + const SCEV *End; + if (canProveRHSGreaterThanEqualStart()) { End = RHS; - else + } else { + // If RHS < Start, the backedge will be taken zero times. So in + // general, we can write the backedge-taken count as: + // + // RHS >= Start ? ceil(RHS - Start) / Stride : 0 + // + // We convert it to the following to make it more convenient for SCEV: + // + // ceil(max(RHS, Start) - Start) / Stride End = IsSigned ? getSMaxExpr(RHS, Start) : getUMaxExpr(RHS, Start); - BECount = computeBECount(getMinusSCEV(End, Start), Stride); + + // See what would happen if we assume the backedge is taken. This is + // used to compute MaxBECount. + BECountIfBackedgeTaken = getUDivCeilSCEV(getMinusSCEV(RHS, Start), Stride); + } + + // At this point, we know: + // + // 1. If IsSigned, Start <=s End; otherwise, Start <=u End + // 2. The index variable doesn't overflow. + // + // Therefore, we know N exists such that + // (Start + Stride * N) >= End, and computing "(Start + Stride * N)" + // doesn't overflow. + // + // Using this information, try to prove whether the addition in + // "(Start - End) + (Stride - 1)" has unsigned overflow. + const SCEV *One = getOne(Stride->getType()); + bool MayAddOverflow = [&] { + if (auto *StrideC = dyn_cast(Stride)) { + if (StrideC->getAPInt().isPowerOf2()) { + // Suppose Stride is a power of two, and Start/End are unsigned + // integers. Let UMAX be the largest representable unsigned + // integer. + // + // By the preconditions of this function, we know + // "(Start + Stride * N) >= End", and this doesn't overflow. + // As a formula: + // + // End <= (Start + Stride * N) <= UMAX + // + // Subtracting Start from all the terms: + // + // End - Start <= Stride * N <= UMAX - Start + // + // Since Start is unsigned, UMAX - Start <= UMAX. Therefore: + // + // End - Start <= Stride * N <= UMAX + // + // Stride * N is a multiple of Stride. Therefore, + // + // End - Start <= Stride * N <= UMAX - (UMAX mod Stride) + // + // Since Stride is a power of two, UMAX + 1 is divisible by Stride. + // Therefore, UMAX mod Stride == Stride - 1. So we can write: + // + // End - Start <= Stride * N <= UMAX - Stride - 1 + // + // Dropping the middle term: + // + // End - Start <= UMAX - Stride - 1 + // + // Adding Stride - 1 to both sides: + // + // (End - Start) + (Stride - 1) <= UMAX + // + // In other words, the addition doesn't have unsigned overflow. + // + // A similar proof works if we treat Start/End as signed values. + // Just rewrite steps before "End - Start <= Stride * N <= UMAX" to + // use signed max instead of unsigned max. Note that we're trying + // to prove a lack of unsigned overflow in either case. + return false; + } + } + if (Start == Stride || Start == getMinusSCEV(Stride, One)) { + // If Start is equal to Stride, (End - Start) + (Stride - 1) == End - 1. + // If !IsSigned, 0 (BECount)) + if (isa(BECount)) { MaxBECount = BECount; - else if (isa(BECountIfBackedgeTaken)) { + } else if (BECountIfBackedgeTaken && + isa(BECountIfBackedgeTaken)) { // If we know exactly how many times the backedge will be taken if it's // taken at least once, then the backedge count will either be that or // zero. @@ -11826,7 +11987,12 @@ ScalarEvolution::howManyGreaterThans(const SCEV *LHS, const SCEV *RHS, return End; } - const SCEV *BECount = computeBECount(getMinusSCEV(Start, End), Stride); + // Compute ((Start - End) + (Stride - 1)) / Stride. + // FIXME: This can overflow. Holding off on fixing this for now; + // howManyGreaterThans will hopefully be gone soon. + const SCEV *One = getOne(Stride->getType()); + const SCEV *BECount = getUDivExpr( + getAddExpr(getMinusSCEV(Start, End), getMinusSCEV(Stride, One)), Stride); APInt MaxStart = IsSigned ? getSignedRangeMax(Start) : getUnsignedRangeMax(Start); @@ -11847,8 +12013,8 @@ ScalarEvolution::howManyGreaterThans(const SCEV *LHS, const SCEV *RHS, const SCEV *MaxBECount = isa(BECount) ? BECount - : computeBECount(getConstant(MaxStart - MinEnd), - getConstant(MinStride)); + : getUDivCeilSCEV(getConstant(MaxStart - MinEnd), + getConstant(MinStride)); if (isa(MaxBECount)) MaxBECount = BECount; @@ -12417,20 +12583,12 @@ bool ScalarEvolution::getIndexExpressionsFromGEP( assert(Subscripts.empty() && Sizes.empty() && "Expected output lists to be empty on entry to this function."); assert(GEP && "getIndexExpressionsFromGEP called with a null GEP"); - Type *Ty = GEP->getPointerOperandType(); + Type *Ty = nullptr; bool DroppedFirstDim = false; for (unsigned i = 1; i < GEP->getNumOperands(); i++) { const SCEV *Expr = getSCEV(GEP->getOperand(i)); if (i == 1) { - if (auto *PtrTy = dyn_cast(Ty)) { - Ty = PtrTy->getElementType(); - } else if (auto *ArrayTy = dyn_cast(Ty)) { - Ty = ArrayTy->getElementType(); - } else { - Subscripts.clear(); - Sizes.clear(); - return false; - } + Ty = GEP->getSourceElementType(); if (auto *Const = dyn_cast(Expr)) if (Const->getValue()->isZero()) { DroppedFirstDim = true; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 5f68db84367cb..b062fb81fc8f6 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -643,6 +643,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(convergent); KEYWORD(dereferenceable); KEYWORD(dereferenceable_or_null); + KEYWORD(elementtype); KEYWORD(inaccessiblememonly); KEYWORD(inaccessiblemem_or_argmemonly); KEYWORD(inlinehint); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index f9eb805326823..1b83d220109c7 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1243,212 +1243,144 @@ bool LLParser::parseUnnamedAttrGrp() { return false; } +static Attribute::AttrKind tokenToAttribute(lltok::Kind Kind) { + switch (Kind) { +#define GET_ATTR_NAMES +#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \ + case lltok::kw_##DISPLAY_NAME: \ + return Attribute::ENUM_NAME; +#include "llvm/IR/Attributes.inc" + default: + return Attribute::None; + } +} + +bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, + bool InAttrGroup) { + if (Attribute::isTypeAttrKind(Attr)) + return parseRequiredTypeAttr(B, Lex.getKind(), Attr); + + switch (Attr) { + case Attribute::Alignment: { + MaybeAlign Alignment; + if (InAttrGroup) { + uint32_t Value = 0; + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value)) + return true; + Alignment = Align(Value); + } else { + if (parseOptionalAlignment(Alignment, true)) + return true; + } + B.addAlignmentAttr(Alignment); + return false; + } + case Attribute::StackAlignment: { + unsigned Alignment; + if (InAttrGroup) { + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here") || + parseUInt32(Alignment)) + return true; + } else { + if (parseOptionalStackAlignment(Alignment)) + return true; + } + B.addStackAlignmentAttr(Alignment); + return false; + } + case Attribute::AllocSize: { + unsigned ElemSizeArg; + Optional NumElemsArg; + if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) + return true; + B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); + return false; + } + case Attribute::VScaleRange: { + unsigned MinValue, MaxValue; + if (parseVScaleRangeArguments(MinValue, MaxValue)) + return true; + B.addVScaleRangeAttr(MinValue, MaxValue); + return false; + } + case Attribute::Dereferenceable: { + uint64_t Bytes; + if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) + return true; + B.addDereferenceableAttr(Bytes); + return false; + } + case Attribute::DereferenceableOrNull: { + uint64_t Bytes; + if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) + return true; + B.addDereferenceableOrNullAttr(Bytes); + return false; + } + default: + B.addAttribute(Attr); + Lex.Lex(); + return false; + } +} + /// parseFnAttributeValuePairs /// ::= | '=' bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, std::vector &FwdRefAttrGrps, - bool inAttrGrp, LocTy &BuiltinLoc) { + bool InAttrGrp, LocTy &BuiltinLoc) { bool HaveError = false; B.clear(); while (true) { lltok::Kind Token = Lex.getKind(); - if (Token == lltok::kw_builtin) - BuiltinLoc = Lex.getLoc(); - switch (Token) { - default: - if (!inAttrGrp) return HaveError; - return error(Lex.getLoc(), "unterminated attribute group"); - case lltok::rbrace: - // Finished. - return false; + if (Token == lltok::rbrace) + return HaveError; // Finished. + + if (Token == lltok::StringConstant) { + if (parseStringAttribute(B)) + return true; + continue; + } - case lltok::AttrGrpID: { + if (Token == lltok::AttrGrpID) { // Allow a function to reference an attribute group: // // define void @foo() #1 { ... } - if (inAttrGrp) + if (InAttrGrp) { HaveError |= error( Lex.getLoc(), "cannot have an attribute group reference in an attribute group"); - - unsigned AttrGrpNum = Lex.getUIntVal(); - if (inAttrGrp) break; - - // Save the reference to the attribute group. We'll fill it in later. - FwdRefAttrGrps.push_back(AttrGrpNum); - break; - } - // Target-dependent attributes: - case lltok::StringConstant: { - if (parseStringAttribute(B)) - return true; - continue; - } - - // Target-independent attributes: - case lltok::kw_align: { - // As a hack, we allow function alignment to be initially parsed as an - // attribute on a function declaration/definition or added to an attribute - // group and later moved to the alignment field. - MaybeAlign Alignment; - if (inAttrGrp) { - Lex.Lex(); - uint32_t Value = 0; - if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value)) - return true; - Alignment = Align(Value); } else { - if (parseOptionalAlignment(Alignment)) - return true; + // Save the reference to the attribute group. We'll fill it in later. + FwdRefAttrGrps.push_back(Lex.getUIntVal()); } - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_alignstack: { - unsigned Alignment; - if (inAttrGrp) { - Lex.Lex(); - if (parseToken(lltok::equal, "expected '=' here") || - parseUInt32(Alignment)) - return true; - } else { - if (parseOptionalStackAlignment(Alignment)) - return true; - } - B.addStackAlignmentAttr(Alignment); - continue; - } - case lltok::kw_allocsize: { - unsigned ElemSizeArg; - Optional NumElemsArg; - // inAttrGrp doesn't matter; we only support allocsize(a[, b]) - if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) - return true; - B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); - continue; - } - case lltok::kw_vscale_range: { - unsigned MinValue, MaxValue; - // inAttrGrp doesn't matter; we only support vscale_range(a[, b]) - if (parseVScaleRangeArguments(MinValue, MaxValue)) - return true; - B.addVScaleRangeAttr(MinValue, MaxValue); + Lex.Lex(); continue; } - case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; - case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break; - case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; - case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; - case lltok::kw_hot: B.addAttribute(Attribute::Hot); break; - case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; - case lltok::kw_inaccessiblememonly: - B.addAttribute(Attribute::InaccessibleMemOnly); break; - case lltok::kw_inaccessiblemem_or_argmemonly: - B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break; - case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; - case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; - case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; - case lltok::kw_mustprogress: - B.addAttribute(Attribute::MustProgress); - break; - case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; - case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; - case lltok::kw_nocallback: - B.addAttribute(Attribute::NoCallback); - break; - case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; - case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; - case lltok::kw_noimplicitfloat: - B.addAttribute(Attribute::NoImplicitFloat); break; - case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break; - case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; - case lltok::kw_nomerge: B.addAttribute(Attribute::NoMerge); break; - case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; - case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; - case lltok::kw_nosync: B.addAttribute(Attribute::NoSync); break; - case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break; - case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break; - case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; - case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; - case lltok::kw_nosanitize_coverage: - B.addAttribute(Attribute::NoSanitizeCoverage); - break; - case lltok::kw_null_pointer_is_valid: - B.addAttribute(Attribute::NullPointerIsValid); break; - case lltok::kw_optforfuzzing: - B.addAttribute(Attribute::OptForFuzzing); break; - case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; - case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returns_twice: - B.addAttribute(Attribute::ReturnsTwice); break; - case lltok::kw_speculatable: B.addAttribute(Attribute::Speculatable); break; - case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break; - case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break; - case lltok::kw_sspstrong: - B.addAttribute(Attribute::StackProtectStrong); break; - case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; - case lltok::kw_shadowcallstack: - B.addAttribute(Attribute::ShadowCallStack); break; - case lltok::kw_sanitize_address: - B.addAttribute(Attribute::SanitizeAddress); break; - case lltok::kw_sanitize_hwaddress: - B.addAttribute(Attribute::SanitizeHWAddress); break; - case lltok::kw_sanitize_memtag: - B.addAttribute(Attribute::SanitizeMemTag); break; - case lltok::kw_sanitize_thread: - B.addAttribute(Attribute::SanitizeThread); break; - case lltok::kw_sanitize_memory: - B.addAttribute(Attribute::SanitizeMemory); break; - case lltok::kw_speculative_load_hardening: - B.addAttribute(Attribute::SpeculativeLoadHardening); - break; - case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break; - case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; - case lltok::kw_willreturn: B.addAttribute(Attribute::WillReturn); break; - case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; - case lltok::kw_preallocated: { - if (parseRequiredTypeAttr(B, lltok::kw_preallocated, - Attribute::Preallocated)) - return true; - break; - } - // error handling. - case lltok::kw_inreg: - case lltok::kw_signext: - case lltok::kw_zeroext: - HaveError |= - error(Lex.getLoc(), "invalid use of attribute on a function"); - break; - case lltok::kw_byval: - case lltok::kw_dereferenceable: - case lltok::kw_dereferenceable_or_null: - case lltok::kw_inalloca: - case lltok::kw_nest: - case lltok::kw_noalias: - case lltok::kw_noundef: - case lltok::kw_nocapture: - case lltok::kw_nonnull: - case lltok::kw_returned: - case lltok::kw_sret: - case lltok::kw_swifterror: - case lltok::kw_swiftself: - case lltok::kw_swiftasync: - case lltok::kw_immarg: - case lltok::kw_byref: - HaveError |= - error(Lex.getLoc(), - "invalid use of parameter-only attribute on a function"); - break; + SMLoc Loc = Lex.getLoc(); + if (Token == lltok::kw_builtin) + BuiltinLoc = Loc; + + Attribute::AttrKind Attr = tokenToAttribute(Token); + if (Attr == Attribute::None) { + if (!InAttrGrp) + return HaveError; + return error(Lex.getLoc(), "unterminated attribute group"); } - // parsePreallocated() consumes token - if (Token != lltok::kw_preallocated) - Lex.Lex(); + if (parseEnumAttribute(Attr, B, InAttrGrp)) + return true; + + // As a hack, we allow function alignment to be initially parsed as an + // attribute on a function declaration/definition or added to an attribute + // group and later moved to the alignment field. + if (!Attribute::canUseAsFnAttr(Attr) && Attr != Attribute::Alignment) + HaveError |= error(Loc, "this attribute does not apply to functions"); } } @@ -1685,258 +1617,32 @@ bool LLParser::parseStringAttribute(AttrBuilder &B) { return false; } -/// parseOptionalParamAttrs - parse a potentially empty list of parameter -/// attributes. -bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) { +/// Parse a potentially empty list of parameter or return attributes. +bool LLParser::parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam) { bool HaveError = false; B.clear(); while (true) { lltok::Kind Token = Lex.getKind(); - switch (Token) { - default: // End of attributes. - return HaveError; - case lltok::StringConstant: { + if (Token == lltok::StringConstant) { if (parseStringAttribute(B)) return true; continue; } - case lltok::kw_align: { - MaybeAlign Alignment; - if (parseOptionalAlignment(Alignment, true)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_alignstack: { - unsigned Alignment; - if (parseOptionalStackAlignment(Alignment)) - return true; - B.addStackAlignmentAttr(Alignment); - continue; - } - case lltok::kw_byval: - if (parseRequiredTypeAttr(B, lltok::kw_byval, Attribute::ByVal)) - return true; - continue; - case lltok::kw_byref: - if (parseRequiredTypeAttr(B, lltok::kw_byref, Attribute::ByRef)) - return true; - continue; - case lltok::kw_inalloca: - if (parseRequiredTypeAttr(B, lltok::kw_inalloca, Attribute::InAlloca)) - return true; - continue; - case lltok::kw_preallocated: - if (parseRequiredTypeAttr(B, lltok::kw_preallocated, - Attribute::Preallocated)) - return true; - continue; - case lltok::kw_sret: - if (parseRequiredTypeAttr(B, lltok::kw_sret, Attribute::StructRet)) - return true; - continue; - case lltok::kw_dereferenceable: { - uint64_t Bytes; - if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) - return true; - B.addDereferenceableAttr(Bytes); - continue; - } - case lltok::kw_dereferenceable_or_null: { - uint64_t Bytes; - if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) - return true; - B.addDereferenceableOrNullAttr(Bytes); - continue; - } - case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; - case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; - case lltok::kw_noundef: - B.addAttribute(Attribute::NoUndef); - break; - case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; - case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break; - case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; - case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returned: B.addAttribute(Attribute::Returned); break; - case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; - case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break; - case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break; - case lltok::kw_swiftasync: B.addAttribute(Attribute::SwiftAsync); break; - case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; - case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; - case lltok::kw_immarg: B.addAttribute(Attribute::ImmArg); break; - - case lltok::kw_alwaysinline: - case lltok::kw_argmemonly: - case lltok::kw_builtin: - case lltok::kw_inlinehint: - case lltok::kw_jumptable: - case lltok::kw_minsize: - case lltok::kw_mustprogress: - case lltok::kw_naked: - case lltok::kw_nobuiltin: - case lltok::kw_noduplicate: - case lltok::kw_noimplicitfloat: - case lltok::kw_noinline: - case lltok::kw_nonlazybind: - case lltok::kw_nomerge: - case lltok::kw_noprofile: - case lltok::kw_noredzone: - case lltok::kw_noreturn: - case lltok::kw_nocf_check: - case lltok::kw_nounwind: - case lltok::kw_nosanitize_coverage: - case lltok::kw_optforfuzzing: - case lltok::kw_optnone: - case lltok::kw_optsize: - case lltok::kw_returns_twice: - case lltok::kw_sanitize_address: - case lltok::kw_sanitize_hwaddress: - case lltok::kw_sanitize_memtag: - case lltok::kw_sanitize_memory: - case lltok::kw_sanitize_thread: - case lltok::kw_speculative_load_hardening: - case lltok::kw_ssp: - case lltok::kw_sspreq: - case lltok::kw_sspstrong: - case lltok::kw_safestack: - case lltok::kw_shadowcallstack: - case lltok::kw_strictfp: - case lltok::kw_uwtable: - case lltok::kw_vscale_range: - HaveError |= - error(Lex.getLoc(), "invalid use of function-only attribute"); - break; - } - - Lex.Lex(); - } -} - -/// parseOptionalReturnAttrs - parse a potentially empty list of return -/// attributes. -bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) { - bool HaveError = false; - B.clear(); - - while (true) { - lltok::Kind Token = Lex.getKind(); - switch (Token) { - default: // End of attributes. + SMLoc Loc = Lex.getLoc(); + Attribute::AttrKind Attr = tokenToAttribute(Token); + if (Attr == Attribute::None) return HaveError; - case lltok::StringConstant: { - if (parseStringAttribute(B)) - return true; - continue; - } - case lltok::kw_dereferenceable: { - uint64_t Bytes; - if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) - return true; - B.addDereferenceableAttr(Bytes); - continue; - } - case lltok::kw_dereferenceable_or_null: { - uint64_t Bytes; - if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) - return true; - B.addDereferenceableOrNullAttr(Bytes); - continue; - } - case lltok::kw_align: { - MaybeAlign Alignment; - if (parseOptionalAlignment(Alignment)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; - case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; - case lltok::kw_noundef: - B.addAttribute(Attribute::NoUndef); - break; - case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; - case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; - case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; - - // error handling. - case lltok::kw_byval: - case lltok::kw_inalloca: - case lltok::kw_nest: - case lltok::kw_nocapture: - case lltok::kw_returned: - case lltok::kw_sret: - case lltok::kw_swifterror: - case lltok::kw_swiftself: - case lltok::kw_swiftasync: - case lltok::kw_immarg: - case lltok::kw_byref: - HaveError |= - error(Lex.getLoc(), "invalid use of parameter-only attribute"); - break; - case lltok::kw_alignstack: - case lltok::kw_alwaysinline: - case lltok::kw_argmemonly: - case lltok::kw_builtin: - case lltok::kw_cold: - case lltok::kw_inlinehint: - case lltok::kw_jumptable: - case lltok::kw_minsize: - case lltok::kw_mustprogress: - case lltok::kw_naked: - case lltok::kw_nobuiltin: - case lltok::kw_noduplicate: - case lltok::kw_noimplicitfloat: - case lltok::kw_noinline: - case lltok::kw_nonlazybind: - case lltok::kw_nomerge: - case lltok::kw_noprofile: - case lltok::kw_noredzone: - case lltok::kw_noreturn: - case lltok::kw_nocf_check: - case lltok::kw_nounwind: - case lltok::kw_nosanitize_coverage: - case lltok::kw_optforfuzzing: - case lltok::kw_optnone: - case lltok::kw_optsize: - case lltok::kw_returns_twice: - case lltok::kw_sanitize_address: - case lltok::kw_sanitize_hwaddress: - case lltok::kw_sanitize_memtag: - case lltok::kw_sanitize_memory: - case lltok::kw_sanitize_thread: - case lltok::kw_speculative_load_hardening: - case lltok::kw_ssp: - case lltok::kw_sspreq: - case lltok::kw_sspstrong: - case lltok::kw_safestack: - case lltok::kw_shadowcallstack: - case lltok::kw_strictfp: - case lltok::kw_uwtable: - case lltok::kw_vscale_range: - HaveError |= - error(Lex.getLoc(), "invalid use of function-only attribute"); - break; - case lltok::kw_readnone: - case lltok::kw_readonly: - HaveError |= - error(Lex.getLoc(), "invalid use of attribute on return type"); - break; - case lltok::kw_preallocated: - HaveError |= - error(Lex.getLoc(), - "invalid use of parameter-only/call site-only attribute"); - break; - } + if (parseEnumAttribute(Attr, B, /* InAttrGroup */ false)) + return true; - Lex.Lex(); + if (IsParam && !Attribute::canUseAsParamAttr(Attr)) + HaveError |= error(Loc, "this attribute does not apply to parameters"); + if (!IsParam && !Attribute::canUseAsRetAttr(Attr)) + HaveError |= error(Loc, "this attribute does not apply to return values"); } } diff --git a/llvm/lib/BinaryFormat/XCOFF.cpp b/llvm/lib/BinaryFormat/XCOFF.cpp index fd5d8568b62ff..6b11ab2ff96bc 100644 --- a/llvm/lib/BinaryFormat/XCOFF.cpp +++ b/llvm/lib/BinaryFormat/XCOFF.cpp @@ -117,7 +117,15 @@ Expected> XCOFF::parseParmsType(uint32_t Value, unsigned ParsedNum = 0; unsigned ParmsNum = FixedParmsNum + FloatingParmsNum; - while (Bits < 32 && ParsedNum < ParmsNum) { + // In the function PPCFunctionInfo::getParmsType(), when there are no vector + // parameters, the 31st bit of ParmsType is always zero even if it indicates a + // floating point parameter. The parameter type information is lost. There + // are only 8 GPRs used for parameters passing, the floating parameters + // also occupy GPRs if there are available, so the 31st bit can never be a + // fixed parameter. At the same time, we also do not know whether the zero of + // the 31st bit indicates a float or double parameter type here. Therefore, we + // ignore the 31st bit. + while (Bits < 31 && ParsedNum < ParmsNum) { if (++ParsedNum > 1) ParmsType += ", "; if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 854243ee95bc6..42e17f018a16c 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -682,9 +682,10 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { return getFnValueByID(ValNo, Ty); } - /// Upgrades old-style typeless byval or sret attributes by adding the - /// corresponding argument's pointee type. - void propagateByValSRetTypes(CallBase *CB, ArrayRef ArgsTys); + /// Upgrades old-style typeless byval/sret/inalloca attributes by adding the + /// corresponding argument's pointee type. Also upgrades intrinsics that now + /// require an elementtype attribute. + void propagateAttributeTypes(CallBase *CB, ArrayRef ArgsTys); /// Converts alignment exponent (i.e. power of two (or zero)) to the /// corresponding alignment to use. If alignment is too large, returns @@ -1385,6 +1386,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::Cold; case bitc::ATTR_KIND_CONVERGENT: return Attribute::Convergent; + case bitc::ATTR_KIND_ELEMENTTYPE: + return Attribute::ElementType; case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY: return Attribute::InaccessibleMemOnly; case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY: @@ -1599,12 +1602,16 @@ Error BitcodeReader::parseAttributeGroupBlock() { B.addStructRetAttr(nullptr); else if (Kind == Attribute::InAlloca) B.addInAllocaAttr(nullptr); - - B.addAttribute(Kind); + else if (Attribute::isEnumAttrKind(Kind)) + B.addAttribute(Kind); + else + return error("Not an enum attribute"); } else if (Record[i] == 1) { // Integer attribute Attribute::AttrKind Kind; if (Error Err = parseAttrKind(Record[++i], &Kind)) return Err; + if (!Attribute::isIntAttrKind(Kind)) + return error("Not an int attribute"); if (Kind == Attribute::Alignment) B.addAlignmentAttr(Record[++i]); else if (Kind == Attribute::StackAlignment) @@ -1642,17 +1649,10 @@ Error BitcodeReader::parseAttributeGroupBlock() { Attribute::AttrKind Kind; if (Error Err = parseAttrKind(Record[++i], &Kind)) return Err; - if (Kind == Attribute::ByVal) { - B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr); - } else if (Kind == Attribute::StructRet) { - B.addStructRetAttr(HasType ? getTypeByID(Record[++i]) : nullptr); - } else if (Kind == Attribute::ByRef) { - B.addByRefAttr(getTypeByID(Record[++i])); - } else if (Kind == Attribute::Preallocated) { - B.addPreallocatedAttr(getTypeByID(Record[++i])); - } else if (Kind == Attribute::InAlloca) { - B.addInAllocaAttr(HasType ? getTypeByID(Record[++i]) : nullptr); - } + if (!Attribute::isTypeAttrKind(Kind)) + return error("Not a type attribute"); + + B.addTypeAttr(Kind, HasType ? getTypeByID(Record[++i]) : nullptr); } } @@ -3810,7 +3810,7 @@ Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) { return Error::success(); } -void BitcodeReader::propagateByValSRetTypes(CallBase *CB, +void BitcodeReader::propagateAttributeTypes(CallBase *CB, ArrayRef ArgsTys) { for (unsigned i = 0; i != CB->arg_size(); ++i) { for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet, @@ -3839,6 +3839,19 @@ void BitcodeReader::propagateByValSRetTypes(CallBase *CB, CB->addParamAttr(i, NewAttr); } } + + switch (CB->getIntrinsicID()) { + case Intrinsic::preserve_array_access_index: + case Intrinsic::preserve_struct_access_index: + if (!CB->getAttributes().getParamElementType(0)) { + Type *ElTy = cast(ArgsTys[0])->getElementType(); + Attribute NewAttr = Attribute::get(Context, Attribute::ElementType, ElTy); + CB->addParamAttr(0, NewAttr); + } + break; + default: + break; + } } /// Lazily parse the specified function body block. @@ -4680,7 +4693,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { cast(I)->setCallingConv( static_cast(CallingConv::MaxID & CCInfo)); cast(I)->setAttributes(PAL); - propagateByValSRetTypes(cast(I), ArgsTys); + propagateAttributeTypes(cast(I), ArgsTys); break; } @@ -5319,7 +5332,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { TCK = CallInst::TCK_NoTail; cast(I)->setTailCallKind(TCK); cast(I)->setAttributes(PAL); - propagateByValSRetTypes(cast(I), ArgsTys); + propagateAttributeTypes(cast(I), ArgsTys); if (FMF.any()) { if (!isa(I)) return error("Fast-math-flags specified for call without " diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index bdb973e8e421b..da3158bcdfa48 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -630,6 +630,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_COLD; case Attribute::Hot: return bitc::ATTR_KIND_HOT; + case Attribute::ElementType: + return bitc::ATTR_KIND_ELEMENTTYPE; case Attribute::InaccessibleMemOnly: return bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY; case Attribute::InaccessibleMemOrArgMemOnly: diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index a1507a349d431..e528d33b5f8ca 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -59,6 +59,7 @@ #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/Config/config.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Comdat.h" #include "llvm/IR/Constant.h" @@ -297,11 +298,24 @@ bool AsmPrinter::doInitialization(Module &M) { // don't, this at least helps the user find where a global came from. if (MAI->hasSingleParameterDotFile()) { // .file "foo.c" + + SmallString<128> FileName; if (MAI->hasBasenameOnlyForFileDirective()) - OutStreamer->emitFileDirective( - llvm::sys::path::filename(M.getSourceFileName())); + FileName = llvm::sys::path::filename(M.getSourceFileName()); else - OutStreamer->emitFileDirective(M.getSourceFileName()); + FileName = M.getSourceFileName(); + if (MAI->hasFourStringsDotFile()) { +#ifdef PACKAGE_VENDOR + const char VerStr[] = + PACKAGE_VENDOR " " PACKAGE_NAME " version " PACKAGE_VERSION; +#else + const char VerStr[] = PACKAGE_NAME " version " PACKAGE_VERSION; +#endif + // TODO: Add timestamp and description. + OutStreamer->emitFileDirective(FileName, VerStr, "", ""); + } else { + OutStreamer->emitFileDirective(FileName); + } } GCModuleInfo *MI = getAnalysisIfAvailable(); @@ -345,7 +359,7 @@ bool AsmPrinter::doInitialization(Module &M) { } if (M.getNamedMetadata(PseudoProbeDescMetadataName)) { - PP = new PseudoProbeHandler(this, &M); + PP = new PseudoProbeHandler(this); Handlers.emplace_back(std::unique_ptr(PP), PPTimerName, PPTimerDescription, PPGroupName, PPGroupDescription); } diff --git a/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp index e8636052c54c9..35a830f416f6b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.cpp @@ -20,31 +20,6 @@ using namespace llvm; -#define DEBUG_TYPE "pseudoprobe" - -PseudoProbeHandler::~PseudoProbeHandler() = default; - -PseudoProbeHandler::PseudoProbeHandler(AsmPrinter *A, Module *M) : Asm(A) { - NamedMDNode *FuncInfo = M->getNamedMetadata(PseudoProbeDescMetadataName); - assert(FuncInfo && "Pseudo probe descriptors are missing"); - for (const auto *Operand : FuncInfo->operands()) { - const auto *MD = cast(Operand); - auto GUID = - mdconst::dyn_extract(MD->getOperand(0))->getZExtValue(); - auto Name = cast(MD->getOperand(2))->getString(); - // We may see pairs with same name but different GUIDs here in LTO mode, due - // to static same-named functions inlined from other modules into this - // module. Function profiles with the same name will be merged no matter - // whether they are collected on the same function. Therefore we just pick - // up the last pair here to represent the same-named function - // collection and all probes from the collection will be merged into a - // single profile eventually. - Names[Name] = GUID; - } - - LLVM_DEBUG(dump()); -} - void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attr, const DILocation *DebugLoc) { @@ -60,8 +35,7 @@ void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index, auto Name = SP->getLinkageName(); if (Name.empty()) Name = SP->getName(); - assert(Names.count(Name) && "Pseudo probe descriptor missing for function"); - uint64_t CallerGuid = Names[Name]; + uint64_t CallerGuid = Function::getGUID(Name); uint64_t CallerProbeId = PseudoProbeDwarfDiscriminator::extractProbeIndex( InlinedAt->getDiscriminator()); ReversedInlineStack.emplace_back(CallerGuid, CallerProbeId); @@ -72,13 +46,3 @@ void PseudoProbeHandler::emitPseudoProbe(uint64_t Guid, uint64_t Index, ReversedInlineStack.rend()); Asm->OutStreamer->emitPseudoProbe(Guid, Index, Type, Attr, InlineStack); } - -#ifndef NDEBUG -void PseudoProbeHandler::dump() const { - dbgs() << "\n=============================\n"; - dbgs() << "\nFunction Name to GUID map:\n"; - dbgs() << "\n=============================\n"; - for (const auto &Item : Names) - dbgs() << "Func: " << Item.first << " GUID: " << Item.second << "\n"; -} -#endif diff --git a/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.h b/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.h index bea07ceae9d4d..f2026a118bf58 100644 --- a/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.h +++ b/llvm/lib/CodeGen/AsmPrinter/PseudoProbePrinter.h @@ -26,12 +26,9 @@ class DILocation; class PseudoProbeHandler : public AsmPrinterHandler { // Target of pseudo probe emission. AsmPrinter *Asm; - // Name to GUID map - DenseMap Names; public: - PseudoProbeHandler(AsmPrinter *A, Module *M); - ~PseudoProbeHandler() override; + PseudoProbeHandler(AsmPrinter *A) : Asm(A){}; void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attr, const DILocation *DebugLoc); @@ -43,10 +40,6 @@ class PseudoProbeHandler : public AsmPrinterHandler { void endFunction(const MachineFunction *MF) override {} void beginInstruction(const MachineInstr *MI) override {} void endInstruction() override {} - -#ifndef NDEBUG - void dump() const; -#endif }; } // namespace llvm diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index ec996b045219f..125a3be585cb5 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -689,6 +689,8 @@ static PartwordMaskValues createMaskInstrs(IRBuilder<> &Builder, Instruction *I, if (PMV.ValueType == PMV.WordType) { PMV.AlignedAddr = Addr; PMV.AlignedAddrAlignment = AddrAlign; + PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0); + PMV.Mask = ConstantInt::get(PMV.ValueType, ~0); return PMV; } diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index a08af69089394..398253fbfce0c 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -142,6 +142,7 @@ add_llvm_component_library(LLVMCodeGen RegisterCoalescer.cpp RegisterPressure.cpp RegisterScavenging.cpp + RemoveRedundantDebugValues.cpp RenameIndependentSubregs.cpp MachineStableHash.cpp MIRVRegNamerUtils.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 708325298aaeb..e0e2db9f47256 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -97,6 +97,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeRegUsageInfoCollectorPass(Registry); initializeRegUsageInfoPropagationPass(Registry); initializeRegisterCoalescerPass(Registry); + initializeRemoveRedundantDebugValuesPass(Registry); initializeRenameIndependentSubregsPass(Registry); initializeSafeStackLegacyPassPass(Registry); initializeShadowStackGCLoweringPass(Registry); diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index a015fab17f74b..83dc9bf4244b6 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -156,10 +156,16 @@ void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, const AttributeList &Attrs = FuncInfo.getAttributes(); addArgFlagsFromAttributes(Flags, Attrs, OpIdx); + PointerType *PtrTy = dyn_cast(Arg.Ty->getScalarType()); + if (PtrTy) { + Flags.setPointer(); + Flags.setPointerAddrSpace(PtrTy->getPointerAddressSpace()); + } + Align MemAlign = DL.getABITypeAlign(Arg.Ty); if (Flags.isByVal() || Flags.isInAlloca() || Flags.isPreallocated()) { assert(OpIdx >= AttributeList::FirstArgIndex); - Type *ElementTy = cast(Arg.Ty)->getElementType(); + Type *ElementTy = PtrTy->getElementType(); auto Ty = Attrs.getAttribute(OpIdx, Attribute::ByVal).getValueAsType(); Flags.setByValSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy)); @@ -201,12 +207,12 @@ CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx, void CallLowering::splitToValueTypes(const ArgInfo &OrigArg, SmallVectorImpl &SplitArgs, const DataLayout &DL, - CallingConv::ID CallConv) const { + CallingConv::ID CallConv, + SmallVectorImpl *Offsets) const { LLVMContext &Ctx = OrigArg.Ty->getContext(); SmallVector SplitVTs; - SmallVector Offsets; - ComputeValueVTs(*TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); + ComputeValueVTs(*TLI, DL, OrigArg.Ty, SplitVTs, Offsets, 0); if (SplitVTs.size() == 0) return; @@ -236,22 +242,6 @@ void CallLowering::splitToValueTypes(const ArgInfo &OrigArg, SplitArgs.back().Flags[0].setInConsecutiveRegsLast(); } -void CallLowering::unpackRegs(ArrayRef DstRegs, Register SrcReg, - Type *PackedTy, - MachineIRBuilder &MIRBuilder) const { - assert(DstRegs.size() > 1 && "Nothing to unpack"); - - const DataLayout &DL = MIRBuilder.getDataLayout(); - - SmallVector LLTs; - SmallVector Offsets; - computeValueLLTs(DL, *PackedTy, LLTs, &Offsets); - assert(LLTs.size() == DstRegs.size() && "Regs / types mismatch"); - - for (unsigned i = 0; i < DstRegs.size(); ++i) - MIRBuilder.buildExtract(DstRegs[i], SrcReg, Offsets[i]); -} - /// Pack values \p SrcRegs to cover the vector type result \p DstRegs. static MachineInstrBuilder mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef DstRegs, @@ -347,6 +337,14 @@ static void buildCopyFromRegs(MachineIRBuilder &B, ArrayRef OrigRegs, .getReg(0); } + // Sometimes pointers are passed zero extended. + LLT OrigTy = MRI.getType(OrigRegs[0]); + if (OrigTy.isPointer()) { + LLT IntPtrTy = LLT::scalar(OrigTy.getSizeInBits()); + B.buildIntToPtr(OrigRegs[0], B.buildTrunc(IntPtrTy, SrcReg)); + return; + } + B.buildTrunc(OrigRegs[0], SrcReg); return; } @@ -484,24 +482,32 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef DstRegs, LLT DstTy = MRI.getType(DstRegs[0]); LLT LCMTy = getLCMType(SrcTy, PartTy); - const unsigned LCMSize = LCMTy.getSizeInBits(); const unsigned DstSize = DstTy.getSizeInBits(); const unsigned SrcSize = SrcTy.getSizeInBits(); + unsigned CoveringSize = LCMTy.getSizeInBits(); Register UnmergeSrc = SrcReg; - if (LCMSize != SrcSize) { - // Widen to the common type. - Register Undef = B.buildUndef(SrcTy).getReg(0); - SmallVector MergeParts(1, SrcReg); - for (unsigned Size = SrcSize; Size != LCMSize; Size += SrcSize) - MergeParts.push_back(Undef); - - UnmergeSrc = B.buildMerge(LCMTy, MergeParts).getReg(0); + + if (CoveringSize != SrcSize) { + // For scalars, it's common to be able to use a simple extension. + if (SrcTy.isScalar() && DstTy.isScalar()) { + CoveringSize = alignTo(SrcSize, DstSize); + LLT CoverTy = LLT::scalar(CoveringSize); + UnmergeSrc = B.buildInstr(ExtendOp, {CoverTy}, {SrcReg}).getReg(0); + } else { + // Widen to the common type. + // FIXME: This should respect the extend type + Register Undef = B.buildUndef(SrcTy).getReg(0); + SmallVector MergeParts(1, SrcReg); + for (unsigned Size = SrcSize; Size != CoveringSize; Size += SrcSize) + MergeParts.push_back(Undef); + UnmergeSrc = B.buildMerge(LCMTy, MergeParts).getReg(0); + } } // Unmerge to the original registers and pad with dead defs. SmallVector UnmergeResults(DstRegs.begin(), DstRegs.end()); - for (unsigned Size = DstSize * DstRegs.size(); Size != LCMSize; + for (unsigned Size = DstSize * DstRegs.size(); Size != CoveringSize; Size += DstSize) { UnmergeResults.push_back(MRI.createGenericVirtualRegister(DstTy)); } @@ -682,7 +688,7 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, // TODO: The memory size may be larger than the value we need to // store. We may need to adjust the offset for big endian targets. - LLT MemTy = Handler.getStackValueStoreType(DL, VA); + LLT MemTy = Handler.getStackValueStoreType(DL, VA, Flags); MachinePointerInfo MPO; Register StackAddr = Handler.getStackAddress( @@ -1018,13 +1024,26 @@ bool CallLowering::resultsCompatible(CallLoweringInfo &Info, } LLT CallLowering::ValueHandler::getStackValueStoreType( - const DataLayout &DL, const CCValAssign &VA) const { + const DataLayout &DL, const CCValAssign &VA, ISD::ArgFlagsTy Flags) const { const MVT ValVT = VA.getValVT(); - if (ValVT != MVT::iPTR) - return LLT(ValVT); + if (ValVT != MVT::iPTR) { + LLT ValTy(ValVT); + + // We lost the pointeriness going through CCValAssign, so try to restore it + // based on the flags. + if (Flags.isPointer()) { + LLT PtrTy = LLT::pointer(Flags.getPointerAddrSpace(), + ValTy.getScalarSizeInBits()); + if (ValVT.isVector()) + return LLT::vector(ValTy.getElementCount(), PtrTy); + return PtrTy; + } + + return ValTy; + } - /// FIXME: We need to get the correct pointer address space. - return LLT::pointer(0, DL.getPointerSize(0)); + unsigned AddrSpace = Flags.getPointerAddrSpace(); + return LLT::pointer(AddrSpace, DL.getPointerSize(AddrSpace)); } void CallLowering::ValueHandler::copyArgumentMemory( @@ -1065,6 +1084,14 @@ Register CallLowering::ValueHandler::extendRegister(Register ValReg, LocTy = LLT::scalar(MaxSizeBits); } + const LLT ValRegTy = MRI.getType(ValReg); + if (ValRegTy.isPointer()) { + // The x32 ABI wants to zero extend 32-bit pointers to 64-bit registers, so + // we have to cast to do the extension. + LLT IntPtrTy = LLT::scalar(ValRegTy.getSizeInBits()); + ValReg = MIRBuilder.buildPtrToInt(IntPtrTy, ValReg).getReg(0); + } + switch (VA.getLocInfo()) { default: break; case CCValAssign::Full: diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index ad1b461db648e..e6ca02e8bd03d 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -11,6 +11,7 @@ #include "llvm/CodeGen/GlobalISel/Combiner.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" @@ -441,16 +442,13 @@ bool CombinerHelper::matchCombineExtendingLoads(MachineInstr &MI, // to find a safe place to sink it) whereas the extend is freely movable. // It also prevents us from duplicating the load for the volatile case or just // for performance. - - if (MI.getOpcode() != TargetOpcode::G_LOAD && - MI.getOpcode() != TargetOpcode::G_SEXTLOAD && - MI.getOpcode() != TargetOpcode::G_ZEXTLOAD) + GAnyLoad *LoadMI = dyn_cast(&MI); + if (!LoadMI) return false; - auto &LoadValue = MI.getOperand(0); - assert(LoadValue.isReg() && "Result wasn't a register?"); + Register LoadReg = LoadMI->getDstReg(); - LLT LoadValueTy = MRI.getType(LoadValue.getReg()); + LLT LoadValueTy = MRI.getType(LoadReg); if (!LoadValueTy.isScalar()) return false; @@ -472,17 +470,16 @@ bool CombinerHelper::matchCombineExtendingLoads(MachineInstr &MI, // and emit a variant of (extend (trunc X)) for the others according to the // relative type sizes. At the same time, pick an extend to use based on the // extend involved in the chosen type. - unsigned PreferredOpcode = MI.getOpcode() == TargetOpcode::G_LOAD - ? TargetOpcode::G_ANYEXT - : MI.getOpcode() == TargetOpcode::G_SEXTLOAD - ? TargetOpcode::G_SEXT - : TargetOpcode::G_ZEXT; + unsigned PreferredOpcode = + isa(&MI) + ? TargetOpcode::G_ANYEXT + : isa(&MI) ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT; Preferred = {LLT(), PreferredOpcode, nullptr}; - for (auto &UseMI : MRI.use_nodbg_instructions(LoadValue.getReg())) { + for (auto &UseMI : MRI.use_nodbg_instructions(LoadReg)) { if (UseMI.getOpcode() == TargetOpcode::G_SEXT || UseMI.getOpcode() == TargetOpcode::G_ZEXT || (UseMI.getOpcode() == TargetOpcode::G_ANYEXT)) { - const auto &MMO = **MI.memoperands_begin(); + const auto &MMO = LoadMI->getMMO(); // For atomics, only form anyextending loads. if (MMO.isAtomic() && UseMI.getOpcode() != TargetOpcode::G_ANYEXT) continue; @@ -493,9 +490,9 @@ bool CombinerHelper::matchCombineExtendingLoads(MachineInstr &MI, MMDesc.AlignInBits = MMO.getAlign().value() * 8; MMDesc.Ordering = MMO.getSuccessOrdering(); LLT UseTy = MRI.getType(UseMI.getOperand(0).getReg()); - LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); - if (LI->getAction({MI.getOpcode(), {UseTy, SrcTy}, {MMDesc}}).Action != - LegalizeActions::Legal) + LLT SrcTy = MRI.getType(LoadMI->getPointerReg()); + if (LI->getAction({LoadMI->getOpcode(), {UseTy, SrcTy}, {MMDesc}}) + .Action != LegalizeActions::Legal) continue; } Preferred = ChoosePreferredUse(Preferred, @@ -668,12 +665,12 @@ bool CombinerHelper::matchSextTruncSextLoad(MachineInstr &MI) { uint64_t SizeInBits = MI.getOperand(2).getImm(); // If the source is a G_SEXTLOAD from the same bit width, then we don't // need any extend at all, just a truncate. - if (auto *LoadMI = getOpcodeDef(TargetOpcode::G_SEXTLOAD, LoadUser, MRI)) { - const auto &MMO = **LoadMI->memoperands_begin(); + if (auto *LoadMI = getOpcodeDef(LoadUser, MRI)) { // If truncating more than the original extended value, abort. - if (TruncSrc && MRI.getType(TruncSrc).getSizeInBits() < MMO.getSizeInBits()) + auto LoadSizeBits = LoadMI->getMemSizeInBits(); + if (TruncSrc && MRI.getType(TruncSrc).getSizeInBits() < LoadSizeBits) return false; - if (MMO.getSizeInBits() == SizeInBits) + if (LoadSizeBits == SizeInBits) return true; } return false; @@ -695,20 +692,16 @@ bool CombinerHelper::matchSextInRegOfLoad( return false; Register SrcReg = MI.getOperand(1).getReg(); - MachineInstr *LoadDef = getOpcodeDef(TargetOpcode::G_LOAD, SrcReg, MRI); - if (!LoadDef || !MRI.hasOneNonDBGUse(LoadDef->getOperand(0).getReg())) + auto *LoadDef = getOpcodeDef(SrcReg, MRI); + if (!LoadDef || !MRI.hasOneNonDBGUse(LoadDef->getOperand(0).getReg()) || + !LoadDef->isSimple()) return false; // If the sign extend extends from a narrower width than the load's width, // then we can narrow the load width when we combine to a G_SEXTLOAD. - auto &MMO = **LoadDef->memoperands_begin(); - // Don't do this for non-simple loads. - if (MMO.isAtomic() || MMO.isVolatile()) - return false; - // Avoid widening the load at all. - unsigned NewSizeBits = - std::min((uint64_t)MI.getOperand(2).getImm(), MMO.getSizeInBits()); + unsigned NewSizeBits = std::min((uint64_t)MI.getOperand(2).getImm(), + LoadDef->getMemSizeInBits()); // Don't generate G_SEXTLOADs with a < 1 byte width. if (NewSizeBits < 8) @@ -717,7 +710,7 @@ bool CombinerHelper::matchSextInRegOfLoad( // anyway for most targets. if (!isPowerOf2_32(NewSizeBits)) return false; - MatchInfo = std::make_tuple(LoadDef->getOperand(0).getReg(), NewSizeBits); + MatchInfo = std::make_tuple(LoadDef->getDstReg(), NewSizeBits); return true; } @@ -727,8 +720,7 @@ void CombinerHelper::applySextInRegOfLoad( Register LoadReg; unsigned ScalarSizeBits; std::tie(LoadReg, ScalarSizeBits) = MatchInfo; - auto *LoadDef = MRI.getVRegDef(LoadReg); - assert(LoadDef && "Expected a load reg"); + GLoad *LoadDef = cast(MRI.getVRegDef(LoadReg)); // If we have the following: // %ld = G_LOAD %ptr, (load 2) @@ -736,13 +728,13 @@ void CombinerHelper::applySextInRegOfLoad( // ==> // %ld = G_SEXTLOAD %ptr (load 1) - auto &MMO = **LoadDef->memoperands_begin(); + auto &MMO = LoadDef->getMMO(); Builder.setInstrAndDebugLoc(*LoadDef); auto &MF = Builder.getMF(); auto PtrInfo = MMO.getPointerInfo(); auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, ScalarSizeBits / 8); Builder.buildLoadInstr(TargetOpcode::G_SEXTLOAD, MI.getOperand(0).getReg(), - LoadDef->getOperand(1).getReg(), *NewMMO); + LoadDef->getPointerReg(), *NewMMO); MI.eraseFromParent(); } @@ -1310,7 +1302,7 @@ bool CombinerHelper::optimizeMemset(MachineInstr &MI, Register Dst, } auto *StoreMMO = - MF.getMachineMemOperand(&DstMMO, DstOff, Ty.getSizeInBytes()); + MF.getMachineMemOperand(&DstMMO, DstOff, Ty); Register Ptr = Dst; if (DstOff != 0) { @@ -3436,7 +3428,7 @@ CombinerHelper::findCandidatesForLoadOrCombine(const MachineInstr *Root) const { /// e.g. x[i] << 24 /// /// \returns The load instruction and the byte offset it is moved into. -static Optional> +static Optional> matchLoadAndBytePosition(Register Reg, unsigned MemSizeInBits, const MachineRegisterInfo &MRI) { assert(MRI.hasOneNonDBGUse(Reg) && @@ -3453,18 +3445,17 @@ matchLoadAndBytePosition(Register Reg, unsigned MemSizeInBits, return None; // TODO: Handle other types of loads. - auto *Load = getOpcodeDef(TargetOpcode::G_ZEXTLOAD, MaybeLoad, MRI); + auto *Load = getOpcodeDef(MaybeLoad, MRI); if (!Load) return None; - const auto &MMO = **Load->memoperands_begin(); - if (!MMO.isUnordered() || MMO.getSizeInBits() != MemSizeInBits) + if (!Load->isUnordered() || Load->getMemSizeInBits() != MemSizeInBits) return None; return std::make_pair(Load, Shift / MemSizeInBits); } -Optional> +Optional> CombinerHelper::findLoadOffsetsForLoadOrCombine( SmallDenseMap &MemOffset2Idx, const SmallVector &RegsToVisit, const unsigned MemSizeInBits) { @@ -3476,7 +3467,7 @@ CombinerHelper::findLoadOffsetsForLoadOrCombine( int64_t LowestIdx = INT64_MAX; // The load which uses the lowest index. - MachineInstr *LowestIdxLoad = nullptr; + GZExtLoad *LowestIdxLoad = nullptr; // Keeps track of the load indices we see. We shouldn't see any indices twice. SmallSet SeenIdx; @@ -3505,7 +3496,7 @@ CombinerHelper::findLoadOffsetsForLoadOrCombine( auto LoadAndPos = matchLoadAndBytePosition(Reg, MemSizeInBits, MRI); if (!LoadAndPos) return None; - MachineInstr *Load; + GZExtLoad *Load; int64_t DstPos; std::tie(Load, DstPos) = *LoadAndPos; @@ -3518,10 +3509,10 @@ CombinerHelper::findLoadOffsetsForLoadOrCombine( return None; // Make sure that the MachineMemOperands of every seen load are compatible. - const MachineMemOperand *LoadMMO = *Load->memoperands_begin(); + auto &LoadMMO = Load->getMMO(); if (!MMO) - MMO = LoadMMO; - if (MMO->getAddrSpace() != LoadMMO->getAddrSpace()) + MMO = &LoadMMO; + if (MMO->getAddrSpace() != LoadMMO.getAddrSpace()) return None; // Find out what the base pointer and index for the load is. @@ -3643,7 +3634,7 @@ bool CombinerHelper::matchLoadOrCombine( // Also verify that each of these ends up putting a[i] into the same memory // offset as a load into a wide type would. SmallDenseMap MemOffset2Idx; - MachineInstr *LowestIdxLoad; + GZExtLoad *LowestIdxLoad; int64_t LowestIdx; auto MaybeLoadInfo = findLoadOffsetsForLoadOrCombine( MemOffset2Idx, *RegsToVisit, NarrowMemSizeInBits); @@ -3683,8 +3674,8 @@ bool CombinerHelper::matchLoadOrCombine( // We wil reuse the pointer from the load which ends up at byte offset 0. It // may not use index 0. - Register Ptr = LowestIdxLoad->getOperand(1).getReg(); - const MachineMemOperand &MMO = **LowestIdxLoad->memoperands_begin(); + Register Ptr = LowestIdxLoad->getPointerReg(); + const MachineMemOperand &MMO = LowestIdxLoad->getMMO(); LegalityQuery::MemDesc MMDesc; MMDesc.MemoryTy = Ty; MMDesc.AlignInBits = MMO.getAlign().value() * 8; @@ -4146,6 +4137,7 @@ bool CombinerHelper::reassociationCanBreakAddressingModePattern( if (!MRI.hasOneNonDBGUse(DefReg)) break; ConvUseMI = &*MRI.use_instr_nodbg_begin(DefReg); + ConvUseOpc = ConvUseMI->getOpcode(); } auto LoadStore = ConvUseOpc == TargetOpcode::G_LOAD || ConvUseOpc == TargetOpcode::G_STORE; diff --git a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp index a7f0d5fde1284..8146a67d4dfb9 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp @@ -501,13 +501,13 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known, case TargetOpcode::G_BSWAP: { Register SrcReg = MI.getOperand(1).getReg(); computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1); - Known.byteSwap(); + Known = Known.byteSwap(); break; } case TargetOpcode::G_BITREVERSE: { Register SrcReg = MI.getOperand(1).getReg(); computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1); - Known.reverseBits(); + Known = Known.reverseBits(); break; } case TargetOpcode::G_UBFX: { diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 40f6f4a5ba23e..8a54b87043a92 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -893,53 +893,53 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, case TargetOpcode::G_INSERT: return narrowScalarInsert(MI, TypeIdx, NarrowTy); case TargetOpcode::G_LOAD: { - auto &MMO = **MI.memoperands_begin(); - Register DstReg = MI.getOperand(0).getReg(); + auto &LoadMI = cast(MI); + Register DstReg = LoadMI.getDstReg(); LLT DstTy = MRI.getType(DstReg); if (DstTy.isVector()) return UnableToLegalize; - if (8 * MMO.getSize() != DstTy.getSizeInBits()) { + if (8 * LoadMI.getMemSize() != DstTy.getSizeInBits()) { Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); - MIRBuilder.buildLoad(TmpReg, MI.getOperand(1), MMO); + MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO()); MIRBuilder.buildAnyExt(DstReg, TmpReg); - MI.eraseFromParent(); + LoadMI.eraseFromParent(); return Legalized; } - return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy); + return reduceLoadStoreWidth(LoadMI, TypeIdx, NarrowTy); } case TargetOpcode::G_ZEXTLOAD: case TargetOpcode::G_SEXTLOAD: { - bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD; - Register DstReg = MI.getOperand(0).getReg(); - Register PtrReg = MI.getOperand(1).getReg(); + auto &LoadMI = cast(MI); + Register DstReg = LoadMI.getDstReg(); + Register PtrReg = LoadMI.getPointerReg(); Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); - auto &MMO = **MI.memoperands_begin(); + auto &MMO = LoadMI.getMMO(); unsigned MemSize = MMO.getSizeInBits(); if (MemSize == NarrowSize) { MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); } else if (MemSize < NarrowSize) { - MIRBuilder.buildLoadInstr(MI.getOpcode(), TmpReg, PtrReg, MMO); + MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO); } else if (MemSize > NarrowSize) { // FIXME: Need to split the load. return UnableToLegalize; } - if (ZExt) + if (isa(LoadMI)) MIRBuilder.buildZExt(DstReg, TmpReg); else MIRBuilder.buildSExt(DstReg, TmpReg); - MI.eraseFromParent(); + LoadMI.eraseFromParent(); return Legalized; } case TargetOpcode::G_STORE: { - const auto &MMO = **MI.memoperands_begin(); + auto &StoreMI = cast(MI); - Register SrcReg = MI.getOperand(0).getReg(); + Register SrcReg = StoreMI.getValueReg(); LLT SrcTy = MRI.getType(SrcReg); if (SrcTy.isVector()) return UnableToLegalize; @@ -950,16 +950,15 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, if (SrcTy.isVector() && LeftoverBits != 0) return UnableToLegalize; - if (8 * MMO.getSize() != SrcTy.getSizeInBits()) { + if (8 * StoreMI.getMemSize() != SrcTy.getSizeInBits()) { Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); - auto &MMO = **MI.memoperands_begin(); MIRBuilder.buildTrunc(TmpReg, SrcReg); - MIRBuilder.buildStore(TmpReg, MI.getOperand(1), MMO); - MI.eraseFromParent(); + MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO()); + StoreMI.eraseFromParent(); return Legalized; } - return reduceLoadStoreWidth(MI, 0, NarrowTy); + return reduceLoadStoreWidth(StoreMI, 0, NarrowTy); } case TargetOpcode::G_SELECT: return narrowScalarSelect(MI, TypeIdx, NarrowTy); @@ -1063,38 +1062,81 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, return Legalized; } case TargetOpcode::G_ICMP: { - uint64_t SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); - if (NarrowSize * 2 != SrcSize) + Register LHS = MI.getOperand(2).getReg(); + LLT SrcTy = MRI.getType(LHS); + uint64_t SrcSize = SrcTy.getSizeInBits(); + CmpInst::Predicate Pred = + static_cast(MI.getOperand(1).getPredicate()); + + // TODO: Handle the non-equality case for weird sizes. + if (NarrowSize * 2 != SrcSize && !ICmpInst::isEquality(Pred)) return UnableToLegalize; - Observer.changingInstr(MI); - Register LHSL = MRI.createGenericVirtualRegister(NarrowTy); - Register LHSH = MRI.createGenericVirtualRegister(NarrowTy); - MIRBuilder.buildUnmerge({LHSL, LHSH}, MI.getOperand(2)); + LLT LeftoverTy; // Example: s88 -> s64 (NarrowTy) + s24 (leftover) + SmallVector LHSPartRegs, LHSLeftoverRegs; + if (!extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs, + LHSLeftoverRegs)) + return UnableToLegalize; - Register RHSL = MRI.createGenericVirtualRegister(NarrowTy); - Register RHSH = MRI.createGenericVirtualRegister(NarrowTy); - MIRBuilder.buildUnmerge({RHSL, RHSH}, MI.getOperand(3)); + LLT Unused; // Matches LeftoverTy; G_ICMP LHS and RHS are the same type. + SmallVector RHSPartRegs, RHSLeftoverRegs; + if (!extractParts(MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused, + RHSPartRegs, RHSLeftoverRegs)) + return UnableToLegalize; - CmpInst::Predicate Pred = - static_cast(MI.getOperand(1).getPredicate()); - LLT ResTy = MRI.getType(MI.getOperand(0).getReg()); - - if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) { - MachineInstrBuilder XorL = MIRBuilder.buildXor(NarrowTy, LHSL, RHSL); - MachineInstrBuilder XorH = MIRBuilder.buildXor(NarrowTy, LHSH, RHSH); - MachineInstrBuilder Or = MIRBuilder.buildOr(NarrowTy, XorL, XorH); - MachineInstrBuilder Zero = MIRBuilder.buildConstant(NarrowTy, 0); - MIRBuilder.buildICmp(Pred, MI.getOperand(0), Or, Zero); + // We now have the LHS and RHS of the compare split into narrow-type + // registers, plus potentially some leftover type. + Register Dst = MI.getOperand(0).getReg(); + LLT ResTy = MRI.getType(Dst); + if (ICmpInst::isEquality(Pred)) { + // For each part on the LHS and RHS, keep track of the result of XOR-ing + // them together. For each equal part, the result should be all 0s. For + // each non-equal part, we'll get at least one 1. + auto Zero = MIRBuilder.buildConstant(NarrowTy, 0); + SmallVector Xors; + for (auto LHSAndRHS : zip(LHSPartRegs, RHSPartRegs)) { + auto LHS = std::get<0>(LHSAndRHS); + auto RHS = std::get<1>(LHSAndRHS); + auto Xor = MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0); + Xors.push_back(Xor); + } + + // Build a G_XOR for each leftover register. Each G_XOR must be widened + // to the desired narrow type so that we can OR them together later. + SmallVector WidenedXors; + for (auto LHSAndRHS : zip(LHSLeftoverRegs, RHSLeftoverRegs)) { + auto LHS = std::get<0>(LHSAndRHS); + auto RHS = std::get<1>(LHSAndRHS); + auto Xor = MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0); + LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy, Xor); + buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors, + /* PadStrategy = */ TargetOpcode::G_ZEXT); + Xors.insert(Xors.end(), WidenedXors.begin(), WidenedXors.end()); + } + + // Now, for each part we broke up, we know if they are equal/not equal + // based off the G_XOR. We can OR these all together and compare against + // 0 to get the result. + assert(Xors.size() >= 2 && "Should have gotten at least two Xors?"); + auto Or = MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]); + for (unsigned I = 2, E = Xors.size(); I < E; ++I) + Or = MIRBuilder.buildOr(NarrowTy, Or, Xors[I]); + MIRBuilder.buildICmp(Pred, Dst, Or, Zero); } else { + // TODO: Handle non-power-of-two types. + assert(LHSPartRegs.size() == 2 && "Expected exactly 2 LHS part regs?"); + assert(RHSPartRegs.size() == 2 && "Expected exactly 2 RHS part regs?"); + Register LHSL = LHSPartRegs[0]; + Register LHSH = LHSPartRegs[1]; + Register RHSL = RHSPartRegs[0]; + Register RHSH = RHSPartRegs[1]; MachineInstrBuilder CmpH = MIRBuilder.buildICmp(Pred, ResTy, LHSH, RHSH); MachineInstrBuilder CmpHEQ = MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy, LHSH, RHSH); MachineInstrBuilder CmpLU = MIRBuilder.buildICmp( ICmpInst::getUnsignedPredicate(Pred), ResTy, LHSL, RHSL); - MIRBuilder.buildSelect(MI.getOperand(0), CmpHEQ, CmpLU, CmpH); + MIRBuilder.buildSelect(Dst, CmpHEQ, CmpLU, CmpH); } - Observer.changedInstr(MI); MI.eraseFromParent(); return Legalized; } @@ -2754,13 +2796,12 @@ LegalizerHelper::bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, return UnableToLegalize; } -LegalizerHelper::LegalizeResult -LegalizerHelper::lowerLoad(MachineInstr &MI) { +LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) { // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT - Register DstReg = MI.getOperand(0).getReg(); - Register PtrReg = MI.getOperand(1).getReg(); + Register DstReg = LoadMI.getDstReg(); + Register PtrReg = LoadMI.getPointerReg(); LLT DstTy = MRI.getType(DstReg); - MachineMemOperand &MMO = **MI.memoperands_begin(); + MachineMemOperand &MMO = LoadMI.getMMO(); LLT MemTy = MMO.getMemoryType(); MachineFunction &MF = MIRBuilder.getMF(); if (MemTy.isVector()) @@ -2786,11 +2827,10 @@ LegalizerHelper::lowerLoad(MachineInstr &MI) { LoadReg = MRI.createGenericVirtualRegister(WideMemTy); } - if (MI.getOpcode() == TargetOpcode::G_SEXTLOAD) { + if (isa(LoadMI)) { auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO); MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits); - } else if (MI.getOpcode() == TargetOpcode::G_ZEXTLOAD || - WideMemTy == DstTy) { + } else if (isa(LoadMI) || WideMemTy == DstTy) { auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO); // The extra bits are guaranteed to be zero, since we stored them that // way. A zext load from Wide thus automatically gives zext from MemVT. @@ -2802,79 +2842,79 @@ LegalizerHelper::lowerLoad(MachineInstr &MI) { if (DstTy != LoadTy) MIRBuilder.buildTrunc(DstReg, LoadReg); - MI.eraseFromParent(); + LoadMI.eraseFromParent(); return Legalized; } - if (DstTy.getSizeInBits() != MMO.getSizeInBits()) + // This load needs splitting into power of 2 sized loads. + if (DstTy.isVector()) + return UnableToLegalize; + if (isPowerOf2_32(MemSizeInBits)) + return UnableToLegalize; // Don't know what we're being asked to do. + + // Big endian lowering not implemented. + if (MIRBuilder.getDataLayout().isBigEndian()) return UnableToLegalize; - if (MI.getOpcode() == TargetOpcode::G_LOAD) { - // This load needs splitting into power of 2 sized loads. - if (DstTy.isVector()) - return UnableToLegalize; - if (isPowerOf2_32(DstTy.getSizeInBits())) - return UnableToLegalize; // Don't know what we're being asked to do. - - // Our strategy here is to generate anyextending loads for the smaller - // types up to next power-2 result type, and then combine the two larger - // result values together, before truncating back down to the non-pow-2 - // type. - // E.g. v1 = i24 load => - // v2 = i32 zextload (2 byte) - // v3 = i32 load (1 byte) - // v4 = i32 shl v3, 16 - // v5 = i32 or v4, v2 - // v1 = i24 trunc v5 - // By doing this we generate the correct truncate which should get - // combined away as an artifact with a matching extend. - uint64_t LargeSplitSize = PowerOf2Floor(DstTy.getSizeInBits()); - uint64_t SmallSplitSize = DstTy.getSizeInBits() - LargeSplitSize; + // Our strategy here is to generate anyextending loads for the smaller + // types up to next power-2 result type, and then combine the two larger + // result values together, before truncating back down to the non-pow-2 + // type. + // E.g. v1 = i24 load => + // v2 = i32 zextload (2 byte) + // v3 = i32 load (1 byte) + // v4 = i32 shl v3, 16 + // v5 = i32 or v4, v2 + // v1 = i24 trunc v5 + // By doing this we generate the correct truncate which should get + // combined away as an artifact with a matching extend. + uint64_t LargeSplitSize = PowerOf2Floor(MemSizeInBits); + uint64_t SmallSplitSize = MemSizeInBits - LargeSplitSize; - MachineFunction &MF = MIRBuilder.getMF(); - MachineMemOperand *LargeMMO = + MachineMemOperand *LargeMMO = MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8); - MachineMemOperand *SmallMMO = MF.getMachineMemOperand( - &MMO, LargeSplitSize / 8, SmallSplitSize / 8); - - LLT PtrTy = MRI.getType(PtrReg); - unsigned AnyExtSize = NextPowerOf2(DstTy.getSizeInBits()); - LLT AnyExtTy = LLT::scalar(AnyExtSize); - auto LargeLoad = MIRBuilder.buildLoadInstr( - TargetOpcode::G_ZEXTLOAD, AnyExtTy, PtrReg, *LargeMMO); - - auto OffsetCst = MIRBuilder.buildConstant( - LLT::scalar(PtrTy.getSizeInBits()), LargeSplitSize / 8); - Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy); - auto SmallPtr = - MIRBuilder.buildPtrAdd(PtrAddReg, PtrReg, OffsetCst); - auto SmallLoad = MIRBuilder.buildLoad(AnyExtTy, SmallPtr, - *SmallMMO); - - auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize); - auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt); + MachineMemOperand *SmallMMO = + MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8); + + LLT PtrTy = MRI.getType(PtrReg); + unsigned AnyExtSize = PowerOf2Ceil(DstTy.getSizeInBits()); + LLT AnyExtTy = LLT::scalar(AnyExtSize); + auto LargeLoad = MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy, + PtrReg, *LargeMMO); + + auto OffsetCst = MIRBuilder.buildConstant(LLT::scalar(PtrTy.getSizeInBits()), + LargeSplitSize / 8); + Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy); + auto SmallPtr = MIRBuilder.buildPtrAdd(PtrAddReg, PtrReg, OffsetCst); + auto SmallLoad = MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), AnyExtTy, + SmallPtr, *SmallMMO); + + auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize); + auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt); + + if (AnyExtTy == DstTy) + MIRBuilder.buildOr(DstReg, Shift, LargeLoad); + else { auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad); MIRBuilder.buildTrunc(DstReg, {Or}); - MI.eraseFromParent(); - return Legalized; } - return UnableToLegalize; + LoadMI.eraseFromParent(); + return Legalized; } -LegalizerHelper::LegalizeResult -LegalizerHelper::lowerStore(MachineInstr &MI) { +LegalizerHelper::LegalizeResult LegalizerHelper::lowerStore(GStore &StoreMI) { // Lower a non-power of 2 store into multiple pow-2 stores. // E.g. split an i24 store into an i16 store + i8 store. // We do this by first extending the stored value to the next largest power // of 2 type, and then using truncating stores to store the components. // By doing this, likewise with G_LOAD, generate an extend that can be // artifact-combined away instead of leaving behind extracts. - Register SrcReg = MI.getOperand(0).getReg(); - Register PtrReg = MI.getOperand(1).getReg(); + Register SrcReg = StoreMI.getValueReg(); + Register PtrReg = StoreMI.getPointerReg(); LLT SrcTy = MRI.getType(SrcReg); MachineFunction &MF = MIRBuilder.getMF(); - MachineMemOperand &MMO = **MI.memoperands_begin(); + MachineMemOperand &MMO = **StoreMI.memoperands_begin(); LLT MemTy = MMO.getMemoryType(); if (SrcTy.isVector()) @@ -2900,22 +2940,24 @@ LegalizerHelper::lowerStore(MachineInstr &MI) { MachineMemOperand *NewMMO = MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideTy); MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO); - MI.eraseFromParent(); + StoreMI.eraseFromParent(); return Legalized; } if (isPowerOf2_32(MemTy.getSizeInBits())) return UnableToLegalize; // Don't know what we're being asked to do. - // Extend to the next pow-2. - const LLT ExtendTy = LLT::scalar(NextPowerOf2(MemTy.getSizeInBits())); - auto ExtVal = MIRBuilder.buildAnyExt(ExtendTy, SrcReg); + // Extend to the next pow-2. If this store was itself the result of lowering, + // e.g. an s56 store being broken into s32 + s24, we might have a stored type + // that's wider the stored size. + const LLT NewSrcTy = LLT::scalar(NextPowerOf2(MemTy.getSizeInBits())); + auto ExtVal = MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg); // Obtain the smaller value by shifting away the larger value. uint64_t LargeSplitSize = PowerOf2Floor(MemTy.getSizeInBits()); - uint64_t SmallSplitSize = SrcTy.getSizeInBits() - LargeSplitSize; - auto ShiftAmt = MIRBuilder.buildConstant(ExtendTy, LargeSplitSize); - auto SmallVal = MIRBuilder.buildLShr(ExtendTy, ExtVal, ShiftAmt); + uint64_t SmallSplitSize = MemTy.getSizeInBits() - LargeSplitSize; + auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize); + auto SmallVal = MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt); // Generate the PtrAdd and truncating stores. LLT PtrTy = MRI.getType(PtrReg); @@ -2931,7 +2973,7 @@ LegalizerHelper::lowerStore(MachineInstr &MI) { MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8); MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO); MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO); - MI.eraseFromParent(); + StoreMI.eraseFromParent(); return Legalized; } @@ -3122,9 +3164,9 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { case TargetOpcode::G_LOAD: case TargetOpcode::G_SEXTLOAD: case TargetOpcode::G_ZEXTLOAD: - return lowerLoad(MI); + return lowerLoad(cast(MI)); case TargetOpcode::G_STORE: - return lowerStore(MI); + return lowerStore(cast(MI)); case TargetOpcode::G_CTLZ_ZERO_UNDEF: case TargetOpcode::G_CTTZ_ZERO_UNDEF: case TargetOpcode::G_CTLZ: @@ -3921,26 +3963,24 @@ LegalizerHelper::fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, } LegalizerHelper::LegalizeResult -LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, +LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx, LLT NarrowTy) { // FIXME: Don't know how to handle secondary types yet. if (TypeIdx != 0) return UnableToLegalize; - MachineMemOperand *MMO = *MI.memoperands_begin(); - // This implementation doesn't work for atomics. Give up instead of doing // something invalid. - if (MMO->isAtomic()) + if (LdStMI.isAtomic()) return UnableToLegalize; - bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD; - Register ValReg = MI.getOperand(0).getReg(); - Register AddrReg = MI.getOperand(1).getReg(); + bool IsLoad = isa(LdStMI); + Register ValReg = LdStMI.getReg(0); + Register AddrReg = LdStMI.getPointerReg(); LLT ValTy = MRI.getType(ValReg); // FIXME: Do we need a distinct NarrowMemory legalize action? - if (ValTy.getSizeInBits() != 8 * MMO->getSize()) { + if (ValTy.getSizeInBits() != 8 * LdStMI.getMemSize()) { LLVM_DEBUG(dbgs() << "Can't narrow extload/truncstore\n"); return UnableToLegalize; } @@ -3971,6 +4011,7 @@ LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, // is a load, return the new registers in ValRegs. For a store, each elements // of ValRegs should be PartTy. Returns the next offset that needs to be // handled. + auto MMO = LdStMI.getMMO(); auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl &ValRegs, unsigned Offset) -> unsigned { MachineFunction &MF = MIRBuilder.getMF(); @@ -3983,7 +4024,7 @@ LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, MIRBuilder.materializePtrAdd(NewAddrReg, AddrReg, OffsetTy, ByteOffset); MachineMemOperand *NewMMO = - MF.getMachineMemOperand(MMO, ByteOffset, PartTy); + MF.getMachineMemOperand(&MMO, ByteOffset, PartTy); if (IsLoad) { Register Dst = MRI.createGenericVirtualRegister(PartTy); @@ -4008,7 +4049,7 @@ LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LeftoverTy, NarrowLeftoverRegs); } - MI.eraseFromParent(); + LdStMI.eraseFromParent(); return Legalized; } @@ -4282,7 +4323,7 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, return fewerElementsVectorExtractInsertVectorElt(MI, TypeIdx, NarrowTy); case G_LOAD: case G_STORE: - return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy); + return reduceLoadStoreWidth(cast(MI), TypeIdx, NarrowTy); case G_SEXT_INREG: return fewerElementsVectorSextInReg(MI, TypeIdx, NarrowTy); GISEL_VECREDUCE_CASES_NONSEQ diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index 73e42927f8e63..31b8347a0aebb 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -998,12 +998,3 @@ bool llvm::shouldOptForSize(const MachineBasicBlock &MBB, return F.hasOptSize() || F.hasMinSize() || llvm::shouldOptimizeForSize(MBB.getBasicBlock(), PSI, BFI); } - -unsigned llvm::getIntrinsicID(const MachineInstr &MI) { -#ifndef NDEBUG - unsigned Opc = MI.getOpcode(); - assert(Opc == TargetOpcode::G_INTRINSIC || - Opc == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS); -#endif - return MI.getOperand(MI.getNumExplicitDefs()).getIntrinsicID(); -} diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp index 6075f64b2f270..23036c2b115f8 100644 --- a/llvm/lib/CodeGen/LiveIntervals.cpp +++ b/llvm/lib/CodeGen/LiveIntervals.cpp @@ -713,10 +713,15 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) { if (LI.empty()) continue; + // Target may have not allocated this yet. + Register PhysReg = VRM->getPhys(Reg); + if (!PhysReg) + continue; + // Find the regunit intervals for the assigned register. They may overlap // the virtual register live range, cancelling any kills. RU.clear(); - for (MCRegUnitIterator Unit(VRM->getPhys(Reg), TRI); Unit.isValid(); + for (MCRegUnitIterator Unit(PhysReg, TRI); Unit.isValid(); ++Unit) { const LiveRange &RURange = getRegUnit(*Unit); if (RURange.empty()) diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp index c5d1734b0f1f6..64a2dd2756430 100644 --- a/llvm/lib/CodeGen/LiveRangeEdit.cpp +++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -113,9 +113,10 @@ bool LiveRangeEdit::allUsesAvailableAt(const MachineInstr *OrigMI, if (!MO.isReg() || !MO.getReg() || !MO.readsReg()) continue; - // We can't remat physreg uses, unless it is a constant. + // We can't remat physreg uses, unless it is a constant or target wants + // to ignore this use. if (Register::isPhysicalRegister(MO.getReg())) { - if (MRI.isConstantPhysReg(MO.getReg())) + if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO)) continue; return false; } diff --git a/llvm/lib/CodeGen/MachineBranchProbabilityInfo.cpp b/llvm/lib/CodeGen/MachineBranchProbabilityInfo.cpp index 85924bec94a71..c9f762f9a6e71 100644 --- a/llvm/lib/CodeGen/MachineBranchProbabilityInfo.cpp +++ b/llvm/lib/CodeGen/MachineBranchProbabilityInfo.cpp @@ -68,26 +68,6 @@ bool MachineBranchProbabilityInfo::isEdgeHot( return getEdgeProbability(Src, Dst) > HotProb; } -MachineBasicBlock * -MachineBranchProbabilityInfo::getHotSucc(MachineBasicBlock *MBB) const { - auto MaxProb = BranchProbability::getZero(); - MachineBasicBlock *MaxSucc = nullptr; - for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), - E = MBB->succ_end(); I != E; ++I) { - auto Prob = getEdgeProbability(MBB, I); - if (Prob > MaxProb) { - MaxProb = Prob; - MaxSucc = *I; - } - } - - BranchProbability HotProb(StaticLikelyProb, 100); - if (getEdgeProbability(MBB, MaxSucc) >= HotProb) - return MaxSucc; - - return nullptr; -} - raw_ostream &MachineBranchProbabilityInfo::printEdgeProbability( raw_ostream &OS, const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const { diff --git a/llvm/lib/CodeGen/RegAllocBase.cpp b/llvm/lib/CodeGen/RegAllocBase.cpp index a2e9f2124cf6d..d891d4c2ffbb0 100644 --- a/llvm/lib/CodeGen/RegAllocBase.cpp +++ b/llvm/lib/CodeGen/RegAllocBase.cpp @@ -175,3 +175,21 @@ void RegAllocBase::postOptimization() { } DeadRemats.clear(); } + +void RegAllocBase::enqueue(LiveInterval *LI) { + const Register Reg = LI->reg(); + + assert(Reg.isVirtual() && "Can only enqueue virtual registers"); + + if (VRM->hasPhys(Reg)) + return; + + const TargetRegisterClass &RC = *MRI->getRegClass(Reg); + if (ShouldAllocateClass(*TRI, RC)) { + LLVM_DEBUG(dbgs() << "Enqueuing " << printReg(Reg, TRI) << '\n'); + enqueueImpl(LI); + } else { + LLVM_DEBUG(dbgs() << "Not enqueueing " << printReg(Reg, TRI) + << " in skipped register class\n"); + } +} diff --git a/llvm/lib/CodeGen/RegAllocBase.h b/llvm/lib/CodeGen/RegAllocBase.h index 3144605345e99..1fb56dbaebb7f 100644 --- a/llvm/lib/CodeGen/RegAllocBase.h +++ b/llvm/lib/CodeGen/RegAllocBase.h @@ -37,6 +37,7 @@ #define LLVM_LIB_CODEGEN_REGALLOCBASE_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/CodeGen/RegAllocCommon.h" #include "llvm/CodeGen/RegisterClassInfo.h" namespace llvm { @@ -67,6 +68,7 @@ class RegAllocBase { LiveIntervals *LIS = nullptr; LiveRegMatrix *Matrix = nullptr; RegisterClassInfo RegClassInfo; + const RegClassFilterFunc ShouldAllocateClass; /// Inst which is a def of an original reg and whose defs are already all /// dead after remat is saved in DeadRemats. The deletion of such inst is @@ -74,7 +76,9 @@ class RegAllocBase { /// always available for the remat of all the siblings of the original reg. SmallPtrSet DeadRemats; - RegAllocBase() = default; + RegAllocBase(const RegClassFilterFunc F = allocateAllRegClasses) : + ShouldAllocateClass(F) {} + virtual ~RegAllocBase() = default; // A RegAlloc pass should call this before allocatePhysRegs. @@ -92,7 +96,10 @@ class RegAllocBase { virtual Spiller &spiller() = 0; /// enqueue - Add VirtReg to the priority queue of unassigned registers. - virtual void enqueue(LiveInterval *LI) = 0; + virtual void enqueueImpl(LiveInterval *LI) = 0; + + /// enqueue - Add VirtReg to the priority queue of unassigned registers. + void enqueue(LiveInterval *LI); /// dequeue - Return the next unassigned register, or NULL. virtual LiveInterval *dequeue() = 0; diff --git a/llvm/lib/CodeGen/RegAllocBasic.cpp b/llvm/lib/CodeGen/RegAllocBasic.cpp index f8de3e30745ea..b65d580779581 100644 --- a/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/llvm/lib/CodeGen/RegAllocBasic.cpp @@ -76,7 +76,7 @@ class RABasic : public MachineFunctionPass, void LRE_WillShrinkVirtReg(Register) override; public: - RABasic(); + RABasic(const RegClassFilterFunc F = allocateAllRegClasses); /// Return the pass name. StringRef getPassName() const override { return "Basic Register Allocator"; } @@ -88,7 +88,7 @@ class RABasic : public MachineFunctionPass, Spiller &spiller() override { return *SpillerInstance; } - void enqueue(LiveInterval *LI) override { + void enqueueImpl(LiveInterval *LI) override { Queue.push(LI); } @@ -171,7 +171,9 @@ void RABasic::LRE_WillShrinkVirtReg(Register VirtReg) { enqueue(&LI); } -RABasic::RABasic(): MachineFunctionPass(ID) { +RABasic::RABasic(RegClassFilterFunc F): + MachineFunctionPass(ID), + RegAllocBase(F) { } void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { @@ -332,7 +334,10 @@ bool RABasic::runOnMachineFunction(MachineFunction &mf) { return true; } -FunctionPass* llvm::createBasicRegisterAllocator() -{ +FunctionPass* llvm::createBasicRegisterAllocator() { return new RABasic(); } + +FunctionPass* llvm::createBasicRegisterAllocator(RegClassFilterFunc F) { + return new RABasic(F); +} diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 8a964ef3efd0c..707161d5a8b07 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegAllocCommon.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/RegisterClassInfo.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -69,7 +70,13 @@ namespace { public: static char ID; - RegAllocFast() : MachineFunctionPass(ID), StackSlotForVirtReg(-1) {} + RegAllocFast(const RegClassFilterFunc F = allocateAllRegClasses, + bool ClearVirtRegs_ = true) : + MachineFunctionPass(ID), + ShouldAllocateClass(F), + StackSlotForVirtReg(-1), + ClearVirtRegs(ClearVirtRegs_) { + } private: MachineFrameInfo *MFI; @@ -77,6 +84,7 @@ namespace { const TargetRegisterInfo *TRI; const TargetInstrInfo *TII; RegisterClassInfo RegClassInfo; + const RegClassFilterFunc ShouldAllocateClass; /// Basic block currently being allocated. MachineBasicBlock *MBB; @@ -84,6 +92,8 @@ namespace { /// Maps virtual regs to the frame index where these values are spilled. IndexedMap StackSlotForVirtReg; + bool ClearVirtRegs; + /// Everything we know about a live virtual register. struct LiveReg { MachineInstr *LastUse = nullptr; ///< Last instr to use reg. @@ -213,8 +223,12 @@ namespace { } MachineFunctionProperties getSetProperties() const override { - return MachineFunctionProperties().set( + if (ClearVirtRegs) { + return MachineFunctionProperties().set( MachineFunctionProperties::Property::NoVRegs); + } + + return MachineFunctionProperties(); } MachineFunctionProperties getClearedProperties() const override { @@ -1539,9 +1553,11 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) { for (MachineBasicBlock &MBB : MF) allocateBasicBlock(MBB); - // All machine operands and other references to virtual registers have been - // replaced. Remove the virtual registers. - MRI->clearVirtRegs(); + if (ClearVirtRegs) { + // All machine operands and other references to virtual registers have been + // replaced. Remove the virtual registers. + MRI->clearVirtRegs(); + } StackSlotForVirtReg.clear(); LiveDbgValueMap.clear(); @@ -1551,3 +1567,9 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) { FunctionPass *llvm::createFastRegisterAllocator() { return new RegAllocFast(); } + +FunctionPass *llvm::createFastRegisterAllocator( + std::function Ftor, bool ClearVirtRegs) { + return new RegAllocFast(Ftor, ClearVirtRegs); +} diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp index f71df3f0ad438..b58b700a5c451 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -412,7 +412,7 @@ class RAGreedy : public MachineFunctionPass, ArrayRef RegCosts; public: - RAGreedy(); + RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses); /// Return the pass name. StringRef getPassName() const override { return "Greedy Register Allocator"; } @@ -421,7 +421,7 @@ class RAGreedy : public MachineFunctionPass, void getAnalysisUsage(AnalysisUsage &AU) const override; void releaseMemory() override; Spiller &spiller() override { return *SpillerInstance; } - void enqueue(LiveInterval *LI) override; + void enqueueImpl(LiveInterval *LI) override; LiveInterval *dequeue() override; MCRegister selectOrSplit(LiveInterval &, SmallVectorImpl &) override; @@ -636,7 +636,22 @@ FunctionPass* llvm::createGreedyRegisterAllocator() { return new RAGreedy(); } -RAGreedy::RAGreedy(): MachineFunctionPass(ID) { +namespace llvm { +FunctionPass* createGreedyRegisterAllocator( + std::function Ftor); + +} + +FunctionPass* llvm::createGreedyRegisterAllocator( + std::function Ftor) { + return new RAGreedy(Ftor); +} + +RAGreedy::RAGreedy(RegClassFilterFunc F): + MachineFunctionPass(ID), + RegAllocBase(F) { } void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { @@ -693,7 +708,7 @@ void RAGreedy::LRE_WillShrinkVirtReg(Register VirtReg) { // Register is assigned, put it back on the queue for reassignment. LiveInterval &LI = LIS->getInterval(VirtReg); Matrix->unassign(LI); - enqueue(&LI); + RegAllocBase::enqueue(&LI); } void RAGreedy::LRE_DidCloneVirtReg(Register New, Register Old) { @@ -716,7 +731,7 @@ void RAGreedy::releaseMemory() { GlobalCand.clear(); } -void RAGreedy::enqueue(LiveInterval *LI) { enqueue(Queue, LI); } +void RAGreedy::enqueueImpl(LiveInterval *LI) { enqueue(Queue, LI); } void RAGreedy::enqueue(PQueue &CurQueue, LiveInterval *LI) { // Prioritize live ranges by size, assigning larger ranges first. @@ -2936,7 +2951,12 @@ void RAGreedy::tryHintRecoloring(LiveInterval &VirtReg) { if (Register::isPhysicalRegister(Reg)) continue; - assert(VRM->hasPhys(Reg) && "We have unallocated variable!!"); + // This may be a skipped class + if (!VRM->hasPhys(Reg)) { + assert(!ShouldAllocateClass(*TRI, *MRI->getRegClass(Reg)) && + "We have an unallocated variable which should have been handled"); + continue; + } // Get the live interval mapped with this virtual register to be able // to check for the interference with the new color. diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp index 3b75e0e4a20a0..ce5fa2cca647a 100644 --- a/llvm/lib/CodeGen/RegisterCoalescer.cpp +++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp @@ -2856,9 +2856,39 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) { if ((TRI->getSubRegIndexLaneMask(Other.SubIdx) & ~V.WriteLanes).none()) return CR_Impossible; - // We need to verify that no instructions are reading the clobbered lanes. To - // save compile time, we'll only check that locally. Don't allow the tainted - // value to escape the basic block. + if (TrackSubRegLiveness) { + auto &OtherLI = LIS->getInterval(Other.Reg); + // If OtherVNI does not have subranges, it means all the lanes of OtherVNI + // share the same live range, so we just need to check whether they have + // any conflict bit in their LaneMask. + if (!OtherLI.hasSubRanges()) { + LaneBitmask OtherMask = TRI->getSubRegIndexLaneMask(Other.SubIdx); + return (OtherMask & V.WriteLanes).none() ? CR_Replace : CR_Impossible; + } + + // If we are clobbering some active lanes of OtherVNI at VNI->def, it is + // impossible to resolve the conflict. Otherwise, we can just replace + // OtherVNI because of no real conflict. + for (LiveInterval::SubRange &OtherSR : OtherLI.subranges()) { + LaneBitmask OtherMask = + TRI->composeSubRegIndexLaneMask(Other.SubIdx, OtherSR.LaneMask); + if ((OtherMask & V.WriteLanes).none()) + continue; + + auto OtherSRQ = OtherSR.Query(VNI->def); + if (OtherSRQ.valueIn() && OtherSRQ.endPoint() > VNI->def) { + // VNI is clobbering some lanes of OtherVNI, they have real conflict. + return CR_Impossible; + } + } + + // VNI is NOT clobbering any lane of OtherVNI, just replace OtherVNI. + return CR_Replace; + } + + // We need to verify that no instructions are reading the clobbered lanes. + // To save compile time, we'll only check that locally. Don't allow the + // tainted value to escape the basic block. MachineBasicBlock *MBB = Indexes->getMBBFromIndex(VNI->def); if (OtherLRQ.endPoint() >= Indexes->getMBBEndIdx(MBB)) return CR_Impossible; diff --git a/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp b/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp new file mode 100644 index 0000000000000..de6129a912d32 --- /dev/null +++ b/llvm/lib/CodeGen/RemoveRedundantDebugValues.cpp @@ -0,0 +1,231 @@ +//===- RemoveRedundantDebugValues.cpp - Remove Redundant Debug Value MIs --===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" + +/// \file RemoveRedundantDebugValues.cpp +/// +/// The RemoveRedundantDebugValues pass removes redundant DBG_VALUEs that +/// appear in MIR after the register allocator. + +#define DEBUG_TYPE "removeredundantdebugvalues" + +using namespace llvm; + +STATISTIC(NumRemovedBackward, "Number of DBG_VALUEs removed (backward scan)"); +STATISTIC(NumRemovedForward, "Number of DBG_VALUEs removed (forward scan)"); + +namespace { + +class RemoveRedundantDebugValues : public MachineFunctionPass { +public: + static char ID; + + RemoveRedundantDebugValues(); + + bool reduceDbgValues(MachineFunction &MF); + + /// Remove redundant debug value MIs for the given machine function. + bool runOnMachineFunction(MachineFunction &MF) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } +}; + +} // namespace + +//===----------------------------------------------------------------------===// +// Implementation +//===----------------------------------------------------------------------===// + +char RemoveRedundantDebugValues::ID = 0; + +char &llvm::RemoveRedundantDebugValuesID = RemoveRedundantDebugValues::ID; + +INITIALIZE_PASS(RemoveRedundantDebugValues, DEBUG_TYPE, + "Remove Redundant DEBUG_VALUE analysis", false, false) + +/// Default construct and initialize the pass. +RemoveRedundantDebugValues::RemoveRedundantDebugValues() + : MachineFunctionPass(ID) { + initializeRemoveRedundantDebugValuesPass(*PassRegistry::getPassRegistry()); +} + +// This analysis aims to remove redundant DBG_VALUEs by going forward +// in the basic block by considering the first DBG_VALUE as a valid +// until its first (location) operand is not clobbered/modified. +// For example: +// (1) DBG_VALUE $edi, !"var1", ... +// (2) +// (3) DBG_VALUE $edi, !"var1", ... +// ... +// in this case, we can remove (3). +// TODO: Support DBG_VALUE_LIST and other debug instructions. +static bool reduceDbgValsForwardScan(MachineBasicBlock &MBB) { + LLVM_DEBUG(dbgs() << "\n == Forward Scan == \n"); + + SmallVector DbgValsToBeRemoved; + DenseMap> + VariableMap; + const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo(); + + for (auto &MI : MBB) { + if (MI.isDebugValue()) { + DebugVariable Var(MI.getDebugVariable(), NoneType(), + MI.getDebugLoc()->getInlinedAt()); + auto VMI = VariableMap.find(Var); + // Just stop tracking this variable, until we cover DBG_VALUE_LIST. + // 1 DBG_VALUE $rax, "x", DIExpression() + // ... + // 2 DBG_VALUE_LIST "x", DIExpression(...), $rax, $rbx + // ... + // 3 DBG_VALUE $rax, "x", DIExpression() + if (MI.isDebugValueList() && VMI != VariableMap.end()) { + VariableMap.erase(VMI); + continue; + } + + MachineOperand &Loc = MI.getDebugOperand(0); + if (!Loc.isReg()) { + // If it it's not a register, just stop tracking such variable. + if (VMI != VariableMap.end()) + VariableMap.erase(VMI); + continue; + } + + // We have found a new value for a variable. + if (VMI == VariableMap.end() || + VMI->second.first->getReg() != Loc.getReg() || + VMI->second.second != MI.getDebugExpression()) { + VariableMap[Var] = {&Loc, MI.getDebugExpression()}; + continue; + } + + // Found an identical DBG_VALUE, so it can be considered + // for later removal. + DbgValsToBeRemoved.push_back(&MI); + } + + if (MI.isMetaInstruction()) + continue; + + // Stop tracking any location that is clobbered by this instruction. + for (auto &Var : VariableMap) { + auto &LocOp = Var.second.first; + if (MI.modifiesRegister(LocOp->getReg(), TRI)) + VariableMap.erase(Var.first); + } + } + + for (auto &Instr : DbgValsToBeRemoved) { + LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); + Instr->eraseFromParent(); + ++NumRemovedForward; + } + + return !DbgValsToBeRemoved.empty(); +} + +// This analysis aims to remove redundant DBG_VALUEs by going backward +// in the basic block and removing all but the last DBG_VALUE for any +// given variable in a set of consecutive DBG_VALUE instructions. +// For example: +// (1) DBG_VALUE $edi, !"var1", ... +// (2) DBG_VALUE $esi, !"var2", ... +// (3) DBG_VALUE $edi, !"var1", ... +// ... +// in this case, we can remove (1). +static bool reduceDbgValsBackwardScan(MachineBasicBlock &MBB) { + LLVM_DEBUG(dbgs() << "\n == Backward Scan == \n"); + SmallVector DbgValsToBeRemoved; + SmallDenseSet VariableSet; + + for (MachineBasicBlock::reverse_iterator I = MBB.rbegin(), E = MBB.rend(); + I != E; ++I) { + MachineInstr *MI = &*I; + + if (MI->isDebugValue()) { + DebugVariable Var(MI->getDebugVariable(), MI->getDebugExpression(), + MI->getDebugLoc()->getInlinedAt()); + auto R = VariableSet.insert(Var); + // If it is a DBG_VALUE describing a constant as: + // DBG_VALUE 0, ... + // we just don't consider such instructions as candidates + // for redundant removal. + if (MI->isNonListDebugValue()) { + MachineOperand &Loc = MI->getDebugOperand(0); + if (!Loc.isReg()) { + // If we have already encountered this variable, just stop + // tracking it. + if (!R.second) + VariableSet.erase(Var); + continue; + } + } + + // We have already encountered the value for this variable, + // so this one can be deleted. + if (!R.second) + DbgValsToBeRemoved.push_back(MI); + continue; + } + + // If we encountered a non-DBG_VALUE, try to find the next + // sequence with consecutive DBG_VALUE instructions. + VariableSet.clear(); + } + + for (auto &Instr : DbgValsToBeRemoved) { + LLVM_DEBUG(dbgs() << "removing "; Instr->dump()); + Instr->eraseFromParent(); + ++NumRemovedBackward; + } + + return !DbgValsToBeRemoved.empty(); +} + +bool RemoveRedundantDebugValues::reduceDbgValues(MachineFunction &MF) { + LLVM_DEBUG(dbgs() << "\nDebug Value Reduction\n"); + + bool Changed = false; + + for (auto &MBB : MF) { + Changed |= reduceDbgValsBackwardScan(MBB); + Changed |= reduceDbgValsForwardScan(MBB); + } + + return Changed; +} + +bool RemoveRedundantDebugValues::runOnMachineFunction(MachineFunction &MF) { + // Skip functions without debugging information. + if (!MF.getFunction().getSubprogram()) + return false; + + // Skip functions from NoDebug compilation units. + if (MF.getFunction().getSubprogram()->getUnit()->getEmissionKind() == + DICompileUnit::NoDebug) + return false; + + bool Changed = reduceDbgValues(MF); + return Changed; +} diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 1a47af6fc16fc..7ff01fa0aff64 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -546,6 +546,7 @@ namespace { SDValue foldSignChangeInBitcast(SDNode *N); SDValue foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC); + SDValue foldSelectOfBinops(SDNode *N); SDValue foldSextSetcc(SDNode *N); SDValue foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1, const SDLoc &DL); @@ -3209,7 +3210,7 @@ SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N) { // Try to find umax(a,b) - b or a - umin(a,b) patterns // they may be converted to usubsat(a,b). - if (Op0.getOpcode() == ISD::UMAX) { + if (Op0.getOpcode() == ISD::UMAX && Op0.hasOneUse()) { SDValue MaxLHS = Op0.getOperand(0); SDValue MaxRHS = Op0.getOperand(1); if (MaxLHS == Op1) @@ -3218,7 +3219,7 @@ SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N) { return getTruncatedUSUBSAT(DstVT, SubVT, MaxLHS, Op1, DAG, SDLoc(N)); } - if (Op1.getOpcode() == ISD::UMIN) { + if (Op1.getOpcode() == ISD::UMIN && Op1.hasOneUse()) { SDValue MinLHS = Op1.getOperand(0); SDValue MinRHS = Op1.getOperand(1); if (MinLHS == Op0) @@ -3229,7 +3230,8 @@ SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N) { // sub(a,trunc(umin(zext(a),b))) -> usubsat(a,trunc(umin(b,SatLimit))) if (Op1.getOpcode() == ISD::TRUNCATE && - Op1.getOperand(0).getOpcode() == ISD::UMIN) { + Op1.getOperand(0).getOpcode() == ISD::UMIN && + Op1.getOperand(0).hasOneUse()) { SDValue MinLHS = Op1.getOperand(0).getOperand(0); SDValue MinRHS = Op1.getOperand(0).getOperand(1); if (MinLHS.getOpcode() == ISD::ZERO_EXTEND && MinLHS.getOperand(0) == Op0) @@ -9642,9 +9644,14 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) { return SelectNode; } - return SimplifySelect(DL, N0, N1, N2); + if (SDValue NewSel = SimplifySelect(DL, N0, N1, N2)) + return NewSel; } + if (!VT.isVector()) + if (SDValue BinOp = foldSelectOfBinops(N)) + return BinOp; + return SDValue(); } @@ -22363,6 +22370,50 @@ SDValue DAGCombiner::foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, return DAG.getNode(ISD::AND, DL, AType, Shift, N2); } +// Fold select(cc, binop(), binop()) -> binop(select(), select()) etc. +SDValue DAGCombiner::foldSelectOfBinops(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + EVT VT = N->getValueType(0); + SDLoc DL(N); + + unsigned BinOpc = N1.getOpcode(); + if (!TLI.isBinOp(BinOpc) || (N2.getOpcode() != BinOpc)) + return SDValue(); + + if (!N->isOnlyUserOf(N0.getNode()) || !N->isOnlyUserOf(N1.getNode())) + return SDValue(); + + // Fold select(cond, binop(x, y), binop(z, y)) + // --> binop(select(cond, x, z), y) + if (N1.getOperand(1) == N2.getOperand(1)) { + SDValue NewSel = + DAG.getSelect(DL, VT, N0, N1.getOperand(0), N2.getOperand(0)); + SDValue NewBinOp = DAG.getNode(BinOpc, DL, VT, NewSel, N1.getOperand(1)); + NewBinOp->setFlags(N1->getFlags()); + NewBinOp->intersectFlagsWith(N2->getFlags()); + return NewBinOp; + } + + // Fold select(cond, binop(x, y), binop(x, z)) + // --> binop(x, select(cond, y, z)) + // Second op VT might be different (e.g. shift amount type) + if (N1.getOperand(0) == N2.getOperand(0) && + VT == N1.getOperand(1).getValueType() && + VT == N2.getOperand(1).getValueType()) { + SDValue NewSel = + DAG.getSelect(DL, VT, N0, N1.getOperand(1), N2.getOperand(1)); + SDValue NewBinOp = DAG.getNode(BinOpc, DL, VT, N1.getOperand(0), NewSel); + NewBinOp->setFlags(N1->getFlags()); + NewBinOp->intersectFlagsWith(N2->getFlags()); + return NewBinOp; + } + + // TODO: Handle isCommutativeBinOp patterns as well? + return SDValue(); +} + // Transform (fneg/fabs (bitconvert x)) to avoid loading constant pool values. SDValue DAGCombiner::foldSignChangeInBitcast(SDNode *N) { SDValue N0 = N->getOperand(0); diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index ec40ddc1ff750..4ca731cfdf622 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1033,7 +1033,7 @@ bool FastISel::lowerCallTo(CallLoweringInfo &CLI) { for (auto &Arg : CLI.getArgs()) { Type *FinalType = Arg.Ty; if (Arg.IsByVal) - FinalType = cast(Arg.Ty)->getElementType(); + FinalType = Arg.IndirectType; bool NeedsRegBlock = TLI.functionArgumentNeedsConsecutiveRegisters( FinalType, CLI.CallConv, CLI.IsVarArg, DL); @@ -1256,9 +1256,21 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) { "Expected inlined-at fields to agree"); // A dbg.declare describes the address of a source variable, so lower it // into an indirect DBG_VALUE. - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true, - *Op, DI->getVariable(), DI->getExpression()); + auto Builder = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true, *Op, + DI->getVariable(), DI->getExpression()); + + // If using instruction referencing, mutate this into a DBG_INSTR_REF, + // to be later patched up by finalizeDebugInstrRefs. Tack a deref onto + // the expression, we don't have an "indirect" flag in DBG_INSTR_REF. + if (TM.Options.ValueTrackingVariableLocations && Op->isReg()) { + Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); + Builder->getOperand(1).ChangeToImmediate(0); + auto *NewExpr = + DIExpression::prepend(DI->getExpression(), DIExpression::DerefBefore); + Builder->getOperand(3).setMetadata(NewExpr); + } } else { // We can't yet handle anything else here because it would require // generating code, thus altering codegen because of debug info. @@ -1301,8 +1313,16 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) { } else if (Register Reg = lookUpRegForValue(V)) { // FIXME: This does not handle register-indirect values at offset 0. bool IsIndirect = false; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg, - DI->getVariable(), DI->getExpression()); + auto Builder = + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg, + DI->getVariable(), DI->getExpression()); + + // If using instruction referencing, mutate this into a DBG_INSTR_REF, + // to be later patched up by finalizeDebugInstrRefs. + if (TM.Options.ValueTrackingVariableLocations) { + Builder->setDesc(TII.get(TargetOpcode::DBG_INSTR_REF)); + Builder->getOperand(1).ChangeToImmediate(0); + } } else { // We don't know how to handle other cases, so we drop. LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n"); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 7dc0cd0cc4f37..5eded16a207c5 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -2247,6 +2247,10 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { case ISD::FSHR: ExpandIntRes_FunnelShift(N, Lo, Hi); break; + + case ISD::VSCALE: + ExpandIntRes_VSCALE(N, Lo, Hi); + break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -4198,6 +4202,21 @@ void DAGTypeLegalizer::ExpandIntRes_FunnelShift(SDNode *N, SplitInteger(Res, Lo, Hi); } +void DAGTypeLegalizer::ExpandIntRes_VSCALE(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT VT = N->getValueType(0); + EVT HalfVT = + EVT::getIntegerVT(*DAG.getContext(), N->getValueSizeInBits(0) / 2); + SDLoc dl(N); + + // We assume VSCALE(1) fits into a legal integer. + APInt One(HalfVT.getSizeInBits(), 1); + SDValue VScaleBase = DAG.getVScale(dl, HalfVT, One); + VScaleBase = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, VScaleBase); + SDValue Res = DAG.getNode(ISD::MUL, dl, VT, VScaleBase, N->getOperand(0)); + SplitInteger(Res, Lo, Hi); +} + //===----------------------------------------------------------------------===// // Integer Operand Expansion //===----------------------------------------------------------------------===// @@ -4741,38 +4760,15 @@ SDValue DAGTypeLegalizer::PromoteIntRes_INSERT_SUBVECTOR(SDNode *N) { SDValue SubVec = N->getOperand(1); SDValue Idx = N->getOperand(2); - auto *ConstantIdx = cast(Idx); - unsigned IdxN = ConstantIdx->getZExtValue(); - - EVT VecVT = Vec.getValueType(); EVT SubVecVT = SubVec.getValueType(); + EVT NSubVT = + EVT::getVectorVT(*DAG.getContext(), NOutVT.getVectorElementType(), + SubVecVT.getVectorElementCount()); - // To insert SubVec into Vec, store the wider vector to memory, overwrite the - // appropriate bits with the narrower vector, and reload. - Align SmallestAlign = DAG.getReducedAlign(SubVecVT, /*UseABI=*/false); - - SDValue StackPtr = - DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign); - auto StackPtrVT = StackPtr->getValueType(0); - auto &MF = DAG.getMachineFunction(); - auto FrameIndex = cast(StackPtr.getNode())->getIndex(); - auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex); - - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo, - SmallestAlign); - - SDValue ScaledIdx = Idx; - if (SubVecVT.isScalableVector() && IdxN != 0) { - APInt IdxAPInt = cast(Idx)->getAPIntValue(); - ScaledIdx = DAG.getVScale(dl, StackPtrVT, - IdxAPInt.sextOrSelf(StackPtrVT.getSizeInBits())); - } + Vec = GetPromotedInteger(Vec); + SubVec = DAG.getNode(ISD::ANY_EXTEND, dl, NSubVT, SubVec); - SDValue SubVecPtr = - TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, ScaledIdx); - Store = DAG.getStore(Store, dl, SubVec, SubVecPtr, PtrInfo, SmallestAlign); - return DAG.getExtLoad(ISD::LoadExtType::EXTLOAD, dl, NOutVT, Store, StackPtr, - PtrInfo, OutVT, SmallestAlign); + return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, NOutVT, Vec, SubVec, Idx); } SDValue DAGTypeLegalizer::PromoteIntRes_VECTOR_REVERSE(SDNode *N) { diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 9051899a9652c..8d17d8fc68b15 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -465,6 +465,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { void ExpandIntRes_Rotate (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_FunnelShift (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_VSCALE (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandShiftByConstant(SDNode *N, const APInt &Amt, SDValue &Lo, SDValue &Hi); bool ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 0dbcfefaedcdb..e058c40ce6ff6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1747,6 +1747,11 @@ SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) { return SDValue(CondCodeNodes[Cond], 0); } +SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT) { + EVT OpVT = TLI->getTypeToTransformTo(*getContext(), ResVT.getScalarType()); + return getStepVector(DL, ResVT, getConstant(1, DL, OpVT)); +} + SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT, SDValue Step) { if (ResVT.isScalableVector()) return getNode(ISD::STEP_VECTOR, DL, ResVT, Step); @@ -2441,15 +2446,6 @@ bool SelectionDAG::MaskedValueIsZero(SDValue V, const APInt &Mask, return Mask.isSubsetOf(computeKnownBits(V, DemandedElts, Depth).Zero); } -/// Return true if the DemandedElts of the vector Op are all zero. We -/// use this predicate to simplify operations downstream. -bool SelectionDAG::MaskedElementsAreZero(SDValue Op, const APInt &DemandedElts, - unsigned Depth) const { - unsigned BitWidth = Op.getScalarValueSizeInBits(); - APInt DemandedBits = APInt::getAllOnesValue(BitWidth); - return MaskedValueIsZero(Op, DemandedBits, DemandedElts, Depth); -} - /// MaskedValueIsAllOnes - Return true if '(Op & Mask) == Mask'. bool SelectionDAG::MaskedValueIsAllOnes(SDValue V, const APInt &Mask, unsigned Depth) const { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 5827a5f7fd4c0..d56d4bcc91693 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -9535,7 +9535,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { // FIXME: Split arguments if CLI.IsPostTypeLegalization Type *FinalType = Args[i].Ty; if (Args[i].IsByVal) - FinalType = cast(Args[i].Ty)->getElementType(); + FinalType = Args[i].IndirectType; bool NeedsRegBlock = functionArgumentNeedsConsecutiveRegisters( FinalType, CLI.CallConv, CLI.IsVarArg, DL); for (unsigned Value = 0, NumValues = ValueVTs.size(); Value != NumValues; @@ -11074,10 +11074,7 @@ void SelectionDAGBuilder::visitStepVector(const CallInst &I) { const TargetLowering &TLI = DAG.getTargetLoweringInfo(); auto DL = getCurSDLoc(); EVT ResultVT = TLI.getValueType(DAG.getDataLayout(), I.getType()); - EVT OpVT = - TLI.getTypeToTransformTo(*DAG.getContext(), ResultVT.getScalarType()); - SDValue Step = DAG.getConstant(1, DL, OpVT); - setValue(&I, DAG.getStepVector(DL, ResultVT, Step)); + setValue(&I, DAG.getStepVector(DL, ResultVT)); } void SelectionDAGBuilder::visitVectorReverse(const CallInst &I) { diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index bc033b06e7a54..71e90c3753b0a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5924,7 +5924,7 @@ TargetLowering::prepareSREMEqFold(EVT SETCCVT, SDValue REMNode, if (!isOperationLegalOrCustom(ISD::SETEQ, VT) || !isOperationLegalOrCustom(ISD::AND, VT) || !isOperationLegalOrCustom(Cond, VT) || - !isOperationLegalOrCustom(ISD::VSELECT, VT)) + !isOperationLegalOrCustom(ISD::VSELECT, SETCCVT)) return SDValue(); Created.push_back(Fold.getNode()); @@ -5950,8 +5950,8 @@ TargetLowering::prepareSREMEqFold(EVT SETCCVT, SDValue REMNode, // 'MaskedIsZero'. If the divisor for channel was *NOT* INT_MIN, we pick // from 'Fold', else pick from 'MaskedIsZero'. Since 'DivisorIsIntMin' is // constant-folded, select can get lowered to a shuffle with constant mask. - SDValue Blended = - DAG.getNode(ISD::VSELECT, DL, VT, DivisorIsIntMin, MaskedIsZero, Fold); + SDValue Blended = DAG.getNode(ISD::VSELECT, DL, SETCCVT, DivisorIsIntMin, + MaskedIsZero, Fold); return Blended; } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index ace475dbe86f9..56fdbc13a2bbf 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1480,11 +1480,10 @@ static bool canUsePrivateLabel(const MCAsmInfo &AsmInfo, if (!AsmInfo.isSectionAtomizableBySymbols(Section)) return true; - // If it is not dead stripped, it is safe to use private labels. - const MCSectionMachO &SMO = cast(Section); - if (SMO.hasAttribute(MachO::S_ATTR_NO_DEAD_STRIP)) - return true; - + // FIXME: we should be able to use private labels for sections that can't be + // dead-stripped (there's no issue with blocking atomization there), but `ld + // -r` sometimes drops the no_dead_strip attribute from sections so for safety + // we don't allow it. return false; } diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 2a4f6bfd98b03..4024fd452fc45 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -1123,6 +1123,8 @@ void TargetPassConfig::addMachinePasses() { // Run post-ra passes. addPostRegAlloc(); + addPass(&RemoveRedundantDebugValuesID, false); + addPass(&FixupStatepointCallerSavedID); // Insert prolog/epilog code. Eliminate abstract frame index references... @@ -1333,8 +1335,8 @@ FunctionPass *TargetPassConfig::createRegAllocPass(bool Optimized) { } bool TargetPassConfig::addRegAssignAndRewriteFast() { - if (RegAlloc != &useDefaultRegisterAllocator && - RegAlloc != &createFastRegisterAllocator) + if (RegAlloc != (RegisterRegAlloc::FunctionPassCtor)&useDefaultRegisterAllocator && + RegAlloc != (RegisterRegAlloc::FunctionPassCtor)&createFastRegisterAllocator) report_fatal_error("Must use fast (default) register allocator for unoptimized regalloc."); addPass(createRegAllocPass(false)); diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp index bd20f32ee2534..1664b4dadfec9 100644 --- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -527,6 +527,11 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA, if (isRevCopyChain(RegB, RegA, MaxDataFlowEdge)) return false; + // Look for other target specific commute preference. + bool Commute; + if (TII->hasCommutePreference(*MI, Commute)) + return Commute; + // Since there are no intervening uses for both registers, then commute // if the def of RegC is closer. Its live interval is shorter. return LastDefB && LastDefC && LastDefC > LastDefB; diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp index 69390c708f599..d12f6c796e500 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewError.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 79d18faf14474..f17dacfce6656 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -591,10 +591,7 @@ bool DWARFUnit::parseDWO() { // Share .debug_addr and .debug_ranges section with compile unit in .dwo if (AddrOffsetSectionBase) DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); - if (getVersion() >= 5) { - DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), - DWARFListTableHeader::getHeaderSize(getFormat())); - } else { + if (getVersion() == 4) { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); } diff --git a/llvm/lib/DebugInfo/MSF/MSFError.cpp b/llvm/lib/DebugInfo/MSF/MSFError.cpp index f068d3334955b..e42157e9d48e1 100644 --- a/llvm/lib/DebugInfo/MSF/MSFError.cpp +++ b/llvm/lib/DebugInfo/MSF/MSFError.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/MSF/MSFError.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include using namespace llvm; using namespace llvm::msf; diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 33a25010d1333..72ca722305074 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -210,8 +210,8 @@ namespace { // /path/to/foo.dSYM/Contents/Resources/DWARF/foo. // For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in // /path/to/bar.dSYM/Contents/Resources/DWARF/foo. -std::string getDarwinDWARFResourceForPath( - const std::string &Path, const std::string &Basename) { +std::string getDarwinDWARFResourceForPath(const std::string &Path, + const std::string &Basename) { SmallString<16> ResourceName = StringRef(Path); if (sys::path::extension(Path) != ".dSYM") { ResourceName += ".dSYM"; @@ -330,7 +330,8 @@ Optional> getBuildID(const ELFFile &Obj) { continue; Error Err = Error::success(); for (auto N : Obj.notes(P, Err)) - if (N.getType() == ELF::NT_GNU_BUILD_ID && N.getName() == ELF::ELF_NOTE_GNU) + if (N.getType() == ELF::NT_GNU_BUILD_ID && + N.getName() == ELF::ELF_NOTE_GNU) return N.getDesc(); consumeError(std::move(Err)); } @@ -353,8 +354,7 @@ Optional> getBuildID(const ELFObjectFileBase *Obj) { } bool findDebugBinary(const std::vector &DebugFileDirectory, - const ArrayRef BuildID, - std::string &Result) { + const ArrayRef BuildID, std::string &Result) { auto getDebugPath = [&](StringRef Directory) { SmallString<128> Path{Directory}; sys::path::append(Path, ".build-id", @@ -366,11 +366,11 @@ bool findDebugBinary(const std::vector &DebugFileDirectory, if (DebugFileDirectory.empty()) { SmallString<128> Path = getDebugPath( #if defined(__NetBSD__) - // Try /usr/libdata/debug/.build-id/../... - "/usr/libdata/debug" + // Try /usr/libdata/debug/.build-id/../... + "/usr/libdata/debug" #else - // Try /usr/lib/debug/.build-id/../... - "/usr/lib/debug" + // Try /usr/lib/debug/.build-id/../... + "/usr/lib/debug" #endif ); if (llvm::sys::fs::exists(Path)) { @@ -393,7 +393,8 @@ bool findDebugBinary(const std::vector &DebugFileDirectory, } // end anonymous namespace ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, - const MachOObjectFile *MachExeObj, const std::string &ArchName) { + const MachOObjectFile *MachExeObj, + const std::string &ArchName) { // On Darwin we may find DWARF in separate object file in // resource directory. std::vector DsymPaths; @@ -653,7 +654,8 @@ LLVMSymbolizer::DemangleName(const std::string &Name, // approach to check if the name should be demangled. if (Name.substr(0, 2) == "_Z") { int status = 0; - char *DemangledName = itaniumDemangle(Name.c_str(), nullptr, nullptr, &status); + char *DemangledName = + itaniumDemangle(Name.c_str(), nullptr, nullptr, &status); if (status != 0) return Name; std::string Result = DemangledName; diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index a98d9fe45fe18..303207176be71 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -1713,7 +1713,7 @@ CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { return CallingConv::Vectorcall; case 'S': return CallingConv::Swift; - case 'T': + case 'W': return CallingConv::SwiftAsync; } diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp index 68878f6729e98..5b73c0e2fbc81 100644 --- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp @@ -7,12 +7,12 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" - #include "llvm/ADT/Hashing.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/Support/FormatVariadic.h" +#include using namespace llvm; using namespace llvm::orc; diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp index f6ebfc318bfd9..c613c57c15f87 100644 --- a/llvm/lib/ExecutionEngine/Orc/Core.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp @@ -1750,6 +1750,49 @@ Expected> Platform::lookupInitSymbols( return std::move(CompoundResult); } +void Platform::lookupInitSymbolsAsync( + unique_function OnComplete, ExecutionSession &ES, + const DenseMap &InitSyms) { + + class TriggerOnComplete { + public: + using OnCompleteFn = unique_function; + TriggerOnComplete(OnCompleteFn OnComplete) + : OnComplete(std::move(OnComplete)) {} + ~TriggerOnComplete() { OnComplete(std::move(LookupResult)); } + void reportResult(Error Err) { + std::lock_guard Lock(ResultMutex); + LookupResult = joinErrors(std::move(LookupResult), std::move(Err)); + } + + private: + std::mutex ResultMutex; + Error LookupResult{Error::success()}; + OnCompleteFn OnComplete; + }; + + LLVM_DEBUG({ + dbgs() << "Issuing init-symbol lookup:\n"; + for (auto &KV : InitSyms) + dbgs() << " " << KV.first->getName() << ": " << KV.second << "\n"; + }); + + auto TOC = std::make_shared(std::move(OnComplete)); + + for (auto &KV : InitSyms) { + auto *JD = KV.first; + auto Names = std::move(KV.second); + ES.lookup( + LookupKind::Static, + JITDylibSearchOrder({{JD, JITDylibLookupFlags::MatchAllSymbols}}), + std::move(Names), SymbolState::Ready, + [TOC](Expected Result) { + TOC->reportResult(Result.takeError()); + }, + NoDependenciesToRegister); + } +} + void Task::anchor() {} void MaterializationTask::printDescription(raw_ostream &OS) { diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 6a1a41a13a1be..7a76a6ccc1226 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" - #include "llvm/ExecutionEngine/Orc/Layer.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" @@ -17,6 +16,7 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" +#include namespace llvm { namespace orc { diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp index 12fa42ccdef6b..9442eab299708 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp @@ -14,6 +14,8 @@ #include "llvm/Support/Host.h" #include "llvm/Support/Process.h" +#define DEBUG_TYPE "orc" + namespace llvm { namespace orc { @@ -47,6 +49,10 @@ Error ExecutorProcessControl::associateJITSideWrapperFunctions( "AsyncWrapperFunction implementation missing"); TagToFunc[KV.second.getAddress()] = std::make_shared(std::move(I->second)); + LLVM_DEBUG({ + dbgs() << "Associated function tag \"" << *KV.first << "\" (" + << formatv("{0:x}", KV.second.getAddress()) << ") with handler\n"; + }); } return Error::success(); } @@ -84,6 +90,8 @@ SelfExecutorProcessControl::SelfExecutorProcessControl( this->PageSize = PageSize; this->MemMgr = OwnedMemMgr.get(); this->MemAccess = this; + this->JDI = {ExecutorAddress::fromPtr(jitDispatchViaWrapperFunctionManager), + ExecutorAddress::fromPtr(this)}; if (this->TargetTriple.isOSBinFormatMachO()) GlobalManglingPrefix = '_'; } @@ -198,5 +206,26 @@ void SelfExecutorProcessControl::writeBuffers( OnWriteComplete(Error::success()); } +shared::detail::CWrapperFunctionResult +SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager( + void *Ctx, const void *FnTag, const char *Data, size_t Size) { + + LLVM_DEBUG({ + dbgs() << "jit-dispatch call with tag " << FnTag << " and " << Size + << " byte payload.\n"; + }); + + std::promise ResultP; + auto ResultF = ResultP.get_future(); + static_cast(Ctx)->runJITSideWrapperFunction( + [ResultP = + std::move(ResultP)](shared::WrapperFunctionResult Result) mutable { + ResultP.set_value(std::move(Result)); + }, + pointerToJITTargetAddress(FnTag), {Data, Size}); + + return ResultF.get().release(); +} + } // end namespace orc } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index 08fd86b7979b1..2d1f394a5fb97 100644 --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -502,397 +502,6 @@ GlobalCtorDtorScraper::operator()(ThreadSafeModule TSM, return std::move(TSM); } -class MachOPlatformSupport : public LLJIT::PlatformSupport { -public: - using DLOpenType = void *(*)(const char *Name, int Mode); - using DLCloseType = int (*)(void *Handle); - using DLSymType = void *(*)(void *Handle, const char *Name); - using DLErrorType = const char *(*)(); - - struct DlFcnValues { - Optional RTLDDefault; - DLOpenType dlopen = nullptr; - DLCloseType dlclose = nullptr; - DLSymType dlsym = nullptr; - DLErrorType dlerror = nullptr; - }; - - static Expected> - Create(LLJIT &J, JITDylib &PlatformJITDylib) { - - // Make process symbols visible. - { - std::string ErrMsg; - auto Lib = sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg); - if (!Lib.isValid()) - return make_error(std::move(ErrMsg), - inconvertibleErrorCode()); - } - - DlFcnValues DlFcn; - - // Add support for RTLDDefault on known platforms. -#ifdef __APPLE__ - DlFcn.RTLDDefault = reinterpret_cast(-2); -#endif // __APPLE__ - - if (auto Err = hookUpFunction(DlFcn.dlopen, "dlopen")) - return std::move(Err); - if (auto Err = hookUpFunction(DlFcn.dlclose, "dlclose")) - return std::move(Err); - if (auto Err = hookUpFunction(DlFcn.dlsym, "dlsym")) - return std::move(Err); - if (auto Err = hookUpFunction(DlFcn.dlerror, "dlerror")) - return std::move(Err); - - std::unique_ptr MP( - new MachOPlatformSupport(J, PlatformJITDylib, DlFcn)); - return std::move(MP); - } - - Error initialize(JITDylib &JD) override { - LLVM_DEBUG({ - dbgs() << "MachOPlatformSupport initializing \"" << JD.getName() - << "\"\n"; - }); - - auto InitSeq = MP.getInitializerSequence(JD); - if (!InitSeq) - return InitSeq.takeError(); - - // If ObjC is not enabled but there are JIT'd ObjC inits then return - // an error. - if (!objCRegistrationEnabled()) - for (auto &KV : *InitSeq) { - if (!KV.second.getObjCSelRefsSections().empty() || - !KV.second.getObjCClassListSections().empty()) - return make_error("JITDylib " + KV.first->getName() + - " contains objc metadata but objc" - " is not enabled", - inconvertibleErrorCode()); - } - - // Run the initializers. - for (auto &KV : *InitSeq) { - if (objCRegistrationEnabled()) { - KV.second.registerObjCSelectors(); - if (auto Err = KV.second.registerObjCClasses()) { - // FIXME: Roll back registrations on error? - return Err; - } - } - KV.second.runModInits(); - } - - return Error::success(); - } - - Error deinitialize(JITDylib &JD) override { - auto &ES = J.getExecutionSession(); - if (auto DeinitSeq = MP.getDeinitializerSequence(JD)) { - for (auto &KV : *DeinitSeq) { - auto DSOHandleName = ES.intern("___dso_handle"); - - // FIXME: Run DeInits here. - auto Result = ES.lookup( - {{KV.first, JITDylibLookupFlags::MatchAllSymbols}}, - SymbolLookupSet(DSOHandleName, - SymbolLookupFlags::WeaklyReferencedSymbol)); - if (!Result) - return Result.takeError(); - if (Result->empty()) - continue; - assert(Result->count(DSOHandleName) && - "Result does not contain __dso_handle"); - auto *DSOHandle = jitTargetAddressToPointer( - Result->begin()->second.getAddress()); - AtExitMgr.runAtExits(DSOHandle); - } - } else - return DeinitSeq.takeError(); - return Error::success(); - } - -private: - template - static Error hookUpFunction(FunctionPtrTy &Fn, const char *Name) { - if (auto *FnAddr = sys::DynamicLibrary::SearchForAddressOfSymbol(Name)) { - Fn = reinterpret_cast(Fn); - return Error::success(); - } - - return make_error((Twine("Can not enable MachO JIT Platform: " - "missing function: ") + - Name) - .str(), - inconvertibleErrorCode()); - } - - MachOPlatformSupport(LLJIT &J, JITDylib &PlatformJITDylib, DlFcnValues DlFcn) - : J(J), MP(setupPlatform(J)), DlFcn(std::move(DlFcn)) { - - SymbolMap HelperSymbols; - - // platform and atexit helpers. - HelperSymbols[J.mangleAndIntern("__lljit.platform_support_instance")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(this), JITSymbolFlags()); - HelperSymbols[J.mangleAndIntern("__lljit.cxa_atexit_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(registerAtExitHelper), - JITSymbolFlags()); - HelperSymbols[J.mangleAndIntern("__lljit.run_atexits_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(runAtExitsHelper), - JITSymbolFlags()); - - // dlfcn helpers. - HelperSymbols[J.mangleAndIntern("__lljit.dlopen_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(dlopenHelper), - JITSymbolFlags()); - HelperSymbols[J.mangleAndIntern("__lljit.dlclose_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(dlcloseHelper), - JITSymbolFlags()); - HelperSymbols[J.mangleAndIntern("__lljit.dlsym_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(dlsymHelper), - JITSymbolFlags()); - HelperSymbols[J.mangleAndIntern("__lljit.dlerror_helper")] = - JITEvaluatedSymbol(pointerToJITTargetAddress(dlerrorHelper), - JITSymbolFlags()); - - cantFail( - PlatformJITDylib.define(absoluteSymbols(std::move(HelperSymbols)))); - cantFail(MP.setupJITDylib(J.getMainJITDylib())); - cantFail(J.addIRModule(PlatformJITDylib, createPlatformRuntimeModule())); - } - - static MachOPlatform &setupPlatform(LLJIT &J) { - auto Tmp = std::make_unique( - J.getExecutionSession(), - static_cast(J.getObjLinkingLayer()), - createStandardSymbolsObject(J)); - auto &MP = *Tmp; - J.getExecutionSession().setPlatform(std::move(Tmp)); - return MP; - } - - static std::unique_ptr createStandardSymbolsObject(LLJIT &J) { - LLVMContext Ctx; - Module M("__standard_symbols", Ctx); - M.setDataLayout(J.getDataLayout()); - - auto *Int64Ty = Type::getInt64Ty(Ctx); - - auto *DSOHandle = - new GlobalVariable(M, Int64Ty, true, GlobalValue::ExternalLinkage, - ConstantInt::get(Int64Ty, 0), "__dso_handle"); - DSOHandle->setVisibility(GlobalValue::DefaultVisibility); - - return cantFail(J.getIRCompileLayer().getCompiler()(M)); - } - - ThreadSafeModule createPlatformRuntimeModule() { - auto Ctx = std::make_unique(); - auto M = std::make_unique("__standard_lib", *Ctx); - M->setDataLayout(J.getDataLayout()); - - auto *MachOPlatformSupportTy = - StructType::create(*Ctx, "lljit.MachOPlatformSupport"); - - auto *PlatformInstanceDecl = new GlobalVariable( - *M, MachOPlatformSupportTy, true, GlobalValue::ExternalLinkage, nullptr, - "__lljit.platform_support_instance"); - - auto *Int8Ty = Type::getInt8Ty(*Ctx); - auto *IntTy = Type::getIntNTy(*Ctx, sizeof(int) * CHAR_BIT); - auto *VoidTy = Type::getVoidTy(*Ctx); - auto *BytePtrTy = PointerType::getUnqual(Int8Ty); - auto *AtExitCallbackTy = FunctionType::get(VoidTy, {BytePtrTy}, false); - auto *AtExitCallbackPtrTy = PointerType::getUnqual(AtExitCallbackTy); - - addHelperAndWrapper( - *M, "__cxa_atexit", - FunctionType::get(IntTy, {AtExitCallbackPtrTy, BytePtrTy, BytePtrTy}, - false), - GlobalValue::DefaultVisibility, "__lljit.cxa_atexit_helper", - {PlatformInstanceDecl}); - - addHelperAndWrapper(*M, "dlopen", - FunctionType::get(BytePtrTy, {BytePtrTy, IntTy}, false), - GlobalValue::DefaultVisibility, "__lljit.dlopen_helper", - {PlatformInstanceDecl}); - - addHelperAndWrapper(*M, "dlclose", - FunctionType::get(IntTy, {BytePtrTy}, false), - GlobalValue::DefaultVisibility, - "__lljit.dlclose_helper", {PlatformInstanceDecl}); - - addHelperAndWrapper( - *M, "dlsym", - FunctionType::get(BytePtrTy, {BytePtrTy, BytePtrTy}, false), - GlobalValue::DefaultVisibility, "__lljit.dlsym_helper", - {PlatformInstanceDecl}); - - addHelperAndWrapper(*M, "dlerror", FunctionType::get(BytePtrTy, {}, false), - GlobalValue::DefaultVisibility, - "__lljit.dlerror_helper", {PlatformInstanceDecl}); - - return ThreadSafeModule(std::move(M), std::move(Ctx)); - } - - static void registerAtExitHelper(void *Self, void (*F)(void *), void *Ctx, - void *DSOHandle) { - static_cast(Self)->AtExitMgr.registerAtExit( - F, Ctx, DSOHandle); - } - - static void runAtExitsHelper(void *Self, void *DSOHandle) { - static_cast(Self)->AtExitMgr.runAtExits(DSOHandle); - } - - void *jit_dlopen(const char *Path, int Mode) { - JITDylib *JDToOpen = nullptr; - // FIXME: Do the right thing with Mode flags. - { - std::lock_guard Lock(PlatformSupportMutex); - - // Clear any existing error messages. - dlErrorMsgs.erase(std::this_thread::get_id()); - - if (auto *JD = J.getExecutionSession().getJITDylibByName(Path)) { - auto I = JDRefCounts.find(JD); - if (I != JDRefCounts.end()) { - ++I->second; - return JD; - } - - JDRefCounts[JD] = 1; - JDToOpen = JD; - } - } - - if (JDToOpen) { - if (auto Err = initialize(*JDToOpen)) { - recordError(std::move(Err)); - return 0; - } - } - - // Fall through to dlopen if no JITDylib found for Path. - return DlFcn.dlopen(Path, Mode); - } - - static void *dlopenHelper(void *Self, const char *Path, int Mode) { - return static_cast(Self)->jit_dlopen(Path, Mode); - } - - int jit_dlclose(void *Handle) { - JITDylib *JDToClose = nullptr; - - { - std::lock_guard Lock(PlatformSupportMutex); - - // Clear any existing error messages. - dlErrorMsgs.erase(std::this_thread::get_id()); - - auto I = JDRefCounts.find(Handle); - if (I != JDRefCounts.end()) { - --I->second; - if (I->second == 0) { - JDRefCounts.erase(I); - JDToClose = static_cast(Handle); - } else - return 0; - } - } - - if (JDToClose) { - if (auto Err = deinitialize(*JDToClose)) { - recordError(std::move(Err)); - return -1; - } - return 0; - } - - // Fall through to dlclose if no JITDylib found for Path. - return DlFcn.dlclose(Handle); - } - - static int dlcloseHelper(void *Self, void *Handle) { - return static_cast(Self)->jit_dlclose(Handle); - } - - void *jit_dlsym(void *Handle, const char *Name) { - JITDylibSearchOrder JITSymSearchOrder; - - // FIXME: RTLD_NEXT, RTLD_SELF not supported. - { - std::lock_guard Lock(PlatformSupportMutex); - - // Clear any existing error messages. - dlErrorMsgs.erase(std::this_thread::get_id()); - - if (JDRefCounts.count(Handle)) { - JITSymSearchOrder.push_back( - {static_cast(Handle), - JITDylibLookupFlags::MatchExportedSymbolsOnly}); - } else if (Handle == DlFcn.RTLDDefault) { - for (auto &KV : JDRefCounts) - JITSymSearchOrder.push_back( - {static_cast(KV.first), - JITDylibLookupFlags::MatchExportedSymbolsOnly}); - } - } - - if (!JITSymSearchOrder.empty()) { - auto MangledName = J.mangleAndIntern(Name); - SymbolLookupSet Syms(MangledName, - SymbolLookupFlags::WeaklyReferencedSymbol); - if (auto Result = J.getExecutionSession().lookup(JITSymSearchOrder, Syms, - LookupKind::DLSym)) { - auto I = Result->find(MangledName); - if (I != Result->end()) - return jitTargetAddressToPointer(I->second.getAddress()); - } else { - recordError(Result.takeError()); - return 0; - } - } - - // Fall through to dlsym. - return DlFcn.dlsym(Handle, Name); - } - - static void *dlsymHelper(void *Self, void *Handle, const char *Name) { - return static_cast(Self)->jit_dlsym(Handle, Name); - } - - const char *jit_dlerror() { - { - std::lock_guard Lock(PlatformSupportMutex); - auto I = dlErrorMsgs.find(std::this_thread::get_id()); - if (I != dlErrorMsgs.end()) - return I->second->c_str(); - } - return DlFcn.dlerror(); - } - - static const char *dlerrorHelper(void *Self) { - return static_cast(Self)->jit_dlerror(); - } - - void recordError(Error Err) { - std::lock_guard Lock(PlatformSupportMutex); - dlErrorMsgs[std::this_thread::get_id()] = - std::make_unique(toString(std::move(Err))); - } - - std::mutex PlatformSupportMutex; - LLJIT &J; - MachOPlatform &MP; - DlFcnValues DlFcn; - ItaniumCXAAtExitSupport AtExitMgr; - DenseMap JDRefCounts; - std::map> dlErrorMsgs; -}; - /// Inactive Platform Support /// /// Explicitly disables platform support. JITDylibs are not scanned for special @@ -1173,15 +782,6 @@ void setUpGenericLLVMIRPlatform(LLJIT &J) { J.setPlatformSupport(std::make_unique(J)); } -Error setUpMachOPlatform(LLJIT &J) { - LLVM_DEBUG({ dbgs() << "Setting up MachOPlatform support for LLJIT\n"; }); - auto MP = MachOPlatformSupport::Create(J, J.getMainJITDylib()); - if (!MP) - return MP.takeError(); - J.setPlatformSupport(std::move(*MP)); - return Error::success(); -} - Error setUpInactivePlatform(LLJIT &J) { LLVM_DEBUG( { dbgs() << "Explicitly deactivated platform support for LLJIT\n"; }); diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp index dd421f91166f4..2a6583249cad4 100644 --- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp +++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp @@ -9,162 +9,182 @@ #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" #include "llvm/BinaryFormat/MachO.h" +#include "llvm/ExecutionEngine/JITLink/x86_64.h" #include "llvm/ExecutionEngine/Orc/DebugUtils.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "orc" +using namespace llvm; +using namespace llvm::orc; +using namespace llvm::orc::shared; + namespace { -struct objc_class; -struct objc_image_info; -struct objc_object; -struct objc_selector; +class MachOHeaderMaterializationUnit : public MaterializationUnit { +public: + MachOHeaderMaterializationUnit(MachOPlatform &MOP, + const SymbolStringPtr &HeaderStartSymbol) + : MaterializationUnit(createHeaderSymbols(MOP, HeaderStartSymbol), + HeaderStartSymbol), + MOP(MOP) {} + + StringRef getName() const override { return "MachOHeaderMU"; } + + void materialize(std::unique_ptr R) override { + unsigned PointerSize; + support::endianness Endianness; + + switch (MOP.getExecutorProcessControl().getTargetTriple().getArch()) { + case Triple::aarch64: + case Triple::x86_64: + PointerSize = 8; + Endianness = support::endianness::little; + break; + default: + llvm_unreachable("Unrecognized architecture"); + } -using Class = objc_class *; -using id = objc_object *; -using SEL = objc_selector *; + auto G = std::make_unique( + "", MOP.getExecutorProcessControl().getTargetTriple(), + PointerSize, Endianness, jitlink::getGenericEdgeKindName); + auto &HeaderSection = G->createSection("__header", sys::Memory::MF_READ); + auto &HeaderBlock = createHeaderBlock(*G, HeaderSection); + + // Init symbol is header-start symbol. + G->addDefinedSymbol(HeaderBlock, 0, *R->getInitializerSymbol(), + HeaderBlock.getSize(), jitlink::Linkage::Strong, + jitlink::Scope::Default, false, true); + for (auto &HS : AdditionalHeaderSymbols) + G->addDefinedSymbol(HeaderBlock, HS.Offset, HS.Name, + HeaderBlock.getSize(), jitlink::Linkage::Strong, + jitlink::Scope::Default, false, true); + + MOP.getObjectLinkingLayer().emit(std::move(R), std::move(G)); + } -using ObjCMsgSendTy = id (*)(id, SEL, ...); -using ObjCReadClassPairTy = Class (*)(Class, const objc_image_info *); -using SelRegisterNameTy = SEL (*)(const char *); + void discard(const JITDylib &JD, const SymbolStringPtr &Sym) override {} -enum class ObjCRegistrationAPI { Uninitialized, Unavailable, Initialized }; +private: + struct HeaderSymbol { + const char *Name; + uint64_t Offset; + }; -ObjCRegistrationAPI ObjCRegistrationAPIState = - ObjCRegistrationAPI::Uninitialized; -ObjCMsgSendTy objc_msgSend = nullptr; -ObjCReadClassPairTy objc_readClassPair = nullptr; -SelRegisterNameTy sel_registerName = nullptr; + static constexpr HeaderSymbol AdditionalHeaderSymbols[] = { + {"___mh_executable_header", 0}}; + + static jitlink::Block &createHeaderBlock(jitlink::LinkGraph &G, + jitlink::Section &HeaderSection) { + MachO::mach_header_64 Hdr; + Hdr.magic = MachO::MH_MAGIC_64; + switch (G.getTargetTriple().getArch()) { + case Triple::aarch64: + Hdr.cputype = MachO::CPU_TYPE_ARM64; + Hdr.cpusubtype = MachO::CPU_SUBTYPE_ARM64_ALL; + break; + case Triple::x86_64: + Hdr.cputype = MachO::CPU_TYPE_X86_64; + Hdr.cpusubtype = MachO::CPU_SUBTYPE_X86_64_ALL; + break; + default: + llvm_unreachable("Unrecognized architecture"); + } + Hdr.filetype = MachO::MH_DYLIB; // Custom file type? + Hdr.ncmds = 0; + Hdr.sizeofcmds = 0; + Hdr.flags = 0; + Hdr.reserved = 0; -} // end anonymous namespace + if (G.getEndianness() != support::endian::system_endianness()) + MachO::swapStruct(Hdr); -namespace llvm { -namespace orc { + auto HeaderContent = G.allocateString( + StringRef(reinterpret_cast(&Hdr), sizeof(Hdr))); -template -static Error setUpObjCRegAPIFunc(FnTy &Target, sys::DynamicLibrary &LibObjC, - const char *Name) { - if (void *Addr = LibObjC.getAddressOfSymbol(Name)) - Target = reinterpret_cast(Addr); - else - return make_error( - (Twine("Could not find address for ") + Name).str(), - inconvertibleErrorCode()); - return Error::success(); -} + return G.createContentBlock(HeaderSection, HeaderContent, 0, 8, 0); + } -Error enableObjCRegistration(const char *PathToLibObjC) { - // If we've already tried to initialize then just bail out. - if (ObjCRegistrationAPIState != ObjCRegistrationAPI::Uninitialized) - return Error::success(); + static SymbolFlagsMap + createHeaderSymbols(MachOPlatform &MOP, + const SymbolStringPtr &HeaderStartSymbol) { + SymbolFlagsMap HeaderSymbolFlags; - ObjCRegistrationAPIState = ObjCRegistrationAPI::Unavailable; + HeaderSymbolFlags[HeaderStartSymbol] = JITSymbolFlags::Exported; + for (auto &HS : AdditionalHeaderSymbols) + HeaderSymbolFlags[MOP.getExecutionSession().intern(HS.Name)] = + JITSymbolFlags::Exported; - std::string ErrMsg; - auto LibObjC = - sys::DynamicLibrary::getPermanentLibrary(PathToLibObjC, &ErrMsg); + return HeaderSymbolFlags; + } - if (!LibObjC.isValid()) - return make_error(std::move(ErrMsg), inconvertibleErrorCode()); + MachOPlatform &MOP; +}; - if (auto Err = setUpObjCRegAPIFunc(objc_msgSend, LibObjC, "objc_msgSend")) - return Err; - if (auto Err = setUpObjCRegAPIFunc(objc_readClassPair, LibObjC, - "objc_readClassPair")) - return Err; - if (auto Err = - setUpObjCRegAPIFunc(sel_registerName, LibObjC, "sel_registerName")) - return Err; +constexpr MachOHeaderMaterializationUnit::HeaderSymbol + MachOHeaderMaterializationUnit::AdditionalHeaderSymbols[]; - ObjCRegistrationAPIState = ObjCRegistrationAPI::Initialized; - return Error::success(); -} +StringRef EHFrameSectionName = "__TEXT,__eh_frame"; +StringRef ModInitFuncSectionName = "__DATA,__mod_init_func"; -bool objCRegistrationEnabled() { - return ObjCRegistrationAPIState == ObjCRegistrationAPI::Initialized; -} +StringRef InitSectionNames[] = {ModInitFuncSectionName}; -void MachOJITDylibInitializers::runModInits() const { - for (const auto &ModInit : ModInitSections) { - assert(ModInit.size().getValue() % sizeof(uintptr_t) == 0 && - "ModInit section size is not a pointer multiple?"); - for (uintptr_t *InitPtr = jitTargetAddressToPointer( - ModInit.StartAddress.getValue()), - *InitEnd = jitTargetAddressToPointer( - ModInit.EndAddress.getValue()); - InitPtr != InitEnd; ++InitPtr) { - auto *Initializer = reinterpret_cast(*InitPtr); - Initializer(); - } - } -} - -void MachOJITDylibInitializers::registerObjCSelectors() const { - assert(objCRegistrationEnabled() && "ObjC registration not enabled."); - - for (const auto &ObjCSelRefs : ObjCSelRefsSections) { - assert(ObjCSelRefs.size().getValue() % sizeof(uintptr_t) == 0 && - "ObjCSelRefs section size is not a pointer multiple?"); - for (auto SelEntryAddr = ObjCSelRefs.StartAddress; - SelEntryAddr != ObjCSelRefs.EndAddress; - SelEntryAddr += ExecutorAddrDiff(sizeof(uintptr_t))) { - const auto *SelName = - *jitTargetAddressToPointer(SelEntryAddr.getValue()); - auto Sel = sel_registerName(SelName); - *jitTargetAddressToPointer(SelEntryAddr.getValue()) = Sel; - } - } -} +} // end anonymous namespace -Error MachOJITDylibInitializers::registerObjCClasses() const { - assert(objCRegistrationEnabled() && "ObjC registration not enabled."); +namespace llvm { +namespace orc { - struct ObjCClassCompiled { - void *Metaclass; - void *Parent; - void *Cache1; - void *Cache2; - void *Data; - }; +Expected> +MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + ExecutorProcessControl &EPC, JITDylib &PlatformJD, + const char *OrcRuntimePath, + Optional RuntimeAliases) { - auto *ImageInfo = - jitTargetAddressToPointer(ObjCImageInfoAddr); - auto ClassSelector = sel_registerName("class"); - - for (const auto &ObjCClassList : ObjCClassListSections) { - assert(ObjCClassList.size().getValue() % sizeof(uintptr_t) == 0 && - "ObjCClassList section size is not a pointer multiple?"); - for (auto ClassPtrAddr = ObjCClassList.StartAddress; - ClassPtrAddr != ObjCClassList.EndAddress; - ClassPtrAddr += ExecutorAddrDiff(sizeof(uintptr_t))) { - auto Cls = *ClassPtrAddr.toPtr(); - auto *ClassCompiled = *ClassPtrAddr.toPtr(); - objc_msgSend(reinterpret_cast(ClassCompiled->Parent), ClassSelector); - auto Registered = objc_readClassPair(Cls, ImageInfo); - - // FIXME: Improve diagnostic by reporting the failed class's name. - if (Registered != Cls) - return make_error("Unable to register Objective-C class", - inconvertibleErrorCode()); - } - } - return Error::success(); -} + // If the target is not supported then bail out immediately. + if (!supportedTarget(EPC.getTargetTriple())) + return make_error("Unsupported MachOPlatform triple: " + + EPC.getTargetTriple().str(), + inconvertibleErrorCode()); -MachOPlatform::MachOPlatform( - ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, - std::unique_ptr StandardSymbolsObject) - : ES(ES), ObjLinkingLayer(ObjLinkingLayer), - StandardSymbolsObject(std::move(StandardSymbolsObject)) { - ObjLinkingLayer.addPlugin(std::make_unique(*this)); + // Create default aliases if the caller didn't supply any. + if (!RuntimeAliases) + RuntimeAliases = standardPlatformAliases(ES); + + // Define the aliases. + if (auto Err = PlatformJD.define(symbolAliases(std::move(*RuntimeAliases)))) + return std::move(Err); + + // Add JIT-dispatch function support symbols. + if (auto Err = PlatformJD.define(absoluteSymbols( + {{ES.intern("___orc_rt_jit_dispatch"), + {EPC.getJITDispatchInfo().JITDispatchFunctionAddress.getValue(), + JITSymbolFlags::Exported}}, + {ES.intern("___orc_rt_jit_dispatch_ctx"), + {EPC.getJITDispatchInfo().JITDispatchContextAddress.getValue(), + JITSymbolFlags::Exported}}}))) + return std::move(Err); + + // Create a generator for the ORC runtime archive. + auto OrcRuntimeArchiveGenerator = StaticLibraryDefinitionGenerator::Load( + ObjLinkingLayer, OrcRuntimePath, EPC.getTargetTriple()); + if (!OrcRuntimeArchiveGenerator) + return OrcRuntimeArchiveGenerator.takeError(); + + // Create the instance. + Error Err = Error::success(); + auto P = std::unique_ptr( + new MachOPlatform(ES, ObjLinkingLayer, EPC, PlatformJD, + std::move(*OrcRuntimeArchiveGenerator), Err)); + if (Err) + return std::move(Err); + return std::move(P); } Error MachOPlatform::setupJITDylib(JITDylib &JD) { - auto ObjBuffer = MemoryBuffer::getMemBuffer( - StandardSymbolsObject->getMemBufferRef(), false); - return ObjLinkingLayer.add(JD, std::move(ObjBuffer)); + return JD.define(std::make_unique( + *this, MachOHeaderStartSymbol)); } Error MachOPlatform::notifyAdding(ResourceTracker &RT, @@ -187,58 +207,118 @@ Error MachOPlatform::notifyRemoving(ResourceTracker &RT) { llvm_unreachable("Not supported yet"); } -Expected -MachOPlatform::getInitializerSequence(JITDylib &JD) { +static void addAliases(ExecutionSession &ES, SymbolAliasMap &Aliases, + ArrayRef> AL) { + for (auto &KV : AL) { + auto AliasName = ES.intern(KV.first); + assert(!Aliases.count(AliasName) && "Duplicate symbol name in alias map"); + Aliases[std::move(AliasName)] = {ES.intern(KV.second), + JITSymbolFlags::Exported}; + } +} - LLVM_DEBUG({ - dbgs() << "MachOPlatform: Building initializer sequence for " - << JD.getName() << "\n"; - }); +SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) { + SymbolAliasMap Aliases; + addAliases(ES, Aliases, requiredCXXAliases()); + addAliases(ES, Aliases, standardRuntimeUtilityAliases()); + return Aliases; +} - std::vector DFSLinkOrder; +ArrayRef> +MachOPlatform::requiredCXXAliases() { + static const std::pair RequiredCXXAliases[] = { + {"___cxa_atexit", "___orc_rt_macho_cxa_atexit"}}; - while (true) { + return ArrayRef>(RequiredCXXAliases); +} - DenseMap NewInitSymbols; +ArrayRef> +MachOPlatform::standardRuntimeUtilityAliases() { + static const std::pair + StandardRuntimeUtilityAliases[] = { + {"___orc_rt_run_program", "___orc_rt_macho_run_program"}, + {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}}; - ES.runSessionLocked([&]() { - DFSLinkOrder = JD.getDFSLinkOrder(); + return ArrayRef>( + StandardRuntimeUtilityAliases); +} - for (auto &InitJD : DFSLinkOrder) { - auto RISItr = RegisteredInitSymbols.find(InitJD.get()); - if (RISItr != RegisteredInitSymbols.end()) { - NewInitSymbols[InitJD.get()] = std::move(RISItr->second); - RegisteredInitSymbols.erase(RISItr); - } - } - }); +bool MachOPlatform::supportedTarget(const Triple &TT) { + switch (TT.getArch()) { + case Triple::x86_64: + return true; + default: + return false; + } +} - if (NewInitSymbols.empty()) - break; +MachOPlatform::MachOPlatform( + ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + ExecutorProcessControl &EPC, JITDylib &PlatformJD, + std::unique_ptr OrcRuntimeGenerator, Error &Err) + : ES(ES), ObjLinkingLayer(ObjLinkingLayer), EPC(EPC), + MachOHeaderStartSymbol(ES.intern("___dso_handle")) { + ErrorAsOutParameter _(&Err); - LLVM_DEBUG({ - dbgs() << "MachOPlatform: Issuing lookups for new init symbols: " - "(lookup may require multiple rounds)\n"; - for (auto &KV : NewInitSymbols) - dbgs() << " \"" << KV.first->getName() << "\": " << KV.second << "\n"; - }); + ObjLinkingLayer.addPlugin(std::make_unique(*this)); + + PlatformJD.addGenerator(std::move(OrcRuntimeGenerator)); - // Outside the lock, issue the lookup. - if (auto R = lookupInitSymbols(JD.getExecutionSession(), NewInitSymbols)) - ; // Nothing to do in the success case. - else - return R.takeError(); + // PlatformJD hasn't been 'set-up' by the platform yet (since we're creating + // the platform now), so set it up. + if (auto E2 = setupJITDylib(PlatformJD)) { + Err = std::move(E2); + return; } - LLVM_DEBUG({ - dbgs() << "MachOPlatform: Init symbol lookup complete, building init " - "sequence\n"; - }); + RegisteredInitSymbols[&PlatformJD].add( + MachOHeaderStartSymbol, SymbolLookupFlags::WeaklyReferencedSymbol); + + // Associate wrapper function tags with JIT-side function implementations. + if (auto E2 = associateRuntimeSupportFunctions(PlatformJD)) { + Err = std::move(E2); + return; + } + + // Lookup addresses of runtime functions callable by the platform, + // call the platform bootstrap function to initialize the platform-state + // object in the executor. + if (auto E2 = bootstrapMachORuntime(PlatformJD)) { + Err = std::move(E2); + return; + } +} + +Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) { + ExecutorProcessControl::WrapperFunctionAssociationMap WFs; + + using GetInitializersSPSSig = + SPSExpected(SPSString); + WFs[ES.intern("___orc_rt_macho_get_initializers_tag")] = + EPC.wrapAsyncWithSPS( + this, &MachOPlatform::rt_getInitializers); - // Lock again to collect the initializers. - InitializerSequence FullInitSeq; + using GetDeinitializersSPSSig = + SPSExpected(SPSExecutorAddress); + WFs[ES.intern("___orc_rt_macho_get_deinitializers_tag")] = + EPC.wrapAsyncWithSPS( + this, &MachOPlatform::rt_getDeinitializers); + + using LookupSymbolSPSSig = + SPSExpected(SPSExecutorAddress, SPSString); + WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] = + EPC.wrapAsyncWithSPS(this, + &MachOPlatform::rt_lookupSymbol); + + return EPC.associateJITSideWrapperFunctions(PlatformJD, std::move(WFs)); +} + +void MachOPlatform::getInitializersBuildSequencePhase( + SendInitializerSequenceFn SendResult, JITDylib &JD, + std::vector DFSLinkOrder) { + MachOJITDylibInitializerSequence FullInitSeq; { - std::lock_guard Lock(InitSeqsMutex); + std::lock_guard Lock(PlatformMutex); for (auto &InitJD : reverse(DFSLinkOrder)) { LLVM_DEBUG({ dbgs() << "MachOPlatform: Appending inits for \"" << InitJD->getName() @@ -246,160 +326,267 @@ MachOPlatform::getInitializerSequence(JITDylib &JD) { }); auto ISItr = InitSeqs.find(InitJD.get()); if (ISItr != InitSeqs.end()) { - FullInitSeq.emplace_back(InitJD.get(), std::move(ISItr->second)); + FullInitSeq.emplace_back(std::move(ISItr->second)); InitSeqs.erase(ISItr); } } } - return FullInitSeq; + SendResult(std::move(FullInitSeq)); } -Expected -MachOPlatform::getDeinitializerSequence(JITDylib &JD) { - std::vector DFSLinkOrder = JD.getDFSLinkOrder(); - - DeinitializerSequence FullDeinitSeq; - { - std::lock_guard Lock(InitSeqsMutex); - for (auto &DeinitJD : DFSLinkOrder) { - FullDeinitSeq.emplace_back(DeinitJD.get(), MachOJITDylibDeinitializers()); +void MachOPlatform::getInitializersLookupPhase( + SendInitializerSequenceFn SendResult, JITDylib &JD) { + + auto DFSLinkOrder = JD.getDFSLinkOrder(); + DenseMap NewInitSymbols; + ES.runSessionLocked([&]() { + for (auto &InitJD : DFSLinkOrder) { + auto RISItr = RegisteredInitSymbols.find(InitJD.get()); + if (RISItr != RegisteredInitSymbols.end()) { + NewInitSymbols[InitJD.get()] = std::move(RISItr->second); + RegisteredInitSymbols.erase(RISItr); + } } + }); + + // If there are no further init symbols to look up then move on to the next + // phase. + if (NewInitSymbols.empty()) { + getInitializersBuildSequencePhase(std::move(SendResult), JD, + std::move(DFSLinkOrder)); + return; } - return FullDeinitSeq; + // Otherwise issue a lookup and re-run this phase when it completes. + lookupInitSymbolsAsync( + [this, SendResult = std::move(SendResult), &JD](Error Err) mutable { + if (Err) + SendResult(std::move(Err)); + else + getInitializersLookupPhase(std::move(SendResult), JD); + }, + ES, std::move(NewInitSymbols)); } -void MachOPlatform::registerInitInfo(JITDylib &JD, - JITTargetAddress ObjCImageInfoAddr, - ExecutorAddressRange ModInits, - ExecutorAddressRange ObjCSelRefs, - ExecutorAddressRange ObjCClassList) { - std::lock_guard Lock(InitSeqsMutex); +void MachOPlatform::rt_getInitializers(SendInitializerSequenceFn SendResult, + StringRef JDName) { + LLVM_DEBUG({ + dbgs() << "MachOPlatform::rt_getInitializers(\"" << JDName << "\")\n"; + }); - auto &InitSeq = InitSeqs[&JD]; + JITDylib *JD = ES.getJITDylibByName(JDName); + if (!JD) { + LLVM_DEBUG({ + dbgs() << " No such JITDylib \"" << JDName << "\". Sending error.\n"; + }); + SendResult(make_error("No JITDylib named " + JDName, + inconvertibleErrorCode())); + return; + } - InitSeq.setObjCImageInfoAddr(ObjCImageInfoAddr); + getInitializersLookupPhase(std::move(SendResult), *JD); +} - if (ModInits.StartAddress) - InitSeq.addModInitsSection(std::move(ModInits)); +void MachOPlatform::rt_getDeinitializers(SendDeinitializerSequenceFn SendResult, + ExecutorAddress Handle) { + LLVM_DEBUG({ + dbgs() << "MachOPlatform::rt_getDeinitializers(\"" + << formatv("{0:x}", Handle.getValue()) << "\")\n"; + }); - if (ObjCSelRefs.StartAddress) - InitSeq.addObjCSelRefsSection(std::move(ObjCSelRefs)); + JITDylib *JD = nullptr; - if (ObjCClassList.StartAddress) - InitSeq.addObjCClassListSection(std::move(ObjCClassList)); -} + { + std::lock_guard Lock(PlatformMutex); + auto I = HeaderAddrToJITDylib.find(Handle.getValue()); + if (I != HeaderAddrToJITDylib.end()) + JD = I->second; + } -static Expected getSectionExtent(jitlink::LinkGraph &G, - StringRef SectionName) { - auto *Sec = G.findSectionByName(SectionName); - if (!Sec) - return ExecutorAddressRange(); - jitlink::SectionRange R(*Sec); - if (R.getSize() % G.getPointerSize() != 0) - return make_error(SectionName + " section size is not a " - "multiple of the pointer size", - inconvertibleErrorCode()); - return ExecutorAddressRange(ExecutorAddress(R.getStart()), - ExecutorAddress(R.getEnd())); + if (!JD) { + LLVM_DEBUG({ + dbgs() << " No JITDylib for handle " + << formatv("{0:x}", Handle.getValue()) << "\n"; + }); + SendResult(make_error("No JITDylib associated with handle " + + formatv("{0:x}", Handle.getValue()), + inconvertibleErrorCode())); + return; + } + + SendResult(MachOJITDylibDeinitializerSequence()); } -void MachOPlatform::InitScraperPlugin::modifyPassConfig( - MaterializationResponsibility &MR, jitlink::LinkGraph &LG, - jitlink::PassConfiguration &Config) { +void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult, + ExecutorAddress Handle, + StringRef SymbolName) { + LLVM_DEBUG({ + dbgs() << "MachOPlatform::rt_lookupSymbol(\"" + << formatv("{0:x}", Handle.getValue()) << "\")\n"; + }); + + JITDylib *JD = nullptr; + + { + std::lock_guard Lock(PlatformMutex); + auto I = HeaderAddrToJITDylib.find(Handle.getValue()); + if (I != HeaderAddrToJITDylib.end()) + JD = I->second; + } - if (!MR.getInitializerSymbol()) + if (!JD) { + LLVM_DEBUG({ + dbgs() << " No JITDylib for handle " + << formatv("{0:x}", Handle.getValue()) << "\n"; + }); + SendResult(make_error("No JITDylib associated with handle " + + formatv("{0:x}", Handle.getValue()), + inconvertibleErrorCode())); return; + } - Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error { - JITLinkSymbolSet InitSectionSyms; - preserveInitSectionIfPresent(InitSectionSyms, G, "__DATA,__mod_init_func"); - preserveInitSectionIfPresent(InitSectionSyms, G, "__DATA,__objc_selrefs"); - preserveInitSectionIfPresent(InitSectionSyms, G, "__DATA,__objc_classlist"); + // FIXME: Proper mangling. + auto MangledName = ("_" + SymbolName).str(); + ES.lookup( + LookupKind::DLSym, {{JD, JITDylibLookupFlags::MatchExportedSymbolsOnly}}, + SymbolLookupSet(ES.intern(MangledName)), SymbolState::Ready, + [SendResult = std::move(SendResult)](Expected Result) mutable { + if (Result) { + assert(Result->size() == 1 && "Unexpected result map count"); + SendResult(ExecutorAddress(Result->begin()->second.getAddress())); + } else + SendResult(Result.takeError()); + }, + NoDependenciesToRegister); +} - if (!InitSectionSyms.empty()) { - std::lock_guard Lock(InitScraperMutex); - InitSymbolDeps[&MR] = std::move(InitSectionSyms); - } +Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) { + + std::pair Symbols[] = { + {"___orc_rt_macho_platform_bootstrap", &orc_rt_macho_platform_bootstrap}, + {"___orc_rt_macho_platform_shutdown", &orc_rt_macho_platform_shutdown}, + {"___orc_rt_macho_register_object_sections", + &orc_rt_macho_register_object_sections}}; + + SymbolLookupSet RuntimeSymbols; + std::vector> AddrsToRecord; + for (const auto &KV : Symbols) { + auto Name = ES.intern(KV.first); + RuntimeSymbols.add(Name); + AddrsToRecord.push_back({std::move(Name), KV.second}); + } + + auto RuntimeSymbolAddrs = ES.lookup( + {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols); + if (!RuntimeSymbolAddrs) + return RuntimeSymbolAddrs.takeError(); + + for (const auto &KV : AddrsToRecord) { + auto &Name = KV.first; + assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?"); + KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress()); + } - if (auto Err = processObjCImageInfo(G, MR)) + if (auto Err = + EPC.runSPSWrapper(orc_rt_macho_platform_bootstrap.getValue())) + return Err; + + // FIXME: Ordering is fuzzy here. We're probably best off saying + // "behavior is undefined if code that uses the runtime is added before + // the platform constructor returns", then move all this to the constructor. + RuntimeBootstrapped = true; + std::vector DeferredPOSRs; + { + std::lock_guard Lock(PlatformMutex); + DeferredPOSRs = std::move(BootstrapPOSRs); + } + + for (auto &D : DeferredPOSRs) + if (auto Err = registerPerObjectSections(D)) return Err; - return Error::success(); - }); + return Error::success(); +} + +Error MachOPlatform::registerInitInfo( + JITDylib &JD, ArrayRef InitSections) { - Config.PostFixupPasses.push_back([this, &JD = MR.getTargetJITDylib()]( - jitlink::LinkGraph &G) -> Error { - ExecutorAddressRange ModInits, ObjCSelRefs, ObjCClassList; + std::unique_lock Lock(PlatformMutex); - JITTargetAddress ObjCImageInfoAddr = 0; - if (auto *ObjCImageInfoSec = - G.findSectionByName("__DATA,__objc_image_info")) { - if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart()) - ObjCImageInfoAddr = Addr; + MachOJITDylibInitializers *InitSeq = nullptr; + { + auto I = InitSeqs.find(&JD); + if (I == InitSeqs.end()) { + // If there's no init sequence entry yet then we need to look up the + // header symbol to force creation of one. + Lock.unlock(); + + auto SearchOrder = + JD.withLinkOrderDo([](const JITDylibSearchOrder &SO) { return SO; }); + if (auto Err = ES.lookup(SearchOrder, MachOHeaderStartSymbol).takeError()) + return Err; + + Lock.lock(); + I = InitSeqs.find(&JD); + assert(I != InitSeqs.end() && + "Entry missing after header symbol lookup?"); } + InitSeq = &I->second; + } - // Record __mod_init_func. - if (auto ModInitsOrErr = getSectionExtent(G, "__DATA,__mod_init_func")) - ModInits = std::move(*ModInitsOrErr); - else - return ModInitsOrErr.takeError(); - - // Record __objc_selrefs. - if (auto ObjCSelRefsOrErr = getSectionExtent(G, "__DATA,__objc_selrefs")) - ObjCSelRefs = std::move(*ObjCSelRefsOrErr); - else - return ObjCSelRefsOrErr.takeError(); - - // Record __objc_classlist. - if (auto ObjCClassListOrErr = - getSectionExtent(G, "__DATA,__objc_classlist")) - ObjCClassList = std::move(*ObjCClassListOrErr); - else - return ObjCClassListOrErr.takeError(); - - // Dump the scraped inits. - LLVM_DEBUG({ - dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; - dbgs() << " __objc_selrefs: "; - auto NumObjCSelRefs = ObjCSelRefs.size().getValue() / sizeof(uintptr_t); - if (NumObjCSelRefs) - dbgs() << NumObjCSelRefs << " pointer(s) at " - << formatv("{0:x16}", ObjCSelRefs.StartAddress.getValue()) - << "\n"; - else - dbgs() << "none\n"; - - dbgs() << " __objc_classlist: "; - auto NumObjCClasses = ObjCClassList.size().getValue() / sizeof(uintptr_t); - if (NumObjCClasses) - dbgs() << NumObjCClasses << " pointer(s) at " - << formatv("{0:x16}", ObjCClassList.StartAddress.getValue()) - << "\n"; - else - dbgs() << "none\n"; - - dbgs() << " __mod_init_func: "; - auto NumModInits = ModInits.size().getValue() / sizeof(uintptr_t); - if (NumModInits) - dbgs() << NumModInits << " pointer(s) at " - << formatv("{0:x16}", ModInits.StartAddress.getValue()) << "\n"; - else - dbgs() << "none\n"; - }); + for (auto *Sec : InitSections) { + // FIXME: Avoid copy here. + jitlink::SectionRange R(*Sec); + InitSeq->InitSections[Sec->getName()].push_back( + {ExecutorAddress(R.getStart()), ExecutorAddress(R.getEnd())}); + } - MP.registerInitInfo(JD, ObjCImageInfoAddr, std::move(ModInits), - std::move(ObjCSelRefs), std::move(ObjCClassList)); + return Error::success(); +} - return Error::success(); - }); +Error MachOPlatform::registerPerObjectSections( + const MachOPerObjectSectionsToRegister &POSR) { + + if (!orc_rt_macho_register_object_sections) + return make_error("Attempting to register per-object " + "sections, but runtime support has not " + "been loaded yet", + inconvertibleErrorCode()); + + Error ErrResult = Error::success(); + if (auto Err = EPC.runSPSWrapper( + orc_rt_macho_register_object_sections.getValue(), ErrResult, POSR)) + return Err; + return ErrResult; +} + +void MachOPlatform::MachOPlatformPlugin::modifyPassConfig( + MaterializationResponsibility &MR, jitlink::LinkGraph &LG, + jitlink::PassConfiguration &Config) { + + // If the initializer symbol is the MachOHeader start symbol then just add + // the macho header support passes. + if (MR.getInitializerSymbol() == MP.MachOHeaderStartSymbol) { + addMachOHeaderSupportPasses(MR, Config); + // The header materialization unit doesn't require any other support, so we + // can bail out early. + return; + } + + // If the object contains initializers then add passes to record them. + if (MR.getInitializerSymbol()) + addInitializerSupportPasses(MR, Config); + + // Add passes for eh-frame support. + addEHSupportPasses(MR, Config); } ObjectLinkingLayer::Plugin::SyntheticSymbolDependenciesMap -MachOPlatform::InitScraperPlugin::getSyntheticSymbolDependencies( +MachOPlatform::MachOPlatformPlugin::getSyntheticSymbolDependencies( MaterializationResponsibility &MR) { - std::lock_guard Lock(InitScraperMutex); + std::lock_guard Lock(PluginMutex); auto I = InitSymbolDeps.find(&MR); if (I != InitSymbolDeps.end()) { SyntheticSymbolDependenciesMap Result; @@ -410,93 +597,135 @@ MachOPlatform::InitScraperPlugin::getSyntheticSymbolDependencies( return SyntheticSymbolDependenciesMap(); } -void MachOPlatform::InitScraperPlugin::preserveInitSectionIfPresent( - JITLinkSymbolSet &Symbols, jitlink::LinkGraph &G, StringRef SectionName) { - if (auto *Sec = G.findSectionByName(SectionName)) { - auto SecBlocks = Sec->blocks(); - if (!llvm::empty(SecBlocks)) - Symbols.insert( - &G.addAnonymousSymbol(**SecBlocks.begin(), 0, 0, false, true)); - } +void MachOPlatform::MachOPlatformPlugin::addInitializerSupportPasses( + MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { + + /// Preserve init sections. + Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) { + return preserveInitSections(G, MR); + }); + + Config.PostFixupPasses.push_back( + [this, &JD = MR.getTargetJITDylib()](jitlink::LinkGraph &G) { + return registerInitSections(G, JD); + }); } -Error MachOPlatform::InitScraperPlugin::processObjCImageInfo( - jitlink::LinkGraph &G, MaterializationResponsibility &MR) { +void MachOPlatform::MachOPlatformPlugin::addMachOHeaderSupportPasses( + MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { - // If there's an ObjC imagine info then either - // (1) It's the first __objc_imageinfo we've seen in this JITDylib. In - // this case we name and record it. - // OR - // (2) We already have a recorded __objc_imageinfo for this JITDylib, - // in which case we just verify it. - auto *ObjCImageInfo = G.findSectionByName("__objc_imageinfo"); - if (!ObjCImageInfo) + Config.PostAllocationPasses.push_back([this, &JD = MR.getTargetJITDylib()]( + jitlink::LinkGraph &G) -> Error { + auto I = llvm::find_if(G.defined_symbols(), [this](jitlink::Symbol *Sym) { + return Sym->getName() == *MP.MachOHeaderStartSymbol; + }); + assert(I != G.defined_symbols().end() && + "Missing MachO header start symbol"); + { + std::lock_guard Lock(MP.PlatformMutex); + JITTargetAddress HeaderAddr = (*I)->getAddress(); + MP.HeaderAddrToJITDylib[HeaderAddr] = &JD; + assert(!MP.InitSeqs.count(&JD) && "InitSeq entry for JD already exists"); + MP.InitSeqs.insert( + std::make_pair(&JD, MachOJITDylibInitializers( + JD.getName(), ExecutorAddress(HeaderAddr)))); + } return Error::success(); + }); +} - auto ObjCImageInfoBlocks = ObjCImageInfo->blocks(); +void MachOPlatform::MachOPlatformPlugin::addEHSupportPasses( + MaterializationResponsibility &MR, jitlink::PassConfiguration &Config) { - // Check that the section is not empty if present. - if (llvm::empty(ObjCImageInfoBlocks)) - return make_error("Empty __objc_imageinfo section in " + - G.getName(), - inconvertibleErrorCode()); + // Add a pass to register the final addresses of the eh-frame sections + // with the runtime. + Config.PostFixupPasses.push_back([this](jitlink::LinkGraph &G) -> Error { + MachOPerObjectSectionsToRegister POSR; - // Check that there's only one block in the section. - if (std::next(ObjCImageInfoBlocks.begin()) != ObjCImageInfoBlocks.end()) - return make_error("Multiple blocks in __objc_imageinfo " - "section in " + - G.getName(), - inconvertibleErrorCode()); + if (auto *EHFrameSection = G.findSectionByName(EHFrameSectionName)) { + jitlink::SectionRange R(*EHFrameSection); + if (!R.empty()) + POSR.EHFrameSection = {ExecutorAddress(R.getStart()), + ExecutorAddress(R.getEnd())}; + } - // Check that the __objc_imageinfo section is unreferenced. - // FIXME: We could optimize this check if Symbols had a ref-count. - for (auto &Sec : G.sections()) { - if (&Sec != ObjCImageInfo) - for (auto *B : Sec.blocks()) - for (auto &E : B->edges()) - if (E.getTarget().isDefined() && - &E.getTarget().getBlock().getSection() == ObjCImageInfo) - return make_error("__objc_imageinfo is referenced " - "within file " + - G.getName(), - inconvertibleErrorCode()); + if (POSR.EHFrameSection.StartAddress) { + + // If we're still bootstrapping the runtime then just record this + // frame for now. + if (!MP.RuntimeBootstrapped) { + std::lock_guard Lock(MP.PlatformMutex); + MP.BootstrapPOSRs.push_back(POSR); + return Error::success(); + } + + // Otherwise register it immediately. + if (auto Err = MP.registerPerObjectSections(POSR)) + return Err; + } + + return Error::success(); + }); +} + +Error MachOPlatform::MachOPlatformPlugin::preserveInitSections( + jitlink::LinkGraph &G, MaterializationResponsibility &MR) { + + JITLinkSymbolSet InitSectionSymbols; + for (auto &InitSectionName : InitSectionNames) { + // Skip non-init sections. + auto *InitSection = G.findSectionByName(InitSectionName); + if (!InitSection) + continue; + + // Make a pass over live symbols in the section: those blocks are already + // preserved. + DenseSet AlreadyLiveBlocks; + for (auto &Sym : InitSection->symbols()) { + auto &B = Sym->getBlock(); + if (Sym->isLive() && Sym->getOffset() == 0 && + Sym->getSize() == B.getSize() && !AlreadyLiveBlocks.count(&B)) { + InitSectionSymbols.insert(Sym); + AlreadyLiveBlocks.insert(&B); + } + } + + // Add anonymous symbols to preserve any not-already-preserved blocks. + for (auto *B : InitSection->blocks()) + if (!AlreadyLiveBlocks.count(B)) + InitSectionSymbols.insert( + &G.addAnonymousSymbol(*B, 0, B->getSize(), false, true)); } - auto &ObjCImageInfoBlock = **ObjCImageInfoBlocks.begin(); - auto *ObjCImageInfoData = ObjCImageInfoBlock.getContent().data(); - auto Version = support::endian::read32(ObjCImageInfoData, G.getEndianness()); - auto Flags = - support::endian::read32(ObjCImageInfoData + 4, G.getEndianness()); - - // Lock the mutex while we verify / update the ObjCImageInfos map. - std::lock_guard Lock(InitScraperMutex); - - auto ObjCImageInfoItr = ObjCImageInfos.find(&MR.getTargetJITDylib()); - if (ObjCImageInfoItr != ObjCImageInfos.end()) { - // We've already registered an __objc_imageinfo section. Verify the - // content of this new section matches, then delete it. - if (ObjCImageInfoItr->second.first != Version) - return make_error( - "ObjC version in " + G.getName() + - " does not match first registered version", - inconvertibleErrorCode()); - if (ObjCImageInfoItr->second.second != Flags) - return make_error("ObjC flags in " + G.getName() + - " do not match first registered flags", - inconvertibleErrorCode()); - - // __objc_imageinfo is valid. Delete the block. - for (auto *S : ObjCImageInfo->symbols()) - G.removeDefinedSymbol(*S); - G.removeBlock(ObjCImageInfoBlock); - } else { - // We haven't registered an __objc_imageinfo section yet. Register and - // move on. The section should already be marked no-dead-strip. - ObjCImageInfos[&MR.getTargetJITDylib()] = std::make_pair(Version, Flags); + if (!InitSectionSymbols.empty()) { + std::lock_guard Lock(PluginMutex); + InitSymbolDeps[&MR] = std::move(InitSectionSymbols); } return Error::success(); } +Error MachOPlatform::MachOPlatformPlugin::registerInitSections( + jitlink::LinkGraph &G, JITDylib &JD) { + + SmallVector InitSections; + + for (auto InitSectionName : InitSectionNames) + if (auto *Sec = G.findSectionByName(InitSectionName)) + InitSections.push_back(Sec); + + // Dump the scraped inits. + LLVM_DEBUG({ + dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; + for (auto *Sec : InitSections) { + jitlink::SectionRange R(*Sec); + dbgs() << " " << Sec->getName() << ": " + << formatv("[ {0:x} -- {1:x} ]", R.getStart(), R.getEnd()) << "\n"; + } + }); + + return MP.registerInitInfo(JD, InitSections); +} + } // End namespace orc. } // End namespace llvm. diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp index a45b18544609d..41769170ca716 100644 --- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -7,12 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" - #include "llvm/ADT/Optional.h" #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" #include "llvm/Support/MemoryBuffer.h" - +#include #include #define DEBUG_TYPE "orc" diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp index 3068a41b932ba..e6fdd065b9958 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp @@ -240,6 +240,48 @@ static JITSymbolFlags toJITSymbolFlags(LLVMJITSymbolFlags F) { return JSF; } +static LLVMJITSymbolFlags fromJITSymbolFlags(JITSymbolFlags JSF) { + LLVMJITSymbolFlags F = {0, 0}; + if (JSF & JITSymbolFlags::Exported) + F.GenericFlags |= LLVMJITSymbolGenericFlagsExported; + if (JSF & JITSymbolFlags::Weak) + F.GenericFlags |= LLVMJITSymbolGenericFlagsWeak; + if (JSF & JITSymbolFlags::Callable) + F.GenericFlags |= LLVMJITSymbolGenericFlagsCallable; + if (JSF & JITSymbolFlags::MaterializationSideEffectsOnly) + F.GenericFlags |= LLVMJITSymbolGenericFlagsMaterializationSideEffectsOnly; + + F.TargetFlags = JSF.getTargetFlags(); + + return F; +} + +static SymbolMap toSymbolMap(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) { + SymbolMap SM; + for (size_t I = 0; I != NumPairs; ++I) { + JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags); + SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] = + JITEvaluatedSymbol(Syms[I].Sym.Address, Flags); + } + return SM; +} + +static SymbolDependenceMap +toSymbolDependenceMap(LLVMOrcCDependenceMapPairs Pairs, size_t NumPairs) { + SymbolDependenceMap SDM; + for (size_t I = 0; I != NumPairs; ++I) { + JITDylib *JD = unwrap(Pairs[I].JD); + SymbolNameSet Names; + + for (size_t J = 0; J != Pairs[I].Names.Length; ++J) { + auto Sym = Pairs[I].Names.Symbols[J]; + Names.insert(OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Sym))); + } + SDM[JD] = Names; + } + return SDM; +} + } // end anonymous namespace void LLVMOrcExecutionSessionSetErrorReporter( @@ -334,13 +376,7 @@ LLVMOrcMaterializationUnitRef LLVMOrcCreateCustomMaterializationUnit( LLVMOrcMaterializationUnitRef LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) { - SymbolMap SM; - for (size_t I = 0; I != NumPairs; ++I) { - JITSymbolFlags Flags = toJITSymbolFlags(Syms[I].Sym.Flags); - SM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] = - JITEvaluatedSymbol(Syms[I].Sym.Address, Flags); - } - + SymbolMap SM = toSymbolMap(Syms, NumPairs); return wrap(absoluteSymbols(std::move(SM)).release()); } @@ -364,6 +400,150 @@ LLVMOrcMaterializationUnitRef LLVMOrcLazyReexports( .release()); } +void LLVMOrcDisposeMaterializationResponsibility( + LLVMOrcMaterializationResponsibilityRef MR) { + std::unique_ptr TmpMR(unwrap(MR)); +} + +LLVMOrcJITDylibRef LLVMOrcMaterializationResponsibilityGetTargetDylib( + LLVMOrcMaterializationResponsibilityRef MR) { + return wrap(&unwrap(MR)->getTargetJITDylib()); +} + +LLVMOrcExecutionSessionRef +LLVMOrcMaterializationResponsibilityGetExecutionSession( + LLVMOrcMaterializationResponsibilityRef MR) { + return wrap(&unwrap(MR)->getExecutionSession()); +} + +LLVMOrcCSymbolFlagsMapPairs LLVMOrcMaterializationResponsibilityGetSymbols( + LLVMOrcMaterializationResponsibilityRef MR, size_t *NumPairs) { + + auto Symbols = unwrap(MR)->getSymbols(); + LLVMOrcCSymbolFlagsMapPairs Result = static_cast( + safe_malloc(Symbols.size() * sizeof(LLVMOrcCSymbolFlagsMapPair))); + size_t I = 0; + for (auto const &pair : Symbols) { + auto Name = wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(pair.first)); + auto Flags = pair.second; + Result[I] = {Name, fromJITSymbolFlags(Flags)}; + I++; + } + *NumPairs = Symbols.size(); + return Result; +} + +void LLVMOrcDisposeCSymbolFlagsMap(LLVMOrcCSymbolFlagsMapPairs Pairs) { + free(Pairs); +} + +LLVMOrcSymbolStringPoolEntryRef +LLVMOrcMaterializationResponsibilityGetInitializerSymbol( + LLVMOrcMaterializationResponsibilityRef MR) { + auto Sym = unwrap(MR)->getInitializerSymbol(); + return wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Sym)); +} + +LLVMOrcSymbolStringPoolEntryRef * +LLVMOrcMaterializationResponsibilityGetRequestedSymbols( + LLVMOrcMaterializationResponsibilityRef MR, size_t *NumSymbols) { + + auto Symbols = unwrap(MR)->getRequestedSymbols(); + LLVMOrcSymbolStringPoolEntryRef *Result = + static_cast(safe_malloc( + Symbols.size() * sizeof(LLVMOrcSymbolStringPoolEntryRef))); + size_t I = 0; + for (auto &Name : Symbols) { + Result[I] = wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name)); + I++; + } + *NumSymbols = Symbols.size(); + return Result; +} + +void LLVMOrcDisposeSymbols(LLVMOrcSymbolStringPoolEntryRef *Symbols) { + free(Symbols); +} + +LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyResolved( + LLVMOrcMaterializationResponsibilityRef MR, LLVMOrcCSymbolMapPairs Symbols, + size_t NumPairs) { + SymbolMap SM = toSymbolMap(Symbols, NumPairs); + return wrap(unwrap(MR)->notifyResolved(std::move(SM))); +} + +LLVMErrorRef LLVMOrcMaterializationResponsibilityNotifyEmitted( + LLVMOrcMaterializationResponsibilityRef MR) { + return wrap(unwrap(MR)->notifyEmitted()); +} + +LLVMErrorRef LLVMOrcMaterializationResponsibilityDefineMaterializing( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcCSymbolFlagsMapPairs Syms, size_t NumSyms) { + SymbolFlagsMap SFM; + for (size_t I = 0; I != NumSyms; ++I) + SFM[OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Syms[I].Name))] = + toJITSymbolFlags(Syms[I].Flags); + + return wrap(unwrap(MR)->defineMaterializing(std::move(SFM))); +} + +LLVMErrorRef LLVMOrcMaterializationResponsibilityReplace( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcMaterializationUnitRef MU) { + std::unique_ptr TmpMU(unwrap(MU)); + return wrap(unwrap(MR)->replace(std::move(TmpMU))); +} + +LLVMErrorRef LLVMOrcMaterializationResponsibilityDelegate( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcSymbolStringPoolEntryRef *Symbols, size_t NumSymbols, + LLVMOrcMaterializationResponsibilityRef *Result) { + SymbolNameSet Syms; + for (size_t I = 0; I != NumSymbols; I++) { + Syms.insert(OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Symbols[I]))); + } + auto OtherMR = unwrap(MR)->delegate(Syms); + + if (!OtherMR) { + return wrap(OtherMR.takeError()); + } + *Result = wrap(OtherMR->release()); + return LLVMErrorSuccess; +} + +void LLVMOrcMaterializationResponsibilityAddDependencies( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcSymbolStringPoolEntryRef Name, + LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs) { + + SymbolDependenceMap SDM = toSymbolDependenceMap(Dependencies, NumPairs); + auto Sym = OrcV2CAPIHelper::moveToSymbolStringPtr(unwrap(Name)); + unwrap(MR)->addDependencies(Sym, SDM); +} + +void LLVMOrcMaterializationResponsibilityAddDependenciesForAll( + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcCDependenceMapPairs Dependencies, size_t NumPairs) { + + SymbolDependenceMap SDM = toSymbolDependenceMap(Dependencies, NumPairs); + unwrap(MR)->addDependenciesForAll(SDM); +} + +void LLVMOrcMaterializationResponsibilityFailMaterialization( + LLVMOrcMaterializationResponsibilityRef MR) { + unwrap(MR)->failMaterialization(); +} + +void LLVMOrcIRTransformLayerEmit(LLVMOrcIRTransformLayerRef IRLayer, + LLVMOrcMaterializationResponsibilityRef MR, + LLVMOrcThreadSafeModuleRef TSM) { + std::unique_ptr TmpTSM(unwrap(TSM)); + unwrap(IRLayer)->emit( + std::unique_ptr(unwrap(MR)), + std::move(*TmpTSM)); +} + LLVMOrcJITDylibRef LLVMOrcExecutionSessionCreateBareJITDylib(LLVMOrcExecutionSessionRef ES, const char *Name) { @@ -749,6 +929,10 @@ LLVMOrcIRTransformLayerRef LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) { return wrap(&unwrap(J)->getIRTransformLayer()); } +const char *LLVMOrcLLJITGetDataLayoutStr(LLVMOrcLLJITRef J) { + return unwrap(J)->getDataLayout().getStringRepresentation().c_str(); +} + LLVMOrcIndirectStubsManagerRef LLVMOrcCreateLocalIndirectStubsManager(const char *TargetTriple) { auto builder = createLocalIndirectStubsManagerBuilder(Triple(TargetTriple)); diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h index 3b297a9e39084..c5bbe6571096d 100644 --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -136,7 +136,7 @@ class IntAttributeImpl : public EnumAttributeImpl { public: IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val) : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) { - assert(Attribute::doesAttrKindHaveArgument(Kind) && + assert(Attribute::isIntAttrKind(Kind) && "Wrong kind for int attribute!"); } @@ -255,11 +255,7 @@ class AttributeSetNode final std::pair> getAllocSizeArgs() const; std::pair getVScaleRangeArgs() const; std::string getAsString(bool InAttrGrp) const; - Type *getByValType() const; - Type *getStructRetType() const; - Type *getByRefType() const; - Type *getPreallocatedType() const; - Type *getInAllocaType() const; + Type *getAttributeType(Attribute::AttrKind Kind) const; using iterator = const Attribute *; diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 86b296ee13900..fc05f52ee7415 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -91,6 +91,11 @@ static std::pair unpackVScaleRangeArgs(uint64_t Value) { Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, uint64_t Val) { + if (Val) + assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute"); + else + assert(Attribute::isEnumAttrKind(Kind) && "Not an enum attribute"); + LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; ID.AddInteger(Kind); @@ -138,6 +143,7 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, Type *Ty) { + assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute"); LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; ID.AddInteger(Kind); @@ -236,15 +242,6 @@ StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) { } } -bool Attribute::doesAttrKindHaveArgument(Attribute::AttrKind AttrKind) { - return AttrKind == Attribute::Alignment || - AttrKind == Attribute::StackAlignment || - AttrKind == Attribute::Dereferenceable || - AttrKind == Attribute::AllocSize || - AttrKind == Attribute::DereferenceableOrNull || - AttrKind == Attribute::VScaleRange; -} - bool Attribute::isExistingAttribute(StringRef Name) { return StringSwitch(Name) #define GET_ATTR_NAMES @@ -488,6 +485,35 @@ void Attribute::Profile(FoldingSetNodeID &ID) const { ID.AddPointer(pImpl); } +enum AttributeProperty { + FnAttr = (1 << 0), + ParamAttr = (1 << 1), + RetAttr = (1 << 2), +}; + +#define GET_ATTR_PROP_TABLE +#include "llvm/IR/Attributes.inc" + +static bool hasAttributeProperty(Attribute::AttrKind Kind, + AttributeProperty Prop) { + unsigned Index = Kind - 1; + assert(Index < sizeof(AttrPropTable) / sizeof(AttrPropTable[0]) && + "Invalid attribute kind"); + return AttrPropTable[Index] & Prop; +} + +bool Attribute::canUseAsFnAttr(AttrKind Kind) { + return hasAttributeProperty(Kind, AttributeProperty::FnAttr); +} + +bool Attribute::canUseAsParamAttr(AttrKind Kind) { + return hasAttributeProperty(Kind, AttributeProperty::ParamAttr); +} + +bool Attribute::canUseAsRetAttr(AttrKind Kind) { + return hasAttributeProperty(Kind, AttributeProperty::RetAttr); +} + //===----------------------------------------------------------------------===// // AttributeImpl Definition //===----------------------------------------------------------------------===// @@ -535,41 +561,23 @@ Type *AttributeImpl::getValueAsType() const { bool AttributeImpl::operator<(const AttributeImpl &AI) const { if (this == &AI) return false; + // This sorts the attributes with Attribute::AttrKinds coming first (sorted // relative to their enum value) and then strings. - if (isEnumAttribute()) { - if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); - if (AI.isIntAttribute()) return true; - if (AI.isStringAttribute()) return true; - if (AI.isTypeAttribute()) return true; - } - - if (isTypeAttribute()) { - if (AI.isEnumAttribute()) return false; - if (AI.isTypeAttribute()) { - assert(getKindAsEnum() != AI.getKindAsEnum() && - "Comparison of types would be unstable"); - return getKindAsEnum() < AI.getKindAsEnum(); - } - if (AI.isIntAttribute()) return true; - if (AI.isStringAttribute()) return true; - } - - if (isIntAttribute()) { - if (AI.isEnumAttribute()) return false; - if (AI.isTypeAttribute()) return false; - if (AI.isIntAttribute()) { - if (getKindAsEnum() == AI.getKindAsEnum()) - return getValueAsInt() < AI.getValueAsInt(); + if (!isStringAttribute()) { + if (AI.isStringAttribute()) + return true; + if (getKindAsEnum() != AI.getKindAsEnum()) return getKindAsEnum() < AI.getKindAsEnum(); - } - if (AI.isStringAttribute()) return true; + assert(!AI.isEnumAttribute() && "Non-unique attribute"); + assert(!AI.isTypeAttribute() && "Comparison of types would be unstable"); + // TODO: Is this actually needed? + assert(AI.isIntAttribute() && "Only possibility left"); + return getValueAsInt() < AI.getValueAsInt(); } - assert(isStringAttribute()); - if (AI.isEnumAttribute()) return false; - if (AI.isTypeAttribute()) return false; - if (AI.isIntAttribute()) return false; + if (!AI.isStringAttribute()) + return false; if (getKindAsString() == AI.getKindAsString()) return getValueAsString() < AI.getValueAsString(); return getKindAsString() < AI.getKindAsString(); @@ -681,23 +689,27 @@ uint64_t AttributeSet::getDereferenceableOrNullBytes() const { } Type *AttributeSet::getByRefType() const { - return SetNode ? SetNode->getByRefType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::ByRef) : nullptr; } Type *AttributeSet::getByValType() const { - return SetNode ? SetNode->getByValType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::ByVal) : nullptr; } Type *AttributeSet::getStructRetType() const { - return SetNode ? SetNode->getStructRetType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::StructRet) : nullptr; } Type *AttributeSet::getPreallocatedType() const { - return SetNode ? SetNode->getPreallocatedType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::Preallocated) : nullptr; } Type *AttributeSet::getInAllocaType() const { - return SetNode ? SetNode->getInAllocaType() : nullptr; + return SetNode ? SetNode->getAttributeType(Attribute::InAlloca) : nullptr; +} + +Type *AttributeSet::getElementType() const { + return SetNode ? SetNode->getAttributeType(Attribute::ElementType) : nullptr; } std::pair> AttributeSet::getAllocSizeArgs() const { @@ -800,23 +812,13 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { if (!B.contains(Kind)) continue; + if (Attribute::isTypeAttrKind(Kind)) { + Attrs.push_back(Attribute::get(C, Kind, B.getTypeAttr(Kind))); + continue; + } + Attribute Attr; switch (Kind) { - case Attribute::ByVal: - Attr = Attribute::getWithByValType(C, B.getByValType()); - break; - case Attribute::StructRet: - Attr = Attribute::getWithStructRetType(C, B.getStructRetType()); - break; - case Attribute::ByRef: - Attr = Attribute::getWithByRefType(C, B.getByRefType()); - break; - case Attribute::Preallocated: - Attr = Attribute::getWithPreallocatedType(C, B.getPreallocatedType()); - break; - case Attribute::InAlloca: - Attr = Attribute::getWithInAllocaType(C, B.getInAllocaType()); - break; case Attribute::Alignment: assert(B.getAlignment() && "Alignment must be set"); Attr = Attribute::getWithAlignment(C, *B.getAlignment()); @@ -899,32 +901,8 @@ MaybeAlign AttributeSetNode::getStackAlignment() const { return None; } -Type *AttributeSetNode::getByValType() const { - if (auto A = findEnumAttribute(Attribute::ByVal)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getStructRetType() const { - if (auto A = findEnumAttribute(Attribute::StructRet)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getByRefType() const { - if (auto A = findEnumAttribute(Attribute::ByRef)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getPreallocatedType() const { - if (auto A = findEnumAttribute(Attribute::Preallocated)) - return A->getValueAsType(); - return nullptr; -} - -Type *AttributeSetNode::getInAllocaType() const { - if (auto A = findEnumAttribute(Attribute::InAlloca)) +Type *AttributeSetNode::getAttributeType(Attribute::AttrKind Kind) const { + if (auto A = findEnumAttribute(Kind)) return A->getValueAsType(); return nullptr; } @@ -1489,6 +1467,10 @@ Type *AttributeList::getParamInAllocaType(unsigned Index) const { return getAttributes(Index + FirstArgIndex).getInAllocaType(); } +Type *AttributeList::getParamElementType(unsigned Index) const { + return getAttributes(Index + FirstArgIndex).getElementType(); +} + MaybeAlign AttributeList::getStackAlignment(unsigned Index) const { return getAttributes(Index).getStackAlignment(); } @@ -1602,20 +1584,9 @@ void AttrBuilder::clear() { Optional AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const { - switch (Kind) { - case Attribute::ByVal: - return ByValTypeIndex; - case Attribute::ByRef: - return ByRefTypeIndex; - case Attribute::InAlloca: - return InAllocaTypeIndex; - case Attribute::Preallocated: - return PreallocatedTypeIndex; - case Attribute::StructRet: - return StructRetTypeIndex; - default: - return None; - } + if (Attribute::isTypeAttrKind(Kind)) + return Kind - Attribute::FirstTypeAttr; + return None; } AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { @@ -1765,6 +1736,12 @@ AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) { return *this; } +Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const { + Optional TypeIndex = kindToTypeIndex(Kind); + assert(TypeIndex && "Not a type attribute"); + return TypeAttrs[*TypeIndex]; +} + AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) { Optional TypeIndex = kindToTypeIndex(Kind); assert(TypeIndex && "Not a type attribute"); @@ -1813,7 +1790,7 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { if (!VScaleRangeArgs) VScaleRangeArgs = B.VScaleRangeArgs; - for (unsigned Index = 0; Index < NumTypeIndices; ++Index) + for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) if (!TypeAttrs[Index]) TypeAttrs[Index] = B.TypeAttrs[Index]; @@ -1845,7 +1822,7 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { if (B.VScaleRangeArgs) VScaleRangeArgs = 0; - for (unsigned Index = 0; Index < NumTypeIndices; ++Index) + for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) if (B.TypeAttrs[Index]) TypeAttrs[Index] = nullptr; @@ -1930,17 +1907,18 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { .addAttribute(Attribute::NoAlias) .addAttribute(Attribute::NoCapture) .addAttribute(Attribute::NonNull) + .addAttribute(Attribute::ReadNone) + .addAttribute(Attribute::ReadOnly) + .addAttribute(Attribute::SwiftError) .addAlignmentAttr(1) // the int here is ignored .addDereferenceableAttr(1) // the int here is ignored .addDereferenceableOrNullAttr(1) // the int here is ignored - .addAttribute(Attribute::ReadNone) - .addAttribute(Attribute::ReadOnly) - .addAttribute(Attribute::InAlloca) .addPreallocatedAttr(Ty) .addInAllocaAttr(Ty) .addByValAttr(Ty) .addStructRetAttr(Ty) - .addByRefAttr(Ty); + .addByRefAttr(Ty) + .addTypeAttr(Attribute::ElementType, Ty); // Some attributes can apply to all "values" but there are no `void` values. if (Ty->isVoidTy()) diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 791c684d3bb69..6c75085a6678d 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2427,10 +2427,8 @@ Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C, Optional InRangeIndex, Type *OnlyIfReducedTy) { PointerType *OrigPtrTy = cast(C->getType()->getScalarType()); - if (!Ty) - Ty = OrigPtrTy->getElementType(); - else - assert(OrigPtrTy->isOpaqueOrPointeeTypeMatches(Ty)); + assert(Ty && "Must specify element type"); + assert(OrigPtrTy->isOpaqueOrPointeeTypeMatches(Ty)); if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, InRangeIndex, Idxs)) diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index b502e5c48dbc0..4f4a8dbbd983b 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1676,11 +1676,26 @@ Optional Intrinsic::remangleIntrinsicFunction(Function *F) { Intrinsic::ID ID = F->getIntrinsicID(); StringRef Name = F->getName(); - if (Name == - Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType())) + std::string WantedName = + Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType()); + if (Name == WantedName) return None; - auto NewDecl = Intrinsic::getDeclaration(F->getParent(), ID, ArgTys); + Function *NewDecl = [&] { + if (auto *ExistingGV = F->getParent()->getNamedValue(WantedName)) { + if (auto *ExistingF = dyn_cast(ExistingGV)) + if (ExistingF->getFunctionType() == F->getFunctionType()) + return ExistingF; + + // The name already exists, but is not a function or has the wrong + // prototype. Make place for the new one by renaming the old version. + // Either this old version will be removed later on or the module is + // invalid and we'll get an error. + ExistingGV->setName(WantedName + ".renamed"); + } + return Intrinsic::getDeclaration(F->getParent(), ID, ArgTys); + }(); + NewDecl->setCallingConv(F->getCallingConv()); assert(NewDecl->getFunctionType() == F->getFunctionType() && "Shouldn't change the signature"); diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 5ea9867a246c2..0f4945bad5ab5 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -1143,9 +1143,11 @@ Value *IRBuilderBase::CreateExtractInteger( Value *IRBuilderBase::CreatePreserveArrayAccessIndex( Type *ElTy, Value *Base, unsigned Dimension, unsigned LastIndex, MDNode *DbgInfo) { - assert(isa(Base->getType()) && - "Invalid Base ptr type for preserve.array.access.index."); auto *BaseType = Base->getType(); + assert(isa(BaseType) && + "Invalid Base ptr type for preserve.array.access.index."); + assert(cast(BaseType)->isOpaqueOrPointeeTypeMatches(ElTy) && + "Pointer element type mismatch"); Value *LastIndexV = getInt32(LastIndex); Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); @@ -1162,6 +1164,8 @@ Value *IRBuilderBase::CreatePreserveArrayAccessIndex( Value *DimV = getInt32(Dimension); CallInst *Fn = CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); + Fn->addParamAttr( + 0, Attribute::get(Fn->getContext(), Attribute::ElementType, ElTy)); if (DbgInfo) Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); @@ -1190,9 +1194,11 @@ Value *IRBuilderBase::CreatePreserveUnionAccessIndex( Value *IRBuilderBase::CreatePreserveStructAccessIndex( Type *ElTy, Value *Base, unsigned Index, unsigned FieldIndex, MDNode *DbgInfo) { - assert(isa(Base->getType()) && - "Invalid Base ptr type for preserve.struct.access.index."); auto *BaseType = Base->getType(); + assert(isa(BaseType) && + "Invalid Base ptr type for preserve.struct.access.index."); + assert(cast(BaseType)->isOpaqueOrPointeeTypeMatches(ElTy) && + "Pointer element type mismatch"); Value *GEPIndex = getInt32(Index); Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); @@ -1206,6 +1212,8 @@ Value *IRBuilderBase::CreatePreserveStructAccessIndex( Value *DIIndex = getInt32(FieldIndex); CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, {Base, GEPIndex, DIIndex}); + Fn->addParamAttr( + 0, Attribute::get(Fn->getContext(), Attribute::ElementType, ElTy)); if (DbgInfo) Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 68df26932a69c..5b01c70dec8d8 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -45,6 +45,10 @@ using namespace llvm; +static cl::opt DisableI2pP2iOpt( + "disable-i2p-p2i-opt", cl::init(false), + cl::desc("Disables inttoptr/ptrtoint roundtrip optimization")); + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// @@ -2845,6 +2849,10 @@ unsigned CastInst::isEliminableCastPair( return secondOp; return 0; case 7: { + // Disable inttoptr/ptrtoint optimization if enabled. + if (DisableI2pP2iOpt) + return 0; + // Cannot simplify if address spaces are different! if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace()) return 0; diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index 9cb00569598aa..1c595651b3d72 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -897,6 +897,7 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, // CanBeNull flag. DerefBytes = DL.getTypeStoreSize(GV->getValueType()).getFixedSize(); CanBeNull = false; + CanBeFreed = false; } } return DerefBytes; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 6039d1cf2dc02..c86536f505f16 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -540,8 +540,7 @@ class Verifier : public InstVisitor, VerifierSupport { void verifyTailCCMustTailAttrs(AttrBuilder Attrs, StringRef Context); void verifyMustTailCall(CallInst &CI); bool verifyAttributeCount(AttributeList Attrs, unsigned Params); - void verifyAttributeTypes(AttributeSet Attrs, bool IsFunction, - const Value *V); + void verifyAttributeTypes(AttributeSet Attrs, const Value *V); void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, const Value *V); @@ -1654,76 +1653,7 @@ void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) { "expected an integer constant", Node->getOperand(2)); } -/// Return true if this attribute kind only applies to functions. -static bool isFuncOnlyAttr(Attribute::AttrKind Kind) { - switch (Kind) { - case Attribute::NoMerge: - case Attribute::NoReturn: - case Attribute::NoSync: - case Attribute::WillReturn: - case Attribute::NoCallback: - case Attribute::NoCfCheck: - case Attribute::NoUnwind: - case Attribute::NoInline: - case Attribute::NoSanitizeCoverage: - case Attribute::AlwaysInline: - case Attribute::OptimizeForSize: - case Attribute::StackProtect: - case Attribute::StackProtectReq: - case Attribute::StackProtectStrong: - case Attribute::SafeStack: - case Attribute::ShadowCallStack: - case Attribute::NoRedZone: - case Attribute::NoImplicitFloat: - case Attribute::Naked: - case Attribute::InlineHint: - case Attribute::UWTable: - case Attribute::VScaleRange: - case Attribute::NonLazyBind: - case Attribute::ReturnsTwice: - case Attribute::SanitizeAddress: - case Attribute::SanitizeHWAddress: - case Attribute::SanitizeMemTag: - case Attribute::SanitizeThread: - case Attribute::SanitizeMemory: - case Attribute::MinSize: - case Attribute::NoDuplicate: - case Attribute::Builtin: - case Attribute::NoBuiltin: - case Attribute::Cold: - case Attribute::Hot: - case Attribute::OptForFuzzing: - case Attribute::OptimizeNone: - case Attribute::JumpTable: - case Attribute::Convergent: - case Attribute::ArgMemOnly: - case Attribute::NoRecurse: - case Attribute::InaccessibleMemOnly: - case Attribute::InaccessibleMemOrArgMemOnly: - case Attribute::AllocSize: - case Attribute::SpeculativeLoadHardening: - case Attribute::Speculatable: - case Attribute::StrictFP: - case Attribute::NullPointerIsValid: - case Attribute::MustProgress: - case Attribute::NoProfile: - return true; - default: - break; - } - return false; -} - -/// Return true if this is a function attribute that can also appear on -/// arguments. -static bool isFuncOrArgAttr(Attribute::AttrKind Kind) { - return Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly || - Kind == Attribute::ReadNone || Kind == Attribute::NoFree || - Kind == Attribute::Preallocated || Kind == Attribute::StackAlignment; -} - -void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction, - const Value *V) { +void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) { for (Attribute A : Attrs) { if (A.isStringAttribute()) { @@ -1741,26 +1671,11 @@ void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction, continue; } - if (A.isIntAttribute() != - Attribute::doesAttrKindHaveArgument(A.getKindAsEnum())) { + if (A.isIntAttribute() != Attribute::isIntAttrKind(A.getKindAsEnum())) { CheckFailed("Attribute '" + A.getAsString() + "' should have an Argument", V); return; } - - if (isFuncOnlyAttr(A.getKindAsEnum())) { - if (!IsFunction) { - CheckFailed("Attribute '" + A.getAsString() + - "' only applies to functions!", - V); - return; - } - } else if (IsFunction && !isFuncOrArgAttr(A.getKindAsEnum())) { - CheckFailed("Attribute '" + A.getAsString() + - "' does not apply to functions!", - V); - return; - } } } @@ -1771,7 +1686,14 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, if (!Attrs.hasAttributes()) return; - verifyAttributeTypes(Attrs, /*IsFunction=*/false, V); + verifyAttributeTypes(Attrs, V); + + for (Attribute Attr : Attrs) + Assert(Attr.isStringAttribute() || + Attribute::canUseAsParamAttr(Attr.getKindAsEnum()), + "Attribute '" + Attr.getAsString() + + "' does not apply to parameters", + V); if (Attrs.hasAttribute(Attribute::ImmArg)) { Assert(Attrs.getNumAttributes() == 1, @@ -1836,10 +1758,14 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, V); AttrBuilder IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty); - Assert(!AttrBuilder(Attrs).overlaps(IncompatibleAttrs), - "Wrong types for attribute: " + - AttributeSet::get(Context, IncompatibleAttrs).getAsString(), - V); + for (Attribute Attr : Attrs) { + if (!Attr.isStringAttribute() && + IncompatibleAttrs.contains(Attr.getKindAsEnum())) { + CheckFailed("Attribute '" + Attr.getAsString() + + "' applied to incompatible type!", V); + return; + } + } if (PointerType *PTy = dyn_cast(Ty)) { if (Attrs.hasAttribute(Attribute::ByVal)) { @@ -1887,18 +1813,12 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, Assert(Attrs.getInAllocaType() == PTy->getElementType(), "Attribute 'inalloca' type does not match parameter!", V); } + + if (Attrs.hasAttribute(Attribute::ElementType)) { + Assert(Attrs.getElementType() == PTy->getElementType(), + "Attribute 'elementtype' type does not match parameter!", V); + } } - } else { - Assert(!Attrs.hasAttribute(Attribute::ByVal), - "Attribute 'byval' only applies to parameters with pointer type!", - V); - Assert(!Attrs.hasAttribute(Attribute::ByRef), - "Attribute 'byref' only applies to parameters with pointer type!", - V); - Assert(!Attrs.hasAttribute(Attribute::SwiftError), - "Attribute 'swifterror' only applies to parameters " - "with pointer type!", - V); } } @@ -1942,29 +1862,13 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, // Verify return value attributes. AttributeSet RetAttrs = Attrs.getRetAttributes(); - Assert((!RetAttrs.hasAttribute(Attribute::ByVal) && - !RetAttrs.hasAttribute(Attribute::Nest) && - !RetAttrs.hasAttribute(Attribute::StructRet) && - !RetAttrs.hasAttribute(Attribute::NoCapture) && - !RetAttrs.hasAttribute(Attribute::NoFree) && - !RetAttrs.hasAttribute(Attribute::Returned) && - !RetAttrs.hasAttribute(Attribute::InAlloca) && - !RetAttrs.hasAttribute(Attribute::Preallocated) && - !RetAttrs.hasAttribute(Attribute::ByRef) && - !RetAttrs.hasAttribute(Attribute::SwiftSelf) && - !RetAttrs.hasAttribute(Attribute::SwiftAsync) && - !RetAttrs.hasAttribute(Attribute::SwiftError)), - "Attributes 'byval', 'inalloca', 'preallocated', 'byref', " - "'nest', 'sret', 'nocapture', 'nofree', " - "'returned', 'swiftself', 'swiftasync', and 'swifterror'" - " do not apply to return values!", - V); - Assert((!RetAttrs.hasAttribute(Attribute::ReadOnly) && - !RetAttrs.hasAttribute(Attribute::WriteOnly) && - !RetAttrs.hasAttribute(Attribute::ReadNone)), - "Attribute '" + RetAttrs.getAsString() + - "' does not apply to function returns", - V); + for (Attribute RetAttr : RetAttrs) + Assert(RetAttr.isStringAttribute() || + Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()), + "Attribute '" + RetAttr.getAsString() + + "' does not apply to function return values", + V); + verifyParameterAttrs(RetAttrs, FT->getReturnType(), V); // Verify parameter attributes. @@ -1975,6 +1879,8 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, if (!IsIntrinsic) { Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg), "immarg attribute only applies to intrinsics",V); + Assert(!ArgAttrs.hasAttribute(Attribute::ElementType), + "Attribute 'elementtype' can only be applied to intrinsics.", V); } verifyParameterAttrs(ArgAttrs, Ty, V); @@ -2025,7 +1931,13 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, if (!Attrs.hasAttributes(AttributeList::FunctionIndex)) return; - verifyAttributeTypes(Attrs.getFnAttributes(), /*IsFunction=*/true, V); + verifyAttributeTypes(Attrs.getFnAttributes(), V); + for (Attribute FnAttr : Attrs.getFnAttributes()) + Assert(FnAttr.isStringAttribute() || + Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()), + "Attribute '" + FnAttr.getAsString() + + "' does not apply to functions!", + V); Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) && Attrs.hasFnAttribute(Attribute::ReadOnly)), @@ -2414,11 +2326,10 @@ void Verifier::visitFunction(const Function &F) { Assert(verifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); - bool isLLVMdotName = F.getName().size() >= 5 && - F.getName().substr(0, 5) == "llvm."; + bool IsIntrinsic = F.isIntrinsic(); // Check function attributes. - verifyFunctionAttrs(FT, Attrs, &F, isLLVMdotName); + verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic); // On function declarations/definitions, we do not support the builtin // attribute. We do not check this in VerifyFunctionAttrs since that is @@ -2426,6 +2337,9 @@ void Verifier::visitFunction(const Function &F) { Assert(!Attrs.hasFnAttribute(Attribute::Builtin), "Attribute 'builtin' can only be applied to a callsite.", &F); + Assert(!Attrs.hasAttrSomewhere(Attribute::ElementType), + "Attribute 'elementtype' can only be applied to a callsite.", &F); + // Check that this function meets the restrictions on this calling convention. // Sometimes varargs is used for perfectly forwarding thunks, so some of these // restrictions can be lifted. @@ -2492,7 +2406,7 @@ void Verifier::visitFunction(const Function &F) { FT->getParamType(i)); Assert(Arg.getType()->isFirstClassType(), "Function arguments must have first-class types!", &Arg); - if (!isLLVMdotName) { + if (!IsIntrinsic) { Assert(!Arg.getType()->isMetadataTy(), "Function takes metadata but isn't an intrinsic", &Arg, &F); Assert(!Arg.getType()->isTokenTy(), @@ -2508,7 +2422,7 @@ void Verifier::visitFunction(const Function &F) { ++i; } - if (!isLLVMdotName) { + if (!IsIntrinsic) { Assert(!F.getReturnType()->isTokenTy(), "Function returns a token but isn't an intrinsic", &F); Assert(!F.getReturnType()->isX86_AMXTy(), @@ -2552,7 +2466,7 @@ void Verifier::visitFunction(const Function &F) { } else { // Verify that this function (which has a body) is not named "llvm.*". It // is not legal to define intrinsics. - Assert(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F); + Assert(!IsIntrinsic, "llvm intrinsics cannot be defined!", &F); // Check the entry node const BasicBlock *Entry = &F.getEntryBlock(); @@ -2607,7 +2521,7 @@ void Verifier::visitFunction(const Function &F) { // direct call/invokes, never having its "address taken". // Only do this if the module is materialized, otherwise we don't have all the // uses. - if (F.getIntrinsicID() && F.getParent()->isMaterialized()) { + if (F.isIntrinsic() && F.getParent()->isMaterialized()) { const User *U; if (F.hasAddressTaken(&U)) Assert(false, "Invalid user of intrinsic instruction!", U); @@ -3150,11 +3064,12 @@ void Verifier::visitCallBase(CallBase &Call) { Assert(verifyAttributeCount(Attrs, Call.arg_size()), "Attribute after last parameter!", Call); - bool IsIntrinsic = Call.getCalledFunction() && - Call.getCalledFunction()->getName().startswith("llvm."); - Function *Callee = dyn_cast(Call.getCalledOperand()->stripPointerCasts()); + bool IsIntrinsic = Callee && Callee->isIntrinsic(); + if (IsIntrinsic) + Assert(Callee->getValueType() == FTy, + "Intrinsic called with incompatible signature", Call); if (Attrs.hasFnAttribute(Attribute::Speculatable)) { // Don't allow speculatable on call sites, unless the underlying function @@ -4702,14 +4617,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { Assert(ArgCount <= 2, "to many arguments"); if (Kind == Attribute::None) break; - if (Attribute::doesAttrKindHaveArgument(Kind)) { + if (Attribute::isIntAttrKind(Kind)) { Assert(ArgCount == 2, "this attribute should have 2 arguments"); Assert(isa(Call.getOperand(Elem.Begin + 1)), "the second argument should be a constant integral value"); - } else if (isFuncOnlyAttr(Kind)) { - Assert((ArgCount) == 0, "this attribute has no argument"); - } else if (!isFuncOrArgAttr(Kind)) { + } else if (Attribute::canUseAsParamAttr(Kind)) { Assert((ArgCount) == 1, "this attribute should have one argument"); + } else if (Attribute::canUseAsFnAttr(Kind)) { + Assert((ArgCount) == 0, "this attribute has no argument"); } } break; @@ -5377,6 +5292,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { NoAliasScopeDecls.push_back(cast(&Call)); break; } + case Intrinsic::preserve_array_access_index: + case Intrinsic::preserve_struct_access_index: { + Type *ElemTy = Call.getAttributes().getParamElementType(0); + Assert(ElemTy, + "Intrinsic requires elementtype attribute on first argument.", + &Call); + break; + } }; } diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index e67a5b42dc4c0..7bc6f05859212 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/PseudoProbe.h" #include "llvm/IR/TypeFinder.h" #include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Support/Error.h" @@ -1207,6 +1208,10 @@ void IRLinker::linkNamedMDNodes() { // Don't link module flags here. Do them separately. if (&NMD == SrcModFlags) continue; + // Don't import pseudo probe descriptors here for thinLTO. They will be + // emitted by the originating module. + if (IsPerformingImport && NMD.getName() == PseudoProbeDescMetadataName) + continue; NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName()); // Add Src elements into Dest node. for (const MDNode *Op : NMD.operands()) diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp index 0006754acb86b..ae7afeb30099c 100644 --- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp @@ -22,6 +22,7 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() { IsLittleEndian = false; HasVisibilityOnlyWithLinkage = true; HasBasenameOnlyForFileDirective = false; + HasFourStringsDotFile = true; // For XCOFF, string constant consists of any number of characters enclosed in // "" (double quotation marks). diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index f6d877c519f87..72f4ee3f33beb 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -253,6 +253,8 @@ class MCAsmStreamer final : public MCStreamer { SMLoc Loc) override; void emitFileDirective(StringRef Filename) override; + void emitFileDirective(StringRef Filename, StringRef CompilerVerion, + StringRef TimeStamp, StringRef Description) override; Expected tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, @@ -1450,6 +1452,28 @@ void MCAsmStreamer::emitFileDirective(StringRef Filename) { EmitEOL(); } +void MCAsmStreamer::emitFileDirective(StringRef Filename, + StringRef CompilerVerion, + StringRef TimeStamp, + StringRef Description) { + assert(MAI->hasFourStringsDotFile()); + OS << "\t.file\t"; + PrintQuotedString(Filename, OS); + OS << ","; + if (!CompilerVerion.empty()) { + PrintQuotedString(CompilerVerion, OS); + } + if (!TimeStamp.empty()) { + OS << ","; + PrintQuotedString(TimeStamp, OS); + } + if (!Description.empty()) { + OS << ","; + PrintQuotedString(Description, OS); + } + EmitEOL(); +} + void MCAsmStreamer::printDwarfFileDirective( unsigned FileNo, StringRef Directory, StringRef Filename, Optional Checksum, Optional Source, diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 4dae2f41fc454..2865a2ad80a99 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -848,6 +848,14 @@ void MCObjectStreamer::emitFileDirective(StringRef Filename) { getAssembler().addFileName(Filename); } +void MCObjectStreamer::emitFileDirective(StringRef Filename, + StringRef CompilerVerion, + StringRef TimeStamp, + StringRef Description) { + getAssembler().addFileName(Filename); + // TODO: add additional info to integrated assembler. +} + void MCObjectStreamer::emitAddrsig() { getAssembler().getWriter().emitAddrsigSection(); } diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 3bc668e699cbc..45e6dfee4ca4b 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -258,9 +258,9 @@ class AsmParser : public MCAsmParser { return LTODiscardSymbols.contains(Name); } - bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, - unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl> &OpDecls, + bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, + unsigned &NumInputs, + SmallVectorImpl> &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, @@ -5927,8 +5927,8 @@ static int rewritesSort(const AsmRewrite *AsmRewriteA, } bool AsmParser::parseMSInlineAsm( - void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, - unsigned &NumInputs, SmallVectorImpl> &OpDecls, + std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, + SmallVectorImpl> &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp index a91623770116a..a5a48d4b1e9d8 100644 --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -514,9 +514,9 @@ class MasmParser : public MCAsmParser { bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override; - bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, - unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl> &OpDecls, + bool parseMSInlineAsm(std::string &AsmString, unsigned &NumOutputs, + unsigned &NumInputs, + SmallVectorImpl> &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, @@ -7257,8 +7257,8 @@ bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const { } bool MasmParser::parseMSInlineAsm( - void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, - unsigned &NumInputs, SmallVectorImpl> &OpDecls, + std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, + SmallVectorImpl> &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 2a1998fd9c4c9..fc7fb555f0b9f 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1147,6 +1147,9 @@ void MCStreamer::EndCOFFSymbolDef() { llvm_unreachable("this directive only supported on COFF targets"); } void MCStreamer::emitFileDirective(StringRef Filename) {} +void MCStreamer::emitFileDirective(StringRef Filename, StringRef CompilerVerion, + StringRef TimeStamp, StringRef Description) { +} void MCStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { llvm_unreachable("this directive only supported on COFF targets"); } diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index d86e692286bec..ab98a2dd2ac1f 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -312,12 +312,17 @@ static bool supportsARM(uint64_t Type) { } static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S, - uint64_t LocData, int64_t /*Addend*/) { + uint64_t LocData, int64_t Addend) { + // Support both RELA and REL relocations. The caller is responsible + // for supplying the correct values for LocData and Addend, i.e. + // Addend == 0 for REL and LocData == 0 for RELA. + assert((LocData == 0 || Addend == 0) && + "one of LocData and Addend must be 0"); switch (Type) { case ELF::R_ARM_ABS32: - return (S + LocData) & 0xFFFFFFFF; + return (S + LocData + Addend) & 0xFFFFFFFF; case ELF::R_ARM_REL32: - return (S + LocData - Offset) & 0xFFFFFFFF; + return (S + LocData + Addend - Offset) & 0xFFFFFFFF; } llvm_unreachable("Invalid relocation type"); } @@ -744,8 +749,13 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type; }; - if (GetRelSectionType() == ELF::SHT_RELA) + if (GetRelSectionType() == ELF::SHT_RELA) { Addend = getELFAddend(R); + // RISCV relocations use both LocData and Addend. + if (Obj->getArch() != Triple::riscv32 && + Obj->getArch() != Triple::riscv64) + LocData = 0; + } } return Resolver(R.getType(), R.getOffset(), S, LocData, Addend); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 49e8c6e6e5282..680353956c10e 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -286,7 +286,6 @@ PipelineTuningOptions::PipelineTuningOptions() { SLPVectorization = false; LoopUnrolling = true; ForgetAllSCEVInLoopUnroll = ForgetSCEVInLoopUnroll; - Coroutines = false; LicmMssaOptCap = SetLicmMssaOptCap; LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap; CallGraphProfile = true; @@ -652,8 +651,7 @@ PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level, FPM.addPass(InstCombinePass()); invokePeepholeEPCallbacks(FPM, Level); - if (PTO.Coroutines) - FPM.addPass(CoroElidePass()); + FPM.addPass(CoroElidePass()); for (auto &C : ScalarOptimizerLateEPCallbacks) C(FPM, Level); @@ -850,8 +848,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap), EnableMSSALoopDependency, /*UseBlockFrequencyInfo=*/true)); - if (PTO.Coroutines) - FPM.addPass(CoroElidePass()); + FPM.addPass(CoroElidePass()); for (auto &C : ScalarOptimizerLateEPCallbacks) C(FPM, Level); @@ -1030,8 +1027,7 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level, MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( buildFunctionSimplificationPipeline(Level, Phase))); - if (PTO.Coroutines) - MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); + MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); return MIWP; } @@ -1086,8 +1082,7 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, EarlyFPM.addPass(SimplifyCFGPass()); EarlyFPM.addPass(SROA()); EarlyFPM.addPass(EarlyCSEPass()); - if (PTO.Coroutines) - EarlyFPM.addPass(CoroEarlyPass()); + EarlyFPM.addPass(CoroEarlyPass()); if (Level == OptimizationLevel::O3) EarlyFPM.addPass(CallSiteSplittingPass()); @@ -1454,8 +1449,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, // resulted in single-entry-single-exit or empty blocks. Clean up the CFG. OptimizePM.addPass(SimplifyCFGPass()); - if (PTO.Coroutines) - OptimizePM.addPass(CoroCleanupPass()); + OptimizePM.addPass(CoroCleanupPass()); // Add the core optimizing pipeline. MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM))); @@ -1565,8 +1559,7 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) { // Module simplification splits coroutines, but does not fully clean up // coroutine intrinsics. To ensure ThinLTO optimization passes don't trip up // on these, we schedule the cleanup here. - if (PTO.Coroutines) - MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); + MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); if (PGOOpt && PGOOpt->PseudoProbeForProfiling) MPM.addPass(PseudoProbeUpdatePass()); @@ -1940,10 +1933,8 @@ ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, // which is just that always inlining occurs. Further, disable generating // lifetime intrinsics to avoid enabling further optimizations during // code generation. - // However, we need to insert lifetime intrinsics to avoid invalid access - // caused by multithreaded coroutines. MPM.addPass(AlwaysInlinerPass( - /*InsertLifetimeIntrinsics=*/PTO.Coroutines)); + /*InsertLifetimeIntrinsics=*/false)); if (PTO.MergeFunctions) MPM.addPass(MergeFunctionsPass()); @@ -1992,15 +1983,11 @@ ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - if (PTO.Coroutines) { - MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); - - CGSCCPassManager CGPM; - CGPM.addPass(CoroSplitPass()); - MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); - - MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); - } + MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); + CGSCCPassManager CGPM; + CGPM.addPass(CoroSplitPass()); + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); for (auto &C : OptimizerLastEPCallbacks) C(MPM, Level); @@ -2094,9 +2081,8 @@ auto parsePassParameters(ParametersParseCallableT &&Parser, StringRef Name, assert(false && "unable to strip pass name from parametrized pass specification"); } - if (Params.empty()) - return ParametersT{}; - if (!Params.consume_front("<") || !Params.consume_back(">")) { + if (!Params.empty() && + (!Params.consume_front("<") || !Params.consume_back(">"))) { assert(false && "invalid format for parametrized pass name"); } @@ -2237,15 +2223,17 @@ Expected parseLoopVectorizeOptions(StringRef Params) { return Opts; } -Expected parseLoopUnswitchOptions(StringRef Params) { - bool Result = false; +Expected> parseLoopUnswitchOptions(StringRef Params) { + std::pair Result = {false, true}; while (!Params.empty()) { StringRef ParamName; std::tie(ParamName, Params) = Params.split(';'); bool Enable = !ParamName.consume_front("no-"); if (ParamName == "nontrivial") { - Result = Enable; + Result.first = Enable; + } else if (ParamName == "trivial") { + Result.second = Enable; } else { return make_error( formatv("invalid LoopUnswitch pass parameter '{0}' ", ParamName) diff --git a/llvm/lib/Passes/PassBuilderBindings.cpp b/llvm/lib/Passes/PassBuilderBindings.cpp index d71239a858d70..bad1fab2ad794 100644 --- a/llvm/lib/Passes/PassBuilderBindings.cpp +++ b/llvm/lib/Passes/PassBuilderBindings.cpp @@ -118,11 +118,6 @@ void LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll( unwrap(Options)->PTO.ForgetAllSCEVInLoopUnroll = ForgetAllSCEVInLoopUnroll; } -void LLVMPassBuilderOptionsSetCoroutines(LLVMPassBuilderOptionsRef Options, - LLVMBool Coroutines) { - unwrap(Options)->PTO.Coroutines = Coroutines; -} - void LLVMPassBuilderOptionsSetLicmMssaOptCap(LLVMPassBuilderOptionsRef Options, unsigned LicmMssaOptCap) { unwrap(Options)->PTO.LicmMssaOptCap = LicmMssaOptCap; diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index d93577d4904c7..f44e302e3ea10 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -451,9 +451,9 @@ LOOP_PASS("loop-versioning-licm", LoopVersioningLICMPass()) #endif LOOP_PASS_WITH_PARAMS("simple-loop-unswitch", "SimpleLoopUnswitchPass", - [](bool NonTrivial) { - return SimpleLoopUnswitchPass(NonTrivial); + [](std::pair Params) { + return SimpleLoopUnswitchPass(Params.first, Params.second); }, parseLoopUnswitchOptions, - "no-nontrivial;nontrivial") + "nontrivial;no-nontrivial;trivial;no-trivial") #undef LOOP_PASS_WITH_PARAMS diff --git a/llvm/lib/Support/AArch64TargetParser.cpp b/llvm/lib/Support/AArch64TargetParser.cpp index 503a7bd49d153..2993892097e70 100644 --- a/llvm/lib/Support/AArch64TargetParser.cpp +++ b/llvm/lib/Support/AArch64TargetParser.cpp @@ -106,6 +106,12 @@ bool AArch64::getExtensionFeatures(uint64_t Extensions, Features.push_back("+pauth"); if (Extensions & AEK_FLAGM) Features.push_back("+flagm"); + if (Extensions & AArch64::AEK_SME) + Features.push_back("+sme"); + if (Extensions & AArch64::AEK_SMEF64) + Features.push_back("+sme-f64"); + if (Extensions & AArch64::AEK_SMEI64) + Features.push_back("+sme-i64"); return true; } diff --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp index 5aaf0a4e7c62e..f20521f2a2d47 100644 --- a/llvm/lib/Support/ARMBuildAttrs.cpp +++ b/llvm/lib/Support/ARMBuildAttrs.cpp @@ -63,6 +63,7 @@ static const TagNameItem tagData[] = { {ARMBuildAttrs::ABI_align_preserved, "Tag_ABI_align8_preserved"}, }; -const TagNameMap llvm::ARMBuildAttrs::ARMAttributeTags(tagData, - sizeof(tagData) / - sizeof(TagNameItem)); +constexpr TagNameMap ARMAttributeTags{tagData}; +const TagNameMap &llvm::ARMBuildAttrs::getARMAttributeTags() { + return ARMAttributeTags; +} diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp index 8cf7d5b1e57e2..4ae3ad4c24535 100644 --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -16,6 +16,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/CommandLine.h" + +#include "DebugOptions.h" + #include "llvm-c/Support.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" @@ -462,7 +465,7 @@ void Option::addCategory(OptionCategory &C) { // Maintain backward compatibility by replacing the default GeneralCategory // if it's still set. Otherwise, just add the new one. The GeneralCategory // must be explicitly added if you want multiple categories that include it. - if (&C != &GeneralCategory && Categories[0] == &GeneralCategory) + if (&C != &getGeneralCategory() && Categories[0] == &getGeneralCategory()) Categories[0] = &C; else if (!is_contained(Categories, &C)) Categories.push_back(&C); @@ -475,9 +478,6 @@ void Option::reset() { removeArgument(); } -// Initialise the general option category. -OptionCategory llvm::cl::GeneralCategory("General options"); - void OptionCategory::registerCategory() { GlobalParser->registerCategory(this); } @@ -1293,10 +1293,12 @@ bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver, /*MarkEOLs=*/false, /*RelativeNames=*/true); } +static void initCommonOptions(); bool cl::ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview, raw_ostream *Errs, const char *EnvVar, bool LongOptionsUseDoubleDash) { + initCommonOptions(); SmallVector NewArgv; BumpPtrAllocator A; StringSaver Saver(A); @@ -1937,7 +1939,9 @@ unsigned generic_parser_base::findOption(StringRef Name) { static StringRef EqValue = "="; static StringRef EmptyOption = ""; static StringRef OptionPrefix = " ="; -static size_t OptionPrefixesSize = OptionPrefix.size() + ArgHelpPrefix.size(); +static size_t getOptionPrefixesSize() { + return OptionPrefix.size() + ArgHelpPrefix.size(); +} static bool shouldPrintOption(StringRef Name, StringRef Description, const Option &O) { @@ -1955,7 +1959,7 @@ size_t generic_parser_base::getOptionWidth(const Option &O) const { if (!shouldPrintOption(Name, getDescription(i), O)) continue; size_t NameSize = Name.empty() ? EmptyOption.size() : Name.size(); - Size = std::max(Size, NameSize + OptionPrefixesSize); + Size = std::max(Size, NameSize + getOptionPrefixesSize()); } return Size; } else { @@ -1994,7 +1998,7 @@ void generic_parser_base::printOptionInfo(const Option &O, StringRef Description = getDescription(i); if (!shouldPrintOption(OptionName, Description, O)) continue; - size_t FirstLineIndent = OptionName.size() + OptionPrefixesSize; + size_t FirstLineIndent = OptionName.size() + getOptionPrefixesSize(); outs() << OptionPrefix << OptionName; if (OptionName.empty()) { outs() << EmptyOption; @@ -2374,105 +2378,6 @@ class HelpPrinterWrapper { } // End anonymous namespace -// Declare the four HelpPrinter instances that are used to print out help, or -// help-hidden as an uncategorized list or in categories. -static HelpPrinter UncategorizedNormalPrinter(false); -static HelpPrinter UncategorizedHiddenPrinter(true); -static CategorizedHelpPrinter CategorizedNormalPrinter(false); -static CategorizedHelpPrinter CategorizedHiddenPrinter(true); - -// Declare HelpPrinter wrappers that will decide whether or not to invoke -// a categorizing help printer -static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter, - CategorizedNormalPrinter); -static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter, - CategorizedHiddenPrinter); - -// Define a category for generic options that all tools should have. -static cl::OptionCategory GenericCategory("Generic Options"); - -// Define uncategorized help printers. -// --help-list is hidden by default because if Option categories are being used -// then --help behaves the same as --help-list. -static cl::opt> HLOp( - "help-list", - cl::desc("Display list of available options (--help-list-hidden for more)"), - cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed, - cl::cat(GenericCategory), cl::sub(*AllSubCommands)); - -static cl::opt> - HLHOp("help-list-hidden", cl::desc("Display list of all available options"), - cl::location(UncategorizedHiddenPrinter), cl::Hidden, - cl::ValueDisallowed, cl::cat(GenericCategory), - cl::sub(*AllSubCommands)); - -// Define uncategorized/categorized help printers. These printers change their -// behaviour at runtime depending on whether one or more Option categories have -// been declared. -static cl::opt> - HOp("help", cl::desc("Display available options (--help-hidden for more)"), - cl::location(WrappedNormalPrinter), cl::ValueDisallowed, - cl::cat(GenericCategory), cl::sub(*AllSubCommands)); - -static cl::alias HOpA("h", cl::desc("Alias for --help"), cl::aliasopt(HOp), - cl::DefaultOption); - -static cl::opt> - HHOp("help-hidden", cl::desc("Display all available options"), - cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed, - cl::cat(GenericCategory), cl::sub(*AllSubCommands)); - -static cl::opt PrintOptions( - "print-options", - cl::desc("Print non-default options after command line parsing"), - cl::Hidden, cl::init(false), cl::cat(GenericCategory), - cl::sub(*AllSubCommands)); - -static cl::opt PrintAllOptions( - "print-all-options", - cl::desc("Print all option values after command line parsing"), cl::Hidden, - cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands)); - -void HelpPrinterWrapper::operator=(bool Value) { - if (!Value) - return; - - // Decide which printer to invoke. If more than one option category is - // registered then it is useful to show the categorized help instead of - // uncategorized help. - if (GlobalParser->RegisteredOptionCategories.size() > 1) { - // unhide --help-list option so user can have uncategorized output if they - // want it. - HLOp.setHiddenFlag(NotHidden); - - CategorizedPrinter = true; // Invoke categorized printer - } else - UncategorizedPrinter = true; // Invoke uncategorized printer -} - -// Print the value of each option. -void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } - -void CommandLineParser::printOptionValues() { - if (!PrintOptions && !PrintAllOptions) - return; - - SmallVector, 128> Opts; - sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true); - - // Compute the maximum argument length... - size_t MaxArgLen = 0; - for (size_t i = 0, e = Opts.size(); i != e; ++i) - MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); - - for (size_t i = 0, e = Opts.size(); i != e; ++i) - Opts[i].second->printOptionValue(MaxArgLen, PrintAllOptions); -} - -static VersionPrinterTy OverrideVersionPrinter = nullptr; - -static std::vector *ExtraVersionPrinters = nullptr; - #if defined(__GNUC__) // GCC and GCC-compatible compilers define __OPTIMIZE__ when optimizations are // enabled. @@ -2528,59 +2433,203 @@ class VersionPrinter { #endif OS << '\n'; } - void operator=(bool OptionWasSpecified) { - if (!OptionWasSpecified) - return; + void operator=(bool OptionWasSpecified); +}; - if (OverrideVersionPrinter != nullptr) { - OverrideVersionPrinter(outs()); - exit(0); - } - print(); - - // Iterate over any registered extra printers and call them to add further - // information. - if (ExtraVersionPrinters != nullptr) { - outs() << '\n'; - for (const auto &I : *ExtraVersionPrinters) - I(outs()); - } +struct CommandLineCommonOptions { + // Declare the four HelpPrinter instances that are used to print out help, or + // help-hidden as an uncategorized list or in categories. + HelpPrinter UncategorizedNormalPrinter{false}; + HelpPrinter UncategorizedHiddenPrinter{true}; + CategorizedHelpPrinter CategorizedNormalPrinter{false}; + CategorizedHelpPrinter CategorizedHiddenPrinter{true}; + // Declare HelpPrinter wrappers that will decide whether or not to invoke + // a categorizing help printer + HelpPrinterWrapper WrappedNormalPrinter{UncategorizedNormalPrinter, + CategorizedNormalPrinter}; + HelpPrinterWrapper WrappedHiddenPrinter{UncategorizedHiddenPrinter, + CategorizedHiddenPrinter}; + // Define a category for generic options that all tools should have. + cl::OptionCategory GenericCategory{"Generic Options"}; + + // Define uncategorized help printers. + // --help-list is hidden by default because if Option categories are being + // used then --help behaves the same as --help-list. + cl::opt> HLOp{ + "help-list", + cl::desc( + "Display list of available options (--help-list-hidden for more)"), + cl::location(UncategorizedNormalPrinter), + cl::Hidden, + cl::ValueDisallowed, + cl::cat(GenericCategory), + cl::sub(*AllSubCommands)}; + + cl::opt> HLHOp{ + "help-list-hidden", + cl::desc("Display list of all available options"), + cl::location(UncategorizedHiddenPrinter), + cl::Hidden, + cl::ValueDisallowed, + cl::cat(GenericCategory), + cl::sub(*AllSubCommands)}; + + // Define uncategorized/categorized help printers. These printers change their + // behaviour at runtime depending on whether one or more Option categories + // have been declared. + cl::opt> HOp{ + "help", + cl::desc("Display available options (--help-hidden for more)"), + cl::location(WrappedNormalPrinter), + cl::ValueDisallowed, + cl::cat(GenericCategory), + cl::sub(*AllSubCommands)}; + + cl::alias HOpA{"h", cl::desc("Alias for --help"), cl::aliasopt(HOp), + cl::DefaultOption}; + + cl::opt> HHOp{ + "help-hidden", + cl::desc("Display all available options"), + cl::location(WrappedHiddenPrinter), + cl::Hidden, + cl::ValueDisallowed, + cl::cat(GenericCategory), + cl::sub(*AllSubCommands)}; + + cl::opt PrintOptions{ + "print-options", + cl::desc("Print non-default options after command line parsing"), + cl::Hidden, + cl::init(false), + cl::cat(GenericCategory), + cl::sub(*AllSubCommands)}; + + cl::opt PrintAllOptions{ + "print-all-options", + cl::desc("Print all option values after command line parsing"), + cl::Hidden, + cl::init(false), + cl::cat(GenericCategory), + cl::sub(*AllSubCommands)}; + + VersionPrinterTy OverrideVersionPrinter = nullptr; + + std::vector ExtraVersionPrinters; + + // Define the --version option that prints out the LLVM version for the tool + VersionPrinter VersionPrinterInstance; + + cl::opt> VersOp{ + "version", cl::desc("Display the version of this program"), + cl::location(VersionPrinterInstance), cl::ValueDisallowed, + cl::cat(GenericCategory)}; +}; +} // End anonymous namespace + +// Lazy-initialized global instance of options controlling the command-line +// parser and general handling. +static ManagedStatic CommonOptions; +static void initCommonOptions() { + *CommonOptions; + initDebugCounterOptions(); + initGraphWriterOptions(); + initSignalsOptions(); + initStatisticOptions(); + initTimerOptions(); + initTypeSizeOptions(); + initWithColorOptions(); + initDebugOptions(); + initRandomSeedOptions(); +} + +OptionCategory &cl::getGeneralCategory() { + // Initialise the general option category. + static OptionCategory GeneralCategory{"General options"}; + return GeneralCategory; +} + +void VersionPrinter::operator=(bool OptionWasSpecified) { + if (!OptionWasSpecified) + return; + + if (CommonOptions->OverrideVersionPrinter != nullptr) { + CommonOptions->OverrideVersionPrinter(outs()); exit(0); } -}; -} // End anonymous namespace + print(); + + // Iterate over any registered extra printers and call them to add further + // information. + if (!CommonOptions->ExtraVersionPrinters.empty()) { + outs() << '\n'; + for (const auto &I : CommonOptions->ExtraVersionPrinters) + I(outs()); + } + + exit(0); +} + +void HelpPrinterWrapper::operator=(bool Value) { + if (!Value) + return; + + // Decide which printer to invoke. If more than one option category is + // registered then it is useful to show the categorized help instead of + // uncategorized help. + if (GlobalParser->RegisteredOptionCategories.size() > 1) { + // unhide --help-list option so user can have uncategorized output if they + // want it. + CommonOptions->HLOp.setHiddenFlag(NotHidden); -// Define the --version option that prints out the LLVM version for the tool -static VersionPrinter VersionPrinterInstance; + CategorizedPrinter = true; // Invoke categorized printer + } else + UncategorizedPrinter = true; // Invoke uncategorized printer +} + +// Print the value of each option. +void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } + +void CommandLineParser::printOptionValues() { + if (!CommonOptions->PrintOptions && !CommonOptions->PrintAllOptions) + return; -static cl::opt> - VersOp("version", cl::desc("Display the version of this program"), - cl::location(VersionPrinterInstance), cl::ValueDisallowed, - cl::cat(GenericCategory)); + SmallVector, 128> Opts; + sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true); + + // Compute the maximum argument length... + size_t MaxArgLen = 0; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); + + for (size_t i = 0, e = Opts.size(); i != e; ++i) + Opts[i].second->printOptionValue(MaxArgLen, CommonOptions->PrintAllOptions); +} // Utility function for printing the help message. void cl::PrintHelpMessage(bool Hidden, bool Categorized) { if (!Hidden && !Categorized) - UncategorizedNormalPrinter.printHelp(); + CommonOptions->UncategorizedNormalPrinter.printHelp(); else if (!Hidden && Categorized) - CategorizedNormalPrinter.printHelp(); + CommonOptions->CategorizedNormalPrinter.printHelp(); else if (Hidden && !Categorized) - UncategorizedHiddenPrinter.printHelp(); + CommonOptions->UncategorizedHiddenPrinter.printHelp(); else - CategorizedHiddenPrinter.printHelp(); + CommonOptions->CategorizedHiddenPrinter.printHelp(); } /// Utility function for printing version number. -void cl::PrintVersionMessage() { VersionPrinterInstance.print(); } +void cl::PrintVersionMessage() { + CommonOptions->VersionPrinterInstance.print(); +} -void cl::SetVersionPrinter(VersionPrinterTy func) { OverrideVersionPrinter = func; } +void cl::SetVersionPrinter(VersionPrinterTy func) { + CommonOptions->OverrideVersionPrinter = func; +} void cl::AddExtraVersionPrinter(VersionPrinterTy func) { - if (!ExtraVersionPrinters) - ExtraVersionPrinters = new std::vector; - - ExtraVersionPrinters->push_back(func); + CommonOptions->ExtraVersionPrinters.push_back(func); } StringMap